EVSL  1.1.0
EigenValues Slicing Library
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros
evsl_pardiso.c
Go to the documentation of this file.
1 #ifdef USE_MKL
2 
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include "def.h"
7 #include "struct.h"
8 #include "internal_proto.h"
9 #include "evsl_direct.h"
10 #include "mkl.h"
11 #include "mkl_pardiso.h"
12 #include "mkl_types.h"
13 
20 typedef struct _BSolDataDirect {
21  /* Internal solver memory pointer pt, */
22  /* 32-bit: int pt[64]; 64-bit: long int pt[64] */
23  /* or void *pt[64] should be OK on both architectures */
24  void *pt[64];
25  /* Pardiso control parameters. */
26  MKL_INT iparm[64];
27  /* upper triangular matrix */
28  csrMat U;
30 
31 
32 typedef struct _ASBSolDataDirect {
33  /* Internal solver memory pointer pt, */
34  /* 32-bit: int pt[64]; 64-bit: long int pt[64] */
35  /* or void *pt[64] should be OK on both architectures */
36  void *pt[64];
37  /* Pardiso control parameters. */
38  MKL_INT iparm[64];
39  /* upper triangular matrix */
40  MKL_INT n, *ia, *ja, maxfct, mnum;
41  MKL_Complex16 *a;
42  /* workspace for solve, of size n */
43  MKL_Complex16 *b, *x;
45 
51 int SetupBSolDirect(csrMat *B, void **data) {
52  double tms = evsl_timer();
53  BSolDataDirect *Bsol_data;
54  Malloc(Bsol_data, 1, BSolDataDirect);
55 
56  MKL_INT mtype = 2; /* Real SPD matrix */
57  /* Maximum number of factors with identical sparsity structure that
58  * must be kept in memory at the same time. In most applications this
59  * value is equal to 1. It is possible to store several different
60  * factorizations with the same nonzero structure at the same time in
61  * the internal data structure management of the solver.
62  * pardiso can process several matrices with an identical matrix sparsity
63  * pattern and it can store the factors of these matrices at the same
64  * time. Matrices with a different sparsity structure can be kept in
65  * memory with different memory address pointers pt.*/
66  MKL_INT maxfct = 1;
67  /* Indicates the actual matrix for the solution phase. With this scalar
68  * you can define which matrix to factorize. The value must be:
69  * 1 <= mnum <= maxfct */
70  MKL_INT mnum = 1;
71  /* Controls the execution of the solver. Usually it is a two- or
72  * three-digit integer. The first digit indicates the starting phase
73  * of execution and the second digit indicates the ending phase. */
74  MKL_INT phase;
75  /* Message level information. If msglvl = 0 then pardiso generates no
76  * output, if msglvl = 1 the solver prints statistical information
77  * to the screen */
78  MKL_INT msglvl = 0;
79  /* Initialize error flag */
80  MKL_INT error = 0;
81  /* Double dummy */
82  double ddum;
83  /* Integer dummy. */
84  MKL_INT idum;
85  /* Number of right hand sides. */
86  MKL_INT nrhs = 1;
87 
88  /* extract upper diag part of B */
89  csrMat *U = &Bsol_data->U;
90  triuCsr(B, U);
91 
92  MKL_INT n = U->nrows;
93  MKL_INT *ia = U->ia;
94  MKL_INT *ja = U->ja;
95  double *a = U->a;
96 
97  /* This function initializes Intel MKL PARDISO internal address pointer
98  * pt with zero values (as needed for the very first call of pardiso)
99  * and sets default iparm values in accordance with the matrix type. */
100 #if 1
101 
102  pardisoinit(Bsol_data->pt, &mtype, Bsol_data->iparm);
103 
104 #else
105  int i;
106  for ( i = 0; i < 64; i++ )
107  {
108  Bsol_data->iparm[i] = 0;
109  }
110  for ( i = 0; i < 64; i++ )
111  {
112  Bsol_data->pt[i] = 0;
113  }
114 
115  Bsol_data->iparm[0] = 1; /* No solver default */
116  Bsol_data->iparm[1] = 2; /* Fill-in reordering from METIS */
117  Bsol_data->iparm[3] = 0; /* No iterative-direct algorithm */
118  Bsol_data->iparm[4] = 0; /* No user fill-in reducing permutation */
119  Bsol_data->iparm[5] = 0; /* Write solution into x */
120  Bsol_data->iparm[6] = 0; /* Not in use */
121  Bsol_data->iparm[7] = 2; /* Max numbers of iterative refinement steps */
122  Bsol_data->iparm[8] = 0; /* Not in use */
123  Bsol_data->iparm[9] = 13; /* Perturb the pivot elements with 1E-13 */
124  Bsol_data->iparm[10] = 1; /* Use nonsymmetric permutation and scaling MPS */
125  Bsol_data->iparm[11] = 0; /* Not in use */
126  Bsol_data->iparm[12] = 0; /* Maximum weighted matching algorithm is switched-off (default for symmetric).
127  Try iparm[12] = 1 in case of inappropriate accuracy */
128  Bsol_data->iparm[13] = 0; /* Output: Number of perturbed pivots */
129  Bsol_data->iparm[14] = 0; /* Not in use */
130  Bsol_data->iparm[15] = 0; /* Not in use */
131  Bsol_data->iparm[16] = 0; /* Not in use */
132  Bsol_data->iparm[17] = -1; /* Output: Number of nonzeros in the factor LU */
133  Bsol_data->iparm[18] = -1; /* Output: Mflops for LU factorization */
134  Bsol_data->iparm[19] = 0; /* Output: Numbers of CG Iterations */
135 #endif
136 
137  /* Zero-based indexing of columns and rows.*/
138  Bsol_data->iparm[34] = 1;
139  /* Max numbers of iterative refinement steps.
140  * 0: The solver automatically performs two steps of iterative refinement
141  * when perturbed pivots are obtained during the numerical factorization.*/
142  Bsol_data->iparm[7] = 0;
143  /* Matrix checker */
144  Bsol_data->iparm[26] = 1;
145 
146  /* --------------------------------------------------------------- */
147  /* Reordering and Symbolic Factorization. This step also allocates */
148  /* all memory that is necessary for the factorization. */
149  /* --------------------------------------------------------------- */
150  phase = 11;
151  pardiso(Bsol_data->pt, &maxfct, &mnum, &mtype, &phase, &n, a, ia, ja,
152  &idum, &nrhs, Bsol_data->iparm, &msglvl, &ddum, &ddum, &error);
153 
154  if ( error != 0 )
155  {
156  printf ("\nERROR during symbolic factorization: %d", error);
157  exit (1);
158  }
159  /*
160  printf ("\nReordering completed ... ");
161  printf ("\nNumber of nonzeros in factors = %d", Bsol_data->iparm[17]);
162  printf ("\nNumber of factorization MFLOPS = %d", Bsol_data->iparm[18]);
163  */
164  /* --------------------------------------------------------------- */
165  /* Numerical factorization. */
166  /* --------------------------------------------------------------- */
167  phase = 22;
168  pardiso(Bsol_data->pt, &maxfct, &mnum, &mtype, &phase, &n, a, ia, ja,
169  &idum, &nrhs, Bsol_data->iparm, &msglvl, &ddum, &ddum, &error);
170 
171  if ( error != 0 )
172  {
173  printf ("\nERROR during numerical factorization: %d", error);
174  exit (2);
175  }
176  /*
177  printf ("\nFactorization completed ... ");
178  */
179 
180  *data = (void *) Bsol_data;
181 
182  double tme = evsl_timer();
183  evslstat.t_setBsv += tme - tms;
184 
185  return 0;
186 }
187 
191 void BSolDirect(double *b, double *x, void *data) {
192  BSolDataDirect *Bsol_data = (BSolDataDirect *) data;
193 
194  MKL_INT maxfct = 1;
195  MKL_INT mnum = 1;
196  MKL_INT mtype = 2; /* Real SPD matrix */
197  MKL_INT msglvl = 0;
198  MKL_INT error = 0;
199  /* Integer dummy. */
200  MKL_INT idum;
201  /* Number of right hand sides. */
202  MKL_INT nrhs = 1;
203 
204  csrMat *U = &Bsol_data->U;
205  MKL_INT n = U->nrows;
206  MKL_INT *ia = U->ia;
207  MKL_INT *ja = U->ja;
208  double *a = U->a;
209 
210  /* ------------------------------------------------------------- */
211  /* Back substitution and iterative refinement. */
212  /* ------------------------------------------------------------- */
213  /* 33: Solve, iterative refinement */
214  MKL_INT phase = 33;
215  pardiso(Bsol_data->pt, &maxfct, &mnum, &mtype, &phase, &n, a, ia, ja,
216  &idum, &nrhs, Bsol_data->iparm, &msglvl, b, x, &error);
217  if ( error != 0 )
218  {
219  printf ("\nERROR during solution: %d", error);
220  exit (3);
221  }
222 
223  /*
224  double *r;
225  Malloc(r, n, double);
226  char uplo = 'U';
227  mkl_cspblas_dcsrsymv(&uplo, &n, a, ia, ja, x, r);
228  double res = 0.0, res0 = 0.0;
229  int i;
230  for (i = 0; i < n; i++) {
231  res += (r[i] - b[i]) * (r[i] - b[i]);
232  res0 += b[i] * b[i];
233  }
234  res = sqrt (res) / sqrt (res0);
235  if (res > 1e-12) {
236  printf ("\nRelative residual = %e", res);
237  }
238  */
239  /*printf ("\nSolve completed ... ");*/
240 }
241 
245 void LTSolDirect(double *b, double *x, void *data) {
246  BSolDataDirect *Bsol_data = (BSolDataDirect *) data;
247 
248  MKL_INT maxfct = 1;
249  MKL_INT mnum = 1;
250  MKL_INT mtype = 2; /* Real SPD matrix */
251  MKL_INT msglvl = 0;
252  MKL_INT error = 0;
253  /* Integer dummy. */
254  MKL_INT idum;
255  /* Number of right hand sides. */
256  MKL_INT nrhs = 1;
257 
258  csrMat *U = &Bsol_data->U;
259  MKL_INT n = U->nrows;
260  MKL_INT *ia = U->ia;
261  MKL_INT *ja = U->ja;
262  double *a = U->a;
263 
264  /* 333: like phase=33, but only backward substitution */
265  MKL_INT phase = 333;
266  pardiso(Bsol_data->pt, &maxfct, &mnum, &mtype, &phase, &n, a, ia, ja,
267  &idum, &nrhs, Bsol_data->iparm, &msglvl, b, x, &error);
268  if ( error != 0 )
269  {
270  printf ("\nERROR during solution: %d", error);
271  exit (3);
272  }
273  /*printf ("\nSolve completed ... ");*/
274 }
275 
278 void FreeBSolDirectData(void *data) {
279  BSolDataDirect *Bsol_data = (BSolDataDirect *) data;
280 
281  MKL_INT maxfct = 1;
282  MKL_INT mnum = 1;
283  MKL_INT mtype = 2; /* Real SPD matrix */
284  MKL_INT msglvl = 0;
285  MKL_INT error = 0;
286  /* Double dummy */
287  double ddum;
288  /* Integer dummy. */
289  MKL_INT idum;
290  /* Number of right hand sides. */
291  MKL_INT nrhs = 1;
292 
293  csrMat *U = &Bsol_data->U;
294  MKL_INT n = U->nrows;
295  MKL_INT *ia = U->ia;
296  MKL_INT *ja = U->ja;
297 
298  /* -------------------------------------------------------------------- */
299  /* .. Termination and release of memory. */
300  /* -------------------------------------------------------------------- */
301  MKL_INT phase = -1; /* Release internal memory. */
302  pardiso(Bsol_data->pt, &maxfct, &mnum, &mtype, &phase, &n, &ddum, ia, ja,
303  &idum, &nrhs, Bsol_data->iparm, &msglvl, &ddum, &ddum, &error);
304 
305  if ( error != 0 )
306  {
307  printf ("\nERROR during termination: %d", error);
308  exit (3);
309  }
310  /*printf ("\nTermination completed ... ");*/
311 
312  free_csr(U);
313  free(data);
314 }
315 
329 int SetupASIGMABSolDirect(csrMat *A, csrMat *BB, int num,
330  complex double *zk, void **data) {
331  double tms = evsl_timer();
332  int i, j, nrow, ncol, nnzUB, nnzUC, *map;
333  csrMat *B, UC, eye, UA, UB;
334  /* the shifted matrix
335  * C = A - s * B */
336  MKL_INT *UCp, *UCi, n;
337  double *UCx;
338  /* complex values of C */
339  MKL_Complex16 *UCz;
340  ASBSolDataDirect *ASBdata, *ASBdata0;
341 
342  MKL_INT mtype = 6; /* Complex and symmetric matrix */
343  MKL_INT maxfct = num;
344  MKL_INT mnum;
345  MKL_INT phase;
346  MKL_INT msglvl = 0;
347  MKL_INT error = 0;
348  double ddum;
349  MKL_INT idum;
350  MKL_INT nrhs = 1;
351 
352  nrow = A->nrows;
353  ncol = A->ncols;
354 
355  if (BB) {
356  B = BB;
357  } else {
358  /* if B==NULL, B=I, standard e.v. prob */
359  speye(nrow, &eye);
360  B = &eye;
361  }
362 
363  /* upper triangular parts of A and B */
364  triuCsr(A, &UA);
365  triuCsr(B, &UB);
366 
367  /* nnz in the upper tirangular part of B */
368  nnzUB = UB.ia[nrow];
369  /* map from nnz in UB to nnz in UC, useful for multi-poles */
370  Malloc(map, nnzUB, int);
371 
372  /* NOTE: if the matrix entries need to be sorted.
373  * The matadd routine will guarantee this
374  * C = A + 0.0 * B
375  * This actually computes the pattern of A + B
376  * and also can guarantee C has sorted rows
377  * map is the mapping from nnzB to nnzC */
378  matadd(1.0, 0.0, &UA, &UB, &UC, NULL, map);
379 
380  /* arrays for C */
381  n = nrow;
382  UCp = UC.ia;
383  UCi = UC.ja;
384  UCx = UC.a;
385  nnzUC = UCp[nrow];
386 
387  /* pole loop
388  * for each pole we shift with B and factorize */
389  for (i = 0; i < num; i++) {
390  /* data for pole i */
391  Malloc(ASBdata, 1, ASBSolDataDirect);
392 
393  /* the complex shift for pole i */
394  double zkr = creal(zk[i]);
395  double zkc = cimag(zk[i]);
396 
397  Malloc(UCz, nnzUC, MKL_Complex16);
398  /* make the values of UC complex */
399  for (j = 0; j < nnzUC; j++) {
400  UCz[j].real = UCx[j];
401  UCz[j].imag = 0.0;
402  }
403 
404  /* shift with UB */
405  for (j = 0; j < nnzUB; j++) {
406  int p = map[j];
407  double v = UB.a[j];
408  CHKERR(UCi[p] != UB.ja[j]);
409  CHKERR(!(p >= 0 && p < nnzUC));
410  UCz[p].real -= zkr * v;
411  UCz[p].imag -= zkc * v;
412  }
413 
414  mnum = i + 1;
415  /* only do init and symbolic factorization once */
416  if (i == 0) {
417 
418  pardisoinit(ASBdata->pt, &mtype, ASBdata->iparm);
419 
420  /* Zero-based indexing of columns and rows.*/
421  ASBdata->iparm[34] = 1;
422  /* Max numbers of iterative refinement steps.
423  * 0: The solver automatically performs two steps of iterative refinement
424  * when perturbed pivots are obtained during the numerical factorization.*/
425  ASBdata->iparm[7] = 0;
426  /* Matrix checker */
427  ASBdata->iparm[26] = 1;
428 
429  /* --------------------------------------------------------------- */
430  /* Reordering and Symbolic Factorization. This step also allocates */
431  /* all memory that is necessary for the factorization. */
432  /* --------------------------------------------------------------- */
433  phase = 11;
434  pardiso(ASBdata->pt, &maxfct, &mnum, &mtype, &phase, &n, UCz, UCp, UCi,
435  &idum, &nrhs, ASBdata->iparm, &msglvl, &ddum, &ddum, &error);
436 
437  if ( error != 0 )
438  {
439  printf ("\nERROR during symbolic factorization: %d", error);
440  exit (1);
441  }
442 
443  ASBdata0 = ASBdata;
444  } else {
445  /* use the pointer and parm for pole-0 */
446  memcpy(ASBdata->pt, ASBdata0->pt, 64*sizeof(void*));
447  memcpy(ASBdata->iparm, ASBdata0->iparm, 64*sizeof(MKL_INT));
448  }
449 
450  /* --------------------------------------------------------------- */
451  /* Numerical factorization. */
452  /* --------------------------------------------------------------- */
453  phase = 22;
454  pardiso(ASBdata->pt, &maxfct, &mnum, &mtype, &phase, &n, UCz, UCp, UCi,
455  &idum, &nrhs, ASBdata->iparm, &msglvl, &ddum, &ddum, &error);
456 
457  if ( error != 0 )
458  {
459  printf ("\nERROR during numerical factorization: %d", error);
460  exit (2);
461  }
462 
463  /* save the data */
464  ASBdata->maxfct = maxfct;
465  ASBdata->mnum = mnum;
466  ASBdata->n = n;
467  ASBdata->ia = UCp;
468  ASBdata->ja = UCi;
469  ASBdata->a = UCz;
470  Malloc(ASBdata->b, nrow, MKL_Complex16);
471  Malloc(ASBdata->x, nrow, MKL_Complex16);
472  data[i] = ASBdata;
473  } /* for (i=...)*/
474 
475  free(map);
476  free(UC.a);
477  free_csr(&UA);
478  free_csr(&UB);
479  if (!BB) {
480  free_csr(&eye);
481  }
482 
483  double tme = evsl_timer();
484  evslstat.t_setASigBsv += tme - tms;
485 
486  return 0;
487 }
488 
501 void ASIGMABSolDirect(int n, double *br, double *bi, double *xr,
502  double *xz, void *data) {
503 
504  ASBSolDataDirect *sol_data = (ASBSolDataDirect *) data;
505  int i;
506  MKL_INT mtype = 6; /* Complex and symmetric matrix */
507  MKL_INT msglvl = 0;
508  MKL_INT error = 0;
509  /* Integer dummy. */
510  MKL_INT idum;
511  /* Number of right hand sides. */
512  MKL_INT nrhs = 1;
513 
514  CHKERR(n != sol_data->n);
515  MKL_Complex16 *b = sol_data->b;
516  MKL_Complex16 *x = sol_data->x;
517 
518  /* copy rhs */
519  for (i = 0; i < n; i++) {
520  b[i].real = br[i];
521  b[i].imag = bi[i];
522  }
523 
524  /* ------------------------------------------------------------- */
525  /* Back substitution and iterative refinement. */
526  /* ------------------------------------------------------------- */
527  /* 33: Solve, iterative refinement */
528  MKL_INT phase = 33;
529  pardiso(sol_data->pt, &sol_data->maxfct, &sol_data->mnum, &mtype, &phase,
530  &sol_data->n, sol_data->a, sol_data->ia, sol_data->ja,
531  &idum, &nrhs, sol_data->iparm, &msglvl, b, x, &error);
532 
533  if ( error != 0 )
534  {
535  printf ("\nERROR during solution: %d", error);
536  exit (3);
537  }
538 
539  /*
540  MKL_Complex16 *r;
541  Malloc(r, n, MKL_Complex16);
542  char uplo = 'U';
543  mkl_cspblas_zcsrsymv(&uplo, &sol_data->n, sol_data->a, sol_data->ia, sol_data->ja, x, r);
544  double res = 0.0, res0 = 0.0;
545  for (i = 0; i < n; i++) {
546  res += (r[i].real - b[i].real) * (r[i].real - b[i].real);
547  res += (r[i].imag - b[i].imag) * (r[i].imag - b[i].imag);
548  res0 += b[i].real * b[i].real;
549  res0 += b[i].imag * b[i].imag;
550  }
551  res = sqrt (res) / sqrt (res0);
552  //if (res > 1e-12) {
553  printf ("\nRelative residual = %e\n", res);
554  //}
555 
556  exit(0);
557  */
558 
559  /* copy sol */
560  for (i = 0; i < n; i++) {
561  xr[i] = x[i].real;
562  xz[i] = x[i].imag;
563  }
564 }
565 
569 void FreeASIGMABSolDirect(int num, void **data) {
570  int i;
571  MKL_INT mtype = 6; /* Complex and symmetric matrix */
572  MKL_INT msglvl = 0;
573  MKL_INT phase = -1; /* Release internal memory. */
574  MKL_INT error = 0;
575  /* Integer dummy. */
576  MKL_INT idum;
577  /* Double dummy */
578  double ddum;
579  MKL_INT nrhs = 1;
580 
581  for (i=0; i<num; i++) {
582 
583  ASBSolDataDirect *sol_data = (ASBSolDataDirect *) data[i];
584 
585  if (i == 0) {
586  /* ----------------------------------------------------------------- */
587  /* Termination and release of memory. */
588  /* ----------------------------------------------------------------- */
589  pardiso(sol_data->pt, &sol_data->maxfct, &sol_data->mnum, &mtype, &phase,
590  &sol_data->n, sol_data->a, sol_data->ia, sol_data->ja,
591  &idum, &nrhs, sol_data->iparm, &msglvl, &ddum, &ddum, &error);
592 
593  if ( error != 0 )
594  {
595  printf ("\nERROR during termination: %d", error);
596  exit (3);
597  }
598 
599  free(sol_data->ia);
600  free(sol_data->ja);
601  }
602 
603  free(sol_data->a);
604  free(sol_data->b);
605  free(sol_data->x);
606  free(sol_data);
607  }
608 }
609 
610 #endif
611 
void triuCsr(csrMat *A, csrMat *U)
Definition: spmat.c:424
void ASIGMABSolDirect(int n, double *br, double *bi, double *xr, double *xz, void *data)
complex linear solver routine passed to evsl
defs in EVSL
int SetupASIGMABSolDirect(csrMat *A, csrMat *BB, int num, complex double *zk, void **data)
setup CXsparse solver for A - SIGMA B
int ncols
Definition: struct.h:32
#define CHKERR(ierr)
Definition: def.h:19
int SetupBSolDirect(csrMat *B, void **data)
Setup the B-sol by computing the Cholesky factorization of B.
Definition: evsl_cxsparse.c:57
void FreeASIGMABSolDirect(int num, void **data)
free the data needed by CXSparse
void FreeBSolDirectData(void *data)
Free solver data.
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...
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
evslStat evslstat
global statistics of EVSL
Definition: evsl.c:21
struct _ASBSolDataDirect ASBSolDataDirect
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 * ia
Definition: struct.h:32
void LTSolDirect(double *b, double *x, void *data)
Solver function of L^{T} x = L^{-T}*b.
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
int * ja
Definition: struct.h:32
struct _BSolDataDirect BSolDataDirect
cs_complex_t * b
Definition: evsl_cxsparse.c:34
double t_setASigBsv
Definition: struct.h:199
void BSolDirect(double *b, double *x, void *data)
Solver function of B.
Definitions used for direct solver interface.
int nrows
Definition: struct.h:32
cs_complex_t * x
Definition: evsl_cxsparse.c:34
double evsl_timer()
evsl timer for mac
Definition: mactime.c:14