Subversion Repositories slepc-dev

Rev

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