Subversion Repositories slepc-dev

Rev

Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1187 slepc 1
 
2
/*                      
3
       This file implements a wrapper to the PRIMME library
1212 slepc 4
       Contributed by Eloy Romero
1187 slepc 5
*/
6
 
1201 slepc 7
#include "src/eps/epsimpl.h"    /*I "slepceps.h" I*/
1236 slepc 8
#include "src/st/stimpl.h"
1187 slepc 9
 
10
EXTERN_C_BEGIN
11
#include "primme.h"
12
EXTERN_C_END
13
 
14
typedef struct {
15
  primme_params primme;           /* param struc */
16
  primme_preset_method method;    /* primme method */
17
  Mat A;                          /* problem matrix */
1212 slepc 18
  Vec w;                          /* store reciprocal A diagonal */
1189 slepc 19
  Vec x,y;                        /* auxiliar vectors */
1187 slepc 20
} EPS_PRIMME;
21
 
1239 slepc 22
const char *methodList[] = {
23
  "dynamic",
24
  "default_min_time",
25
  "default_min_matvecs",
26
  "arnoldi",
27
  "gd",
28
  "gd_plusk",
29
  "gd_olsen_plusk",
30
  "jd_olsen_plusk",
31
  "rqi",
32
  "jdqr",
33
  "jdqmr",
34
  "jdqmr_etol",
35
  "subspace_iteration",
36
  "lobpcg_orthobasis",
37
  "lobpcg_orthobasis_window"
38
};
39
const char *precondList[] = {"none", "diagonal"};
40
EPSPRIMMEMethod methodN[] = {
41
  EPSPRIMME_DYNAMIC,
42
  EPSPRIMME_DEFAULT_MIN_TIME,
43
  EPSPRIMME_DEFAULT_MIN_MATVECS,
44
  EPSPRIMME_ARNOLDI,
45
  EPSPRIMME_GD,
46
  EPSPRIMME_GD_PLUSK,
47
  EPSPRIMME_GD_OLSEN_PLUSK,
48
  EPSPRIMME_JD_OLSEN_PLUSK,
49
  EPSPRIMME_RQI,
50
  EPSPRIMME_JDQR,
51
  EPSPRIMME_JDQMR,
52
  EPSPRIMME_JDQMR_ETOL,
53
  EPSPRIMME_SUBSPACE_ITERATION,
54
  EPSPRIMME_LOBPCG_ORTHOBASIS,
55
  EPSPRIMME_LOBPCG_ORTHOBASIS_WINDOW
56
};
57
EPSPRIMMEPrecond precondN[] = {EPSPRIMME_NONE, EPSPRIMME_DIAGONAL};
1187 slepc 58
 
1239 slepc 59
static void multMatvec_PRIMME(void *in, void *out, int *blockSize, primme_params *primme);
60
static void applyPreconditioner_PRIMME(void *in, void *out, int *blockSize, struct primme_params *primme);
61
 
1201 slepc 62
static void par_GlobalSumDouble(void *sendBuf, void *recvBuf, int *count, primme_params *primme) {
1212 slepc 63
  MPI_Allreduce((double*)sendBuf, (double*)recvBuf, *count, MPI_DOUBLE, MPI_SUM, ((EPS)(primme->commInfo))->comm);
1187 slepc 64
}
65
 
66
#undef __FUNCT__  
67
#define __FUNCT__ "EPSSetUp_PRIMME"
68
PetscErrorCode EPSSetUp_PRIMME(EPS eps)
69
{
70
  PetscErrorCode ierr;
1204 slepc 71
  PetscInt       N, n;
72
  int            numProcs, procID;
1187 slepc 73
  EPS_PRIMME     *ops = (EPS_PRIMME *)eps->data;
74
  primme_params  *primme = &(((EPS_PRIMME *)eps->data)->primme);
75
 
76
  PetscFunctionBegin;
77
 
1212 slepc 78
  MPI_Comm_size(eps->comm,&numProcs);
79
  MPI_Comm_rank(eps->comm,&procID);
1187 slepc 80
 
1212 slepc 81
  /* Check some constraints and set some default values */
1187 slepc 82
  ierr = VecGetSize(eps->vec_initial,&N);CHKERRQ(ierr);
83
  ierr = VecGetLocalSize(eps->vec_initial,&n);CHKERRQ(ierr);
1207 slepc 84
 
1220 slepc 85
  if (!eps->max_it) eps->max_it = PetscMax(1000,N);
1189 slepc 86
  ierr = STGetOperators(eps->OP, &ops->A, PETSC_NULL);
1212 slepc 87
  if (!ops->A) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"The problem matrix has to be specified first");
1187 slepc 88
  if (!eps->ishermitian)
1189 slepc 89
    SETERRQ(PETSC_ERR_SUP,"PRIMME is only available for Hermitian problems");
90
  if (eps->isgeneralized)
91
    SETERRQ(PETSC_ERR_SUP,"PRIMME is not available for generalized problems");
1187 slepc 92
 
93
  /* Transfer SLEPc options to PRIMME options */
94
  primme->n = N;
95
  primme->nLocal = n;
96
  primme->numEvals = eps->nev;
1189 slepc 97
  primme->matrix = ops;
1212 slepc 98
  primme->commInfo = eps;
1187 slepc 99
  primme->initSize = 1;
100
  primme->maxMatvecs = eps->max_it;
101
  primme->eps = eps->tol;
102
  primme->numProcs = numProcs;
103
  primme->procID = procID;
104
 
105
  switch(eps->which) {
1203 slepc 106
    case EPS_LARGEST_REAL:
1187 slepc 107
      primme->target = primme_largest;
108
      break;
109
 
1203 slepc 110
    case EPS_SMALLEST_REAL:
1187 slepc 111
      primme->target = primme_smallest;
112
      break;
113
 
114
    default:
1203 slepc 115
      SETERRQ(PETSC_ERR_SUP,"PRIMME only allows EPS_LARGEST_REAL and EPS_SMALLEST_REAL for 'which' value");
1187 slepc 116
      break;  
117
  }
1207 slepc 118
 
1239 slepc 119
  if (primme_set_method(ops->method, primme) < 0)
120
    SETERRQ(PETSC_ERR_SUP,"PRIMME method not valid");
1187 slepc 121
 
1207 slepc 122
  /* If user sets ncv, maxBasisSize is modified. If not, ncv is set as maxBasisSize */
123
  if (eps->ncv) primme->maxBasisSize = eps->ncv;
124
  else eps->ncv = primme->maxBasisSize;
125
  if (eps->ncv < eps->nev+primme->maxBlockSize)  
126
    SETERRQ(PETSC_ERR_SUP,"PRIMME needs ncv >= nev+maxBlockSize");
127
 
1187 slepc 128
  /* Set workspace */
129
  ierr = EPSAllocateSolutionContiguous(eps);CHKERRQ(ierr);
1207 slepc 130
 
1187 slepc 131
  /* Copy vec_initial to V[0] vector */
132
  ierr = VecCopy(eps->vec_initial, eps->V[0]); CHKERRQ(ierr);
133
 
1207 slepc 134
  if (primme->correctionParams.precondition) {
1187 slepc 135
    /* Calc reciprocal A diagonal */
1212 slepc 136
    ierr = VecDuplicate(eps->vec_initial, &ops->w); CHKERRQ(ierr);
137
    ierr = MatGetDiagonal(ops->A, ops->w); CHKERRQ(ierr);
138
    ierr = VecReciprocal(ops->w); CHKERRQ(ierr);
1189 slepc 139
    primme->preconditioner = PETSC_NULL;
1187 slepc 140
    primme->applyPreconditioner = applyPreconditioner_PRIMME;
141
  }
142
 
1212 slepc 143
  /* Prepare auxiliary vectors */
1189 slepc 144
  ierr = VecCreateMPIWithArray(PETSC_COMM_WORLD,n,N,PETSC_NULL,&ops->x);CHKERRQ(ierr);
145
  ierr = VecCreateMPIWithArray(PETSC_COMM_WORLD,n,N,PETSC_NULL,&ops->y);CHKERRQ(ierr);
146
 
1187 slepc 147
  PetscFunctionReturn(0);
148
}
149
 
150
#undef __FUNCT__  
151
#define __FUNCT__ "EPSSolve_PRIMME"
152
PetscErrorCode EPSSolve_PRIMME(EPS eps)
153
{
154
  PetscErrorCode ierr;
1201 slepc 155
  EPS_PRIMME     *ops = (EPS_PRIMME *)eps->data;
156
  PetscScalar    *a;
1187 slepc 157
#ifdef PETSC_USE_COMPLEX
1201 slepc 158
  int            i;
159
  PetscReal      *evals;
1187 slepc 160
#endif
161
 
162
  PetscFunctionBegin;
163
 
164
  /* Call PRIMME solver */
165
  ierr = VecGetArray(eps->V[0], &a); CHKERRQ(ierr);
1239 slepc 166
 
1187 slepc 167
#ifndef PETSC_USE_COMPLEX
168
  ierr = dprimme(eps->eigr, a, eps->errest, &ops->primme);
169
#else
1212 slepc 170
  /* PRIMME returns real eigenvalues, but SLEPc works with complex ones */
1201 slepc 171
  ierr = PetscMalloc(eps->ncv*sizeof(PetscReal),&evals); CHKERRQ(ierr);
172
  ierr = zprimme(evals, (Complex_Z*)a, eps->errest, &ops->primme);
173
  for (i=0;i<eps->ncv;i++)
174
    eps->eigr[i] = evals[i];
175
  ierr = PetscFree(evals); CHKERRQ(ierr);
1187 slepc 176
#endif
177
  ierr = VecRestoreArray(eps->V[0], &a); CHKERRQ(ierr);
178
 
179
  switch(ierr) {
180
    case 0: /* Successful */
181
      break;
182
 
183
    case -1:
184
      SETERRQ(PETSC_ERR_SUP,"PRIMME: Failed to open output file");
185
      break;
186
 
187
    case -2:
188
      SETERRQ(PETSC_ERR_SUP,"PRIMME: Insufficient integer or real workspace allocated");
189
      break;
190
 
191
    case -3:
192
      SETERRQ(PETSC_ERR_SUP,"PRIMME: main_iter encountered a problem");
193
      break;
194
 
195
    default:
196
      SETERRQ(PETSC_ERR_SUP,"PRIMME: some parameters wrong configured");
197
      break;
198
  }
199
 
200
  eps->nconv = ops->primme.initSize>=0?ops->primme.initSize:0;
201
  eps->reason = EPS_CONVERGED_TOL;
1236 slepc 202
  eps->its = ops->primme.stats.numOuterIterations;
203
  eps->OP->applys = ops->primme.stats.numMatvecs;
1187 slepc 204
 
1201 slepc 205
#ifndef PETSC_USE_COMPLEX
1187 slepc 206
  ierr = PetscMemzero(eps->eigi, eps->nconv*sizeof(double)); CHKERRQ(ierr);
207
#endif
208
  PetscFunctionReturn(0);
209
}
210
 
1201 slepc 211
#undef __FUNCT__  
212
#define __FUNCT__ "multMatvec_PRIMME"
1239 slepc 213
static void multMatvec_PRIMME(void *in, void *out, int *blockSize, primme_params *primme)
1187 slepc 214
{
1212 slepc 215
  PetscErrorCode ierr;
216
  int            i, N = primme->n;
217
  EPS_PRIMME     *ops = (EPS_PRIMME *)primme->matrix;
218
  Vec            x = ops->x;
219
  Vec            y = ops->y;
220
  Mat            A = ops->A;
1187 slepc 221
 
1201 slepc 222
  PetscFunctionBegin;
1187 slepc 223
  for (i=0;i<*blockSize;i++) {
224
    /* build vectors using 'in' an 'out' workspace */
1201 slepc 225
    ierr = VecPlaceArray(x, (PetscScalar*)in+N*i ); CHKERRABORT(PETSC_COMM_WORLD,ierr);
226
    ierr = VecPlaceArray(y, (PetscScalar*)out+N*i ); CHKERRABORT(PETSC_COMM_WORLD,ierr);
1187 slepc 227
 
1201 slepc 228
    ierr = MatMult(A, x, y); CHKERRABORT(PETSC_COMM_WORLD,ierr);
1187 slepc 229
 
1201 slepc 230
    ierr = VecResetArray(x); CHKERRABORT(PETSC_COMM_WORLD,ierr);
231
    ierr = VecResetArray(y); CHKERRABORT(PETSC_COMM_WORLD,ierr);
1187 slepc 232
  }
1201 slepc 233
  PetscFunctionReturnVoid();
1187 slepc 234
}
235
 
1201 slepc 236
#undef __FUNCT__  
237
#define __FUNCT__ "applyPreconditioner_PRIMME"
1239 slepc 238
static void applyPreconditioner_PRIMME(void *in, void *out, int *blockSize, struct primme_params *primme)
1187 slepc 239
{
1212 slepc 240
  PetscErrorCode ierr;
241
  int            i, N = primme->n;
242
  EPS_PRIMME     *ops = (EPS_PRIMME *)primme->matrix;
243
  Vec            x = ops->x;
244
  Vec            y = ops->y;
245
  Vec            w = ops->w;
1189 slepc 246
 
1201 slepc 247
  PetscFunctionBegin;
1187 slepc 248
  for (i=0;i<*blockSize;i++) {
249
    /* build vectors using 'in' an 'out' workspace */
1201 slepc 250
    ierr = VecPlaceArray(x, (PetscScalar*)in+N*i ); CHKERRABORT(PETSC_COMM_WORLD,ierr);
251
    ierr = VecPlaceArray(y, (PetscScalar*)out+N*i ); CHKERRABORT(PETSC_COMM_WORLD,ierr);
1187 slepc 252
 
1212 slepc 253
    ierr = VecPointwiseMult(y, w, x); CHKERRABORT(PETSC_COMM_WORLD,ierr);
1187 slepc 254
 
1201 slepc 255
    ierr = VecResetArray(x); CHKERRABORT(PETSC_COMM_WORLD,ierr);
256
    ierr = VecResetArray(y); CHKERRABORT(PETSC_COMM_WORLD,ierr);
1187 slepc 257
  }
1201 slepc 258
  PetscFunctionReturnVoid();
1187 slepc 259
}
260
 
261
 
262
#undef __FUNCT__  
263
#define __FUNCT__ "EPSDestroy_PRIMME"
264
PetscErrorCode EPSDestroy_PRIMME(EPS eps)
265
{
266
  PetscErrorCode ierr;
267
  EPS_PRIMME    *ops = (EPS_PRIMME *)eps->data;
268
 
269
  PetscFunctionBegin;
270
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
271
 
1218 slepc 272
  if (ops->primme.correctionParams.precondition) {
273
    ierr = VecDestroy(ops->w);CHKERRQ(ierr);
274
  }
1187 slepc 275
  primme_Free(&ops->primme);
1189 slepc 276
  ierr = VecDestroy(ops->x);CHKERRQ(ierr);
277
  ierr = VecDestroy(ops->y);CHKERRQ(ierr);
1218 slepc 278
  ierr = PetscFree(eps->data);CHKERRQ(ierr);
1187 slepc 279
  ierr = EPSFreeSolutionContiguous(eps);CHKERRQ(ierr);
280
 
281
  PetscFunctionReturn(0);
282
}
283
 
284
#undef __FUNCT__  
285
#define __FUNCT__ "EPSView_PRIMME"
286
PetscErrorCode EPSView_PRIMME(EPS eps,PetscViewer viewer)
287
{
1212 slepc 288
  PetscErrorCode ierr;
289
  PetscTruth isascii;
1189 slepc 290
  primme_params *primme = &((EPS_PRIMME *)eps->data)->primme;
1239 slepc 291
  EPSPRIMMEMethod methodn;
292
  EPSPRIMMEPrecond precondn;
293
 
1187 slepc 294
  PetscFunctionBegin;
1189 slepc 295
  ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);CHKERRQ(ierr);
296
  if (!isascii) {
1201 slepc 297
    SETERRQ1(1,"Viewer type %s not supported for EPSPRIMME",((PetscObject)viewer)->type_name);
1189 slepc 298
  }
299
 
1207 slepc 300
  ierr = PetscViewerASCIIPrintf(viewer,"PRIMME solver block size: %d\n",primme->maxBlockSize);CHKERRQ(ierr);
1239 slepc 301
  ierr = EPSPRIMMEGetMethod(eps, &methodn);CHKERRQ(ierr);
302
  ierr = PetscViewerASCIIPrintf(viewer,"PRIMME solver method: %s\n", methodList[methodn]);CHKERRQ(ierr);
303
  ierr = EPSPRIMMEGetPrecond(eps, &precondn);CHKERRQ(ierr);
304
  ierr = PetscViewerASCIIPrintf(viewer,"PRIMME solver preconditioning: %s\n", precondList[precondn]);CHKERRQ(ierr);
1189 slepc 305
 
1187 slepc 306
  PetscFunctionReturn(0);
307
}
308
 
309
#undef __FUNCT__  
310
#define __FUNCT__ "EPSSetFromOptions_PRIMME"
311
PetscErrorCode EPSSetFromOptions_PRIMME(EPS eps)
312
{
313
  PetscErrorCode ierr;
314
  EPS_PRIMME    *ops = (EPS_PRIMME *)eps->data;
315
  PetscInt       op;
316
  PetscTruth     flg;
317
 
318
  PetscFunctionBegin;
319
 
320
  ierr = PetscOptionsHead("PRIMME options");CHKERRQ(ierr);
321
 
322
  op = ops->primme.maxBlockSize;
1203 slepc 323
  ierr = PetscOptionsInt("-eps_primme_block_size"," maximum block size","EPSPRIMMESetBlockSize",op,&op,&flg); CHKERRQ(ierr);
1187 slepc 324
  if (flg) {ierr = EPSPRIMMESetBlockSize(eps,op);CHKERRQ(ierr);}
325
  op = 0;
326
  ierr = PetscOptionsEList("-eps_primme_method","set method for solving the eigenproblem",
1239 slepc 327
                           "EPSPRIMMESetMethod",methodList,15,methodList[0],&op,&flg); CHKERRQ(ierr);
1187 slepc 328
  if (flg) {ierr = EPSPRIMMESetMethod(eps, methodN[op]);CHKERRQ(ierr);}
1212 slepc 329
  ierr = PetscOptionsEList("-eps_primme_precond","set preconditioner type",
1187 slepc 330
                           "EPSPRIMMESetPrecond",precondList,2,precondList[0],&op,&flg); CHKERRQ(ierr);
1190 slepc 331
  if (flg) {ierr = EPSPRIMMESetPrecond(eps, precondN[op]);CHKERRQ(ierr);}
1187 slepc 332
 
333
  ierr = PetscOptionsTail();CHKERRQ(ierr);
334
 
335
  PetscFunctionReturn(0);
336
}
337
 
338
EXTERN_C_BEGIN
339
#undef __FUNCT__  
340
#define __FUNCT__ "EPSPRIMMESetBlockSize_PRIMME"
341
PetscErrorCode EPSPRIMMESetBlockSize_PRIMME(EPS eps,int bs)
342
{
343
  EPS_PRIMME *ops = (EPS_PRIMME *) eps->data;
344
 
345
  PetscFunctionBegin;
346
 
347
  if (bs == PETSC_DEFAULT) ops->primme.maxBlockSize = 1;
348
  else if (bs <= 0) {
349
    SETERRQ(1, "PRIMME: wrong block size");
350
  } else ops->primme.maxBlockSize = bs;
351
 
352
  PetscFunctionReturn(0);
353
}
354
EXTERN_C_END
355
 
356
#undef __FUNCT__  
357
#define __FUNCT__ "EPSPRIMMESetBlockSize"
1201 slepc 358
/*@
1212 slepc 359
    EPSPRIMMESetBlockSize - The maximum block size the code will try to use.
360
    The user should set
1187 slepc 361
    this based on the architecture specifics of the target computer,
362
    as well as any a priori knowledge of multiplicities. The code does
363
    NOT require BlockSize > 1 to find multiple eigenvalues.  For some
364
    methods, keeping BlockSize = 1 yields the best overall performance.
365
 
366
   Collective on EPS
367
 
368
   Input Parameters:
369
+  eps - the eigenproblem solver context
370
-  bs - block size
371
 
372
   Options Database Key:
1212 slepc 373
.  -eps_primme_block_size - Sets the max allowed block size value
1187 slepc 374
 
1212 slepc 375
   Notes:
376
   If the block size is not set, the value established by primme_initialize
377
   is used.
1187 slepc 378
 
379
   Level: advanced
380
.seealso: EPSPRIMMEGetBlockSize()
381
@*/
382
PetscErrorCode EPSPRIMMESetBlockSize(EPS eps,int bs)
383
{
384
  PetscErrorCode ierr, (*f)(EPS,int);
385
 
386
  PetscFunctionBegin;
387
 
388
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
389
  ierr = PetscObjectQueryFunction((PetscObject)eps,"EPSPRIMMESetBlockSize_C",(void (**)())&f);CHKERRQ(ierr);
390
  if (f) {
391
    ierr = (*f)(eps,bs);CHKERRQ(ierr);
392
  }
393
 
394
  PetscFunctionReturn(0);
395
}
396
 
397
EXTERN_C_BEGIN
398
#undef __FUNCT__  
399
#define __FUNCT__ "EPSPRIMMEGetBlockSize_PRIMME"
400
PetscErrorCode EPSPRIMMEGetBlockSize_PRIMME(EPS eps,int *bs)
401
{
402
  EPS_PRIMME *ops = (EPS_PRIMME *) eps->data;
403
 
404
  PetscFunctionBegin;
405
 
406
  if (bs) *bs = ops->primme.maxBlockSize;
407
 
408
  PetscFunctionReturn(0);
409
}
410
EXTERN_C_END
411
 
412
#undef __FUNCT__  
413
#define __FUNCT__ "EPSPRIMMEGetBlockSize"
1201 slepc 414
/*@
1187 slepc 415
    EPSPRIMMEGetBlockSize - Get the maximum block size the code will try to use.
416
 
417
    Collective on EPS
418
 
419
   Input Parameters:
1206 slepc 420
.  eps - the eigenproblem solver context
1187 slepc 421
 
422
   Output Parameters:  
1206 slepc 423
.  bs - returned block size
1187 slepc 424
 
425
   Level: advanced
426
.seealso: EPSPRIMMESetBlockSize()
427
@*/
428
PetscErrorCode EPSPRIMMEGetBlockSize(EPS eps,int *bs)
429
{
430
  PetscErrorCode ierr, (*f)(EPS,int*);
431
 
432
  PetscFunctionBegin;
433
 
434
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
435
  ierr = PetscObjectQueryFunction((PetscObject)eps,"EPSPRIMMEGetBlockSize_C",(void (**)())&f);CHKERRQ(ierr);
436
  if (f) {
437
    ierr = (*f)(eps,bs);CHKERRQ(ierr);
438
  }
439
 
440
  PetscFunctionReturn(0);
441
}
442
 
443
EXTERN_C_BEGIN
444
#undef __FUNCT__  
445
#define __FUNCT__ "EPSPRIMMESetMethod_PRIMME"
1190 slepc 446
PetscErrorCode EPSPRIMMESetMethod_PRIMME(EPS eps, EPSPRIMMEMethod method)
1187 slepc 447
{
448
  EPS_PRIMME *ops = (EPS_PRIMME *) eps->data;
449
 
450
  PetscFunctionBegin;
451
 
1239 slepc 452
  if (method == PETSC_DEFAULT) ops->method = DYNAMIC;
1187 slepc 453
  else ops->method = (primme_preset_method)method;
1239 slepc 454
 
1187 slepc 455
  PetscFunctionReturn(0);
456
}
457
EXTERN_C_END
458
 
459
#undef __FUNCT__  
460
#define __FUNCT__ "EPSPRIMMESetMethod"
1201 slepc 461
/*@
1187 slepc 462
   EPSPRIMMESetMethod - Sets the method for the PRIMME library.
463
 
464
   Collective on EPS
465
 
466
   Input Parameters:
1206 slepc 467
+  eps - the eigenproblem solver context
1212 slepc 468
-  method - method that will be used by PRIMME. It must be one of:
1239 slepc 469
    EPSPRIMME_DYNAMIC, EPSPRIMME_DEFAULT_MIN_TIME(EPSPRIMME_JDQMR_ETOL),
1190 slepc 470
    EPSPRIMME_DEFAULT_MIN_MATVECS(EPSPRIMME_GD_OLSEN_PLUSK), EPSPRIMME_ARNOLDI,
1212 slepc 471
    EPSPRIMME_GD, EPSPRIMME_GD_PLUSK, EPSPRIMME_GD_OLSEN_PLUSK,
1239 slepc 472
    EPSPRIMME_JD_OLSEN_PLUSK, EPSPRIMME_RQI, EPSPRIMME_JDQR, EPSPRIMME_JDQMR,
1212 slepc 473
    EPSPRIMME_JDQMR_ETOL, EPSPRIMME_SUBSPACE_ITERATION,
1190 slepc 474
    EPSPRIMME_LOBPCG_ORTHOBASIS, EPSPRIMME_LOBPCG_ORTHOBASIS_WINDOW
1187 slepc 475
 
476
   Options Database Key:
1206 slepc 477
.  -eps_primme_set_method - Sets the method for the PRIMME library.
1187 slepc 478
 
1212 slepc 479
   Note:
1239 slepc 480
   If not set, the method defaults to EPSPRIMME_DYNAMIC.
1187 slepc 481
 
482
   Level: advanced
483
.seealso: EPSPRIMMEGetMethod()  
484
@*/
1190 slepc 485
PetscErrorCode EPSPRIMMESetMethod(EPS eps, EPSPRIMMEMethod method)
1187 slepc 486
{
1190 slepc 487
  PetscErrorCode ierr, (*f)(EPS,EPSPRIMMEMethod);
1187 slepc 488
 
489
  PetscFunctionBegin;
490
 
491
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
492
  ierr = PetscObjectQueryFunction((PetscObject)eps,"EPSPRIMMESetMethod_C",(void (**)())&f);CHKERRQ(ierr);
493
  if (f) {
494
    ierr = (*f)(eps,method); CHKERRQ(ierr);
495
  }
496
 
497
  PetscFunctionReturn(0);
498
}
499
 
500
EXTERN_C_BEGIN
501
#undef __FUNCT__  
502
#define __FUNCT__ "EPSPRIMMEGetMethod_PRIMME"
1190 slepc 503
PetscErrorCode EPSPRIMMEGetMethod_PRIMME(EPS eps, EPSPRIMMEMethod *method)
1187 slepc 504
{
505
  EPS_PRIMME *ops = (EPS_PRIMME *) eps->data;
506
 
507
  PetscFunctionBegin;
508
 
1239 slepc 509
  if (method)
510
    *method = (EPSPRIMMEMethod)ops->method;
511
 
1187 slepc 512
  PetscFunctionReturn(0);
513
}
514
EXTERN_C_END
515
 
516
#undef __FUNCT__  
517
#define __FUNCT__ "EPSPRIMMEGetMethod"
518
/*@C
519
    EPSPRIMMEGetMethod - Gets the method for the PRIMME library.
520
 
521
    Mon Collective on EPS
522
 
523
   Input Parameters:
1206 slepc 524
.  eps - the eigenproblem solver context
1187 slepc 525
 
526
   Output Parameters:
1212 slepc 527
.  method - method that will be used by PRIMME. It must be one of:
1239 slepc 528
    EPSPRIMME_DYNAMIC, EPSPRIMME_DEFAULT_MIN_TIME(EPSPRIMME_JDQMR_ETOL),
1190 slepc 529
    EPSPRIMME_DEFAULT_MIN_MATVECS(EPSPRIMME_GD_OLSEN_PLUSK), EPSPRIMME_ARNOLDI,
1212 slepc 530
    EPSPRIMME_GD, EPSPRIMME_GD_PLUSK, EPSPRIMME_GD_OLSEN_PLUSK,
1239 slepc 531
    EPSPRIMME_JD_OLSEN_PLUSK, EPSPRIMME_RQI, EPSPRIMME_JDQR, EPSPRIMME_JDQMR,
1212 slepc 532
    EPSPRIMME_JDQMR_ETOL, EPSPRIMME_SUBSPACE_ITERATION,
1190 slepc 533
    EPSPRIMME_LOBPCG_ORTHOBASIS, EPSPRIMME_LOBPCG_ORTHOBASIS_WINDOW
1187 slepc 534
 
535
    Level: advanced
536
.seealso: EPSPRIMMESetMethod()
537
@*/
1190 slepc 538
PetscErrorCode EPSPRIMMEGetMethod(EPS eps, EPSPRIMMEMethod *method)
1187 slepc 539
{
1190 slepc 540
  PetscErrorCode ierr, (*f)(EPS,EPSPRIMMEMethod*);
1187 slepc 541
 
542
  PetscFunctionBegin;
543
 
544
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
545
  ierr = PetscObjectQueryFunction((PetscObject)eps,"EPSPRIMMEGetMethod_C",(void (**)())&f);CHKERRQ(ierr);
546
  if (f) {
547
    ierr = (*f)(eps,method); CHKERRQ(ierr);
548
  }
549
 
550
  PetscFunctionReturn(0);
551
}
552
 
553
 
554
EXTERN_C_BEGIN
555
#undef __FUNCT__  
556
#define __FUNCT__ "EPSPRIMMESetPrecond_PRIMME"
1190 slepc 557
    PetscErrorCode EPSPRIMMESetPrecond_PRIMME(EPS eps, EPSPRIMMEPrecond precond)
1187 slepc 558
{
559
  EPS_PRIMME *ops = (EPS_PRIMME *) eps->data;
560
 
561
  PetscFunctionBegin;
562
 
1190 slepc 563
  if (precond == EPSPRIMME_NONE) ops->primme.correctionParams.precondition = 0;
564
  else ops->primme.correctionParams.precondition = 1;
1187 slepc 565
 
566
  PetscFunctionReturn(0);
567
}
568
EXTERN_C_END
569
 
570
#undef __FUNCT__  
571
#define __FUNCT__ "EPSPRIMMESetPrecond"
1201 slepc 572
/*@
1212 slepc 573
    EPSPRIMMESetPrecond - Sets the preconditioner to be used in the PRIMME
574
    library. Currently, only diagonal preconditioning is supported.
1187 slepc 575
 
576
    Collective on EPS
577
 
578
   Input Parameters:
1206 slepc 579
+  eps - the eigenproblem solver context
1212 slepc 580
-  precond - either EPSPRIMME_NONE (no preconditioning) or EPSPRIMME_DIAGONAL
581
   (diagonal preconditioning)
1187 slepc 582
 
583
   Options Database Key:
1212 slepc 584
.  -eps_primme_precond - Sets either 'none' or 'diagonal' preconditioner
1187 slepc 585
 
586
    Note:
1212 slepc 587
    The default is no preconditioning.
1187 slepc 588
 
589
    Level: advanced
1190 slepc 590
.seealso: EPSPRIMMEGetPrecond()
1187 slepc 591
@*/
1190 slepc 592
PetscErrorCode EPSPRIMMESetPrecond(EPS eps, EPSPRIMMEPrecond precond)
1187 slepc 593
{
1190 slepc 594
  PetscErrorCode ierr, (*f)(EPS, EPSPRIMMEPrecond);
1187 slepc 595
 
596
  PetscFunctionBegin;
597
 
598
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
599
  ierr = PetscObjectQueryFunction((PetscObject)eps,"EPSPRIMMESetPrecond_C",(void (**)())&f);CHKERRQ(ierr);
600
  if (f) {
1190 slepc 601
    ierr = (*f)(eps, precond);CHKERRQ(ierr);
1187 slepc 602
  }
603
 
604
  PetscFunctionReturn(0);
605
}
606
 
607
 
608
EXTERN_C_BEGIN
609
#undef __FUNCT__  
610
#define __FUNCT__ "EPSPRIMMEGetPrecond_PRIMME"
1190 slepc 611
    PetscErrorCode EPSPRIMMEGetPrecond_PRIMME(EPS eps, EPSPRIMMEPrecond *precond)
1187 slepc 612
{
613
  EPS_PRIMME *ops = (EPS_PRIMME *) eps->data;
614
 
615
  PetscFunctionBegin;
616
 
1190 slepc 617
  if (precond)
618
    *precond = ops->primme.correctionParams.precondition ? EPSPRIMME_DIAGONAL : EPSPRIMME_NONE;
1187 slepc 619
 
620
  PetscFunctionReturn(0);
621
}
622
EXTERN_C_END
623
 
624
#undef __FUNCT__  
625
#define __FUNCT__ "EPSPRIMMEGetPrecond"
626
/*@C
1212 slepc 627
    EPSPRIMMEGetPrecond - Gets the preconditioner to be used in the PRIMME
628
    library.
1187 slepc 629
 
630
    Collective on EPS
631
 
632
   Input Parameters:
1206 slepc 633
.  eps - the eigenproblem solver context
1187 slepc 634
 
635
  Output Parameters:
1212 slepc 636
.  precond - either EPSPRIMME_NONE (no preconditioning) or EPSPRIMME_DIAGONAL
637
   (diagonal preconditioning)
1187 slepc 638
 
639
    Level: advanced
1190 slepc 640
.seealso: EPSPRIMMESetPrecond()
1187 slepc 641
@*/
1190 slepc 642
PetscErrorCode EPSPRIMMEGetPrecond(EPS eps, EPSPRIMMEPrecond *precond)
1187 slepc 643
{
1190 slepc 644
  PetscErrorCode ierr, (*f)(EPS, EPSPRIMMEPrecond*);
1187 slepc 645
 
646
  PetscFunctionBegin;
647
 
648
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
649
  ierr = PetscObjectQueryFunction((PetscObject)eps,"EPSPRIMMEGetPrecond_C",(void (**)())&f);CHKERRQ(ierr);
650
  if (f) {
1190 slepc 651
    ierr = (*f)(eps, precond);CHKERRQ(ierr);
1187 slepc 652
  }
653
 
654
  PetscFunctionReturn(0);
655
}
656
 
657
 
658
EXTERN_C_BEGIN
659
#undef __FUNCT__  
660
#define __FUNCT__ "EPSCreate_PRIMME"
661
PetscErrorCode EPSCreate_PRIMME(EPS eps)
662
{
663
  PetscErrorCode ierr;
664
  EPS_PRIMME     *primme;
665
 
666
  PetscFunctionBegin;
667
 
668
  ierr = PetscNew(EPS_PRIMME,&primme);CHKERRQ(ierr);
669
  PetscLogObjectMemory(eps,sizeof(EPS_PRIMME));
670
  eps->data                      = (void *) primme;
671
  eps->ops->solve                = EPSSolve_PRIMME;
672
  eps->ops->setup                = EPSSetUp_PRIMME;
673
  eps->ops->setfromoptions       = EPSSetFromOptions_PRIMME;
674
  eps->ops->destroy              = EPSDestroy_PRIMME;
675
  eps->ops->view                 = EPSView_PRIMME;
676
  eps->ops->backtransform        = EPSBackTransform_Default;
677
  eps->ops->computevectors       = EPSComputeVectors_Default;
678
 
679
  primme_initialize(&primme->primme);
680
  primme->primme.matrixMatvec = multMatvec_PRIMME;
1239 slepc 681
  primme->primme.globalSumDouble = par_GlobalSumDouble;
682
  primme->method = DYNAMIC;
1187 slepc 683
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSPRIMMESetBlockSize_C","EPSPRIMMESetBlockSize_PRIMME",EPSPRIMMESetBlockSize_PRIMME);CHKERRQ(ierr);
684
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSPRIMMESetMethod_C","EPSPRIMMESetMethod_PRIMME",EPSPRIMMESetMethod_PRIMME);CHKERRQ(ierr);
1207 slepc 685
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSPRIMMESetPrecond_C","EPSPRIMMESetPrecond_PRIMME",EPSPRIMMESetPrecond_PRIMME);CHKERRQ(ierr);
1187 slepc 686
 
687
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSPRIMMEGetBlockSize_C","EPSPRIMMEGetBlockSize_PRIMME",EPSPRIMMEGetBlockSize_PRIMME);CHKERRQ(ierr);
688
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSPRIMMEGetMethod_C","EPSPRIMMEGetMethod_PRIMME",EPSPRIMMEGetMethod_PRIMME);CHKERRQ(ierr);
1207 slepc 689
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSPRIMMEGetPrecond_C","EPSPRIMMEGetPrecond_PRIMME",EPSPRIMMEGetPrecond_PRIMME);CHKERRQ(ierr);
1187 slepc 690
 
1212 slepc 691
  eps->which = EPS_LARGEST_REAL;
692
 
1187 slepc 693
  PetscFunctionReturn(0);
694
}
695
EXTERN_C_END
696
 
697