Subversion Repositories slepc-dev

Rev

Details | Compare with Previous | Last modification | View Log | RSS feed

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