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
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
2116 eromero 6
   Copyright (c) 2002-2010, 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
 
2001 eromero 24
#include "petsc.h"
1521 slepc 25
#include "private/epsimpl.h"    /*I "slepceps.h" I*/
26
#include "private/stimpl.h"
1187 slepc 27
 
1947 jroman 28
PetscErrorCode EPSSolve_PRIMME(EPS);
29
 
1187 slepc 30
EXTERN_C_BEGIN
31
#include "primme.h"
32
EXTERN_C_END
33
 
34
typedef struct {
35
  primme_params primme;           /* param struc */
36
  primme_preset_method method;    /* primme method */
37
  Mat A;                          /* problem matrix */
2001 eromero 38
  EPS eps;                        /* EPS current context */
39
  KSP ksp;                        /* preconditioner */
1189 slepc 40
  Vec x,y;                        /* auxiliar vectors */
1187 slepc 41
} EPS_PRIMME;
42
 
1239 slepc 43
const char *methodList[] = {
44
  "dynamic",
45
  "default_min_time",
46
  "default_min_matvecs",
47
  "arnoldi",
48
  "gd",
49
  "gd_plusk",
50
  "gd_olsen_plusk",
51
  "jd_olsen_plusk",
52
  "rqi",
53
  "jdqr",
54
  "jdqmr",
55
  "jdqmr_etol",
56
  "subspace_iteration",
57
  "lobpcg_orthobasis",
58
  "lobpcg_orthobasis_window"
59
};
60
EPSPRIMMEMethod methodN[] = {
1940 jroman 61
  EPS_PRIMME_DYNAMIC,
62
  EPS_PRIMME_DEFAULT_MIN_TIME,
63
  EPS_PRIMME_DEFAULT_MIN_MATVECS,
64
  EPS_PRIMME_ARNOLDI,
65
  EPS_PRIMME_GD,
66
  EPS_PRIMME_GD_PLUSK,
67
  EPS_PRIMME_GD_OLSEN_PLUSK,
68
  EPS_PRIMME_JD_OLSEN_PLUSK,
69
  EPS_PRIMME_RQI,
70
  EPS_PRIMME_JDQR,
71
  EPS_PRIMME_JDQMR,
72
  EPS_PRIMME_JDQMR_ETOL,
73
  EPS_PRIMME_SUBSPACE_ITERATION,
74
  EPS_PRIMME_LOBPCG_ORTHOBASIS,
75
  EPS_PRIMME_LOBPCG_ORTHOBASISW
1239 slepc 76
};
1187 slepc 77
 
1239 slepc 78
static void multMatvec_PRIMME(void *in, void *out, int *blockSize, primme_params *primme);
79
static void applyPreconditioner_PRIMME(void *in, void *out, int *blockSize, struct primme_params *primme);
80
 
1446 slepc 81
void par_GlobalSumDouble(void *sendBuf, void *recvBuf, int *count, primme_params *primme) {
1472 slepc 82
  PetscErrorCode ierr;
83
  ierr = MPI_Allreduce((double*)sendBuf, (double*)recvBuf, *count, MPI_DOUBLE, MPI_SUM, ((PetscObject)(primme->commInfo))->comm);CHKERRABORT(((PetscObject)(primme->commInfo))->comm,ierr);
1187 slepc 84
}
85
 
86
#undef __FUNCT__  
87
#define __FUNCT__ "EPSSetUp_PRIMME"
88
PetscErrorCode EPSSetUp_PRIMME(EPS eps)
89
{
90
  PetscErrorCode ierr;
1509 slepc 91
  PetscMPIInt    numProcs, procID;
1187 slepc 92
  EPS_PRIMME     *ops = (EPS_PRIMME *)eps->data;
93
  primme_params  *primme = &(((EPS_PRIMME *)eps->data)->primme);
2001 eromero 94
  PetscTruth     t;
1187 slepc 95
 
96
  PetscFunctionBegin;
97
 
1472 slepc 98
  ierr = MPI_Comm_size(((PetscObject)eps)->comm,&numProcs);CHKERRQ(ierr);
99
  ierr = MPI_Comm_rank(((PetscObject)eps)->comm,&procID);CHKERRQ(ierr);
1187 slepc 100
 
1212 slepc 101
  /* Check some constraints and set some default values */
1928 jroman 102
  if (!eps->max_it) eps->max_it = PetscMax(1000,eps->n);
1189 slepc 103
  ierr = STGetOperators(eps->OP, &ops->A, PETSC_NULL);
1212 slepc 104
  if (!ops->A) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"The problem matrix has to be specified first");
1187 slepc 105
  if (!eps->ishermitian)
1189 slepc 106
    SETERRQ(PETSC_ERR_SUP,"PRIMME is only available for Hermitian problems");
107
  if (eps->isgeneralized)
108
    SETERRQ(PETSC_ERR_SUP,"PRIMME is not available for generalized problems");
2104 eromero 109
  if (!eps->which) eps->which = EPS_LARGEST_REAL;
110
 
111
  /* Change the default sigma to inf if necessary */
112
  if (eps->which == EPS_LARGEST_MAGNITUDE || eps->which == EPS_LARGEST_REAL ||
113
      eps->which == EPS_LARGEST_IMAGINARY) {
114
    ierr = STSetDefaultShift(eps->OP, 3e300); CHKERRQ(ierr);
115
  }
116
 
2003 eromero 117
  ierr = STSetUp(eps->OP); CHKERRQ(ierr);
2001 eromero 118
  ierr = PetscTypeCompare((PetscObject)eps->OP, STPRECOND, &t); CHKERRQ(ierr);
2003 eromero 119
  if (t == PETSC_FALSE) SETERRQ(PETSC_ERR_SUP, "PRIMME only works with precond spectral transformation");
1187 slepc 120
 
121
  /* Transfer SLEPc options to PRIMME options */
1928 jroman 122
  primme->n = eps->n;
123
  primme->nLocal = eps->nloc;
1187 slepc 124
  primme->numEvals = eps->nev;
1189 slepc 125
  primme->matrix = ops;
1212 slepc 126
  primme->commInfo = eps;
1187 slepc 127
  primme->maxMatvecs = eps->max_it;
128
  primme->eps = eps->tol;
129
  primme->numProcs = numProcs;
130
  primme->procID = procID;
1700 eromero 131
  primme->printLevel = 0;
2001 eromero 132
  primme->correctionParams.precondition = 1;
1187 slepc 133
 
1942 jroman 134
  if (!eps->which) eps->which = EPS_LARGEST_REAL;
1187 slepc 135
  switch(eps->which) {
1203 slepc 136
    case EPS_LARGEST_REAL:
1187 slepc 137
      primme->target = primme_largest;
138
      break;
1203 slepc 139
    case EPS_SMALLEST_REAL:
1187 slepc 140
      primme->target = primme_smallest;
141
      break;
142
    default:
1203 slepc 143
      SETERRQ(PETSC_ERR_SUP,"PRIMME only allows EPS_LARGEST_REAL and EPS_SMALLEST_REAL for 'which' value");
1187 slepc 144
      break;  
145
  }
1207 slepc 146
 
1239 slepc 147
  if (primme_set_method(ops->method, primme) < 0)
148
    SETERRQ(PETSC_ERR_SUP,"PRIMME method not valid");
1187 slepc 149
 
1207 slepc 150
  /* If user sets ncv, maxBasisSize is modified. If not, ncv is set as maxBasisSize */
151
  if (eps->ncv) primme->maxBasisSize = eps->ncv;
152
  else eps->ncv = primme->maxBasisSize;
153
  if (eps->ncv < eps->nev+primme->maxBlockSize)  
154
    SETERRQ(PETSC_ERR_SUP,"PRIMME needs ncv >= nev+maxBlockSize");
1579 slepc 155
  if (eps->mpd) PetscInfo(eps,"Warning: parameter mpd ignored\n");
1207 slepc 156
 
1560 slepc 157
  if (eps->extraction) {
158
     ierr = PetscInfo(eps,"Warning: extraction type ignored\n");CHKERRQ(ierr);
1426 slepc 159
  }
160
 
1187 slepc 161
  /* Set workspace */
1596 slepc 162
  ierr = EPSAllocateSolution(eps);CHKERRQ(ierr);
1207 slepc 163
 
2001 eromero 164
  /* Setup the preconditioner */
165
  ops->eps = eps;
1207 slepc 166
  if (primme->correctionParams.precondition) {
2001 eromero 167
    ierr = STGetKSP(eps->OP, &ops->ksp); CHKERRQ(ierr);
2003 eromero 168
    ierr = PetscTypeCompare((PetscObject)ops->ksp, KSPPREONLY, &t); CHKERRQ(ierr);
169
    if (t == PETSC_FALSE) SETERRQ(PETSC_ERR_SUP, "PRIMME only works with preonly ksp of the spectral transformation");
1189 slepc 170
    primme->preconditioner = PETSC_NULL;
1187 slepc 171
    primme->applyPreconditioner = applyPreconditioner_PRIMME;
172
  }
173
 
1212 slepc 174
  /* Prepare auxiliary vectors */
1928 jroman 175
  ierr = VecCreateMPIWithArray(PETSC_COMM_WORLD,eps->nloc,eps->n,PETSC_NULL,&ops->x);CHKERRQ(ierr);
176
  ierr = VecCreateMPIWithArray(PETSC_COMM_WORLD,eps->nloc,eps->n,PETSC_NULL,&ops->y);CHKERRQ(ierr);
1189 slepc 177
 
1947 jroman 178
  /* dispatch solve method */
179
  if (eps->leftvecs) SETERRQ(PETSC_ERR_SUP,"Left vectors not supported in this solver");
180
  eps->ops->solve = EPSSolve_PRIMME;
1187 slepc 181
  PetscFunctionReturn(0);
182
}
183
 
184
#undef __FUNCT__  
185
#define __FUNCT__ "EPSSolve_PRIMME"
186
PetscErrorCode EPSSolve_PRIMME(EPS eps)
187
{
188
  PetscErrorCode ierr;
1201 slepc 189
  EPS_PRIMME     *ops = (EPS_PRIMME *)eps->data;
190
  PetscScalar    *a;
1187 slepc 191
#ifdef PETSC_USE_COMPLEX
1509 slepc 192
  PetscInt       i;
1201 slepc 193
  PetscReal      *evals;
1187 slepc 194
#endif
195
 
196
  PetscFunctionBegin;
197
 
1240 slepc 198
  /* Reset some parameters left from previous runs */
199
  ops->primme.aNorm    = 0.0;
1933 jroman 200
  ops->primme.initSize = eps->nini;
1240 slepc 201
  ops->primme.iseed[0] = -1;
202
 
1187 slepc 203
  /* Call PRIMME solver */
204
  ierr = VecGetArray(eps->V[0], &a); CHKERRQ(ierr);
205
#ifndef PETSC_USE_COMPLEX
206
  ierr = dprimme(eps->eigr, a, eps->errest, &ops->primme);
207
#else
1212 slepc 208
  /* PRIMME returns real eigenvalues, but SLEPc works with complex ones */
1201 slepc 209
  ierr = PetscMalloc(eps->ncv*sizeof(PetscReal),&evals); CHKERRQ(ierr);
210
  ierr = zprimme(evals, (Complex_Z*)a, eps->errest, &ops->primme);
211
  for (i=0;i<eps->ncv;i++)
212
    eps->eigr[i] = evals[i];
213
  ierr = PetscFree(evals); CHKERRQ(ierr);
1187 slepc 214
#endif
215
  ierr = VecRestoreArray(eps->V[0], &a); CHKERRQ(ierr);
216
 
217
  switch(ierr) {
218
    case 0: /* Successful */
219
      break;
220
 
221
    case -1:
222
      SETERRQ(PETSC_ERR_SUP,"PRIMME: Failed to open output file");
223
      break;
224
 
225
    case -2:
226
      SETERRQ(PETSC_ERR_SUP,"PRIMME: Insufficient integer or real workspace allocated");
227
      break;
228
 
229
    case -3:
230
      SETERRQ(PETSC_ERR_SUP,"PRIMME: main_iter encountered a problem");
231
      break;
232
 
233
    default:
234
      SETERRQ(PETSC_ERR_SUP,"PRIMME: some parameters wrong configured");
235
      break;
236
  }
237
 
1240 slepc 238
  eps->nconv = ops->primme.initSize >= 0 ? ops->primme.initSize : 0;
239
  eps->reason = eps->ncv >= eps->nev ? EPS_CONVERGED_TOL : EPS_DIVERGED_ITS;
1236 slepc 240
  eps->its = ops->primme.stats.numOuterIterations;
241
  eps->OP->applys = ops->primme.stats.numMatvecs;
1187 slepc 242
 
243
  PetscFunctionReturn(0);
244
}
245
 
1201 slepc 246
#undef __FUNCT__  
247
#define __FUNCT__ "multMatvec_PRIMME"
1239 slepc 248
static void multMatvec_PRIMME(void *in, void *out, int *blockSize, primme_params *primme)
1187 slepc 249
{
1212 slepc 250
  PetscErrorCode ierr;
1509 slepc 251
  PetscInt       i, N = primme->n;
1212 slepc 252
  EPS_PRIMME     *ops = (EPS_PRIMME *)primme->matrix;
253
  Vec            x = ops->x;
254
  Vec            y = ops->y;
255
  Mat            A = ops->A;
1187 slepc 256
 
1201 slepc 257
  PetscFunctionBegin;
1187 slepc 258
  for (i=0;i<*blockSize;i++) {
259
    /* build vectors using 'in' an 'out' workspace */
1201 slepc 260
    ierr = VecPlaceArray(x, (PetscScalar*)in+N*i ); CHKERRABORT(PETSC_COMM_WORLD,ierr);
261
    ierr = VecPlaceArray(y, (PetscScalar*)out+N*i ); CHKERRABORT(PETSC_COMM_WORLD,ierr);
1187 slepc 262
 
1201 slepc 263
    ierr = MatMult(A, x, y); CHKERRABORT(PETSC_COMM_WORLD,ierr);
1187 slepc 264
 
1201 slepc 265
    ierr = VecResetArray(x); CHKERRABORT(PETSC_COMM_WORLD,ierr);
266
    ierr = VecResetArray(y); CHKERRABORT(PETSC_COMM_WORLD,ierr);
1187 slepc 267
  }
1201 slepc 268
  PetscFunctionReturnVoid();
1187 slepc 269
}
270
 
1201 slepc 271
#undef __FUNCT__  
272
#define __FUNCT__ "applyPreconditioner_PRIMME"
1239 slepc 273
static void applyPreconditioner_PRIMME(void *in, void *out, int *blockSize, struct primme_params *primme)
1187 slepc 274
{
1212 slepc 275
  PetscErrorCode ierr;
2001 eromero 276
  PetscInt       i, N = primme->n, lits;
1212 slepc 277
  EPS_PRIMME     *ops = (EPS_PRIMME *)primme->matrix;
278
  Vec            x = ops->x;
279
  Vec            y = ops->y;
1189 slepc 280
 
1201 slepc 281
  PetscFunctionBegin;
1187 slepc 282
  for (i=0;i<*blockSize;i++) {
283
    /* build vectors using 'in' an 'out' workspace */
1201 slepc 284
    ierr = VecPlaceArray(x, (PetscScalar*)in+N*i ); CHKERRABORT(PETSC_COMM_WORLD,ierr);
285
    ierr = VecPlaceArray(y, (PetscScalar*)out+N*i ); CHKERRABORT(PETSC_COMM_WORLD,ierr);
1187 slepc 286
 
2001 eromero 287
    ierr = KSPSolve(ops->ksp, x, y); CHKERRABORT(PETSC_COMM_WORLD,ierr);
288
    ierr = KSPGetIterationNumber(ops->ksp, &lits); CHKERRABORT(PETSC_COMM_WORLD,ierr);
289
    ops->eps->OP->lineariterations+= lits;
1187 slepc 290
 
1201 slepc 291
    ierr = VecResetArray(x); CHKERRABORT(PETSC_COMM_WORLD,ierr);
292
    ierr = VecResetArray(y); CHKERRABORT(PETSC_COMM_WORLD,ierr);
1187 slepc 293
  }
1201 slepc 294
  PetscFunctionReturnVoid();
1187 slepc 295
}
296
 
297
 
298
#undef __FUNCT__  
299
#define __FUNCT__ "EPSDestroy_PRIMME"
300
PetscErrorCode EPSDestroy_PRIMME(EPS eps)
301
{
302
  PetscErrorCode ierr;
303
  EPS_PRIMME    *ops = (EPS_PRIMME *)eps->data;
304
 
305
  PetscFunctionBegin;
306
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
307
 
308
  primme_Free(&ops->primme);
1189 slepc 309
  ierr = VecDestroy(ops->x);CHKERRQ(ierr);
310
  ierr = VecDestroy(ops->y);CHKERRQ(ierr);
1218 slepc 311
  ierr = PetscFree(eps->data);CHKERRQ(ierr);
1596 slepc 312
  ierr = EPSFreeSolution(eps);CHKERRQ(ierr);
1187 slepc 313
 
1925 jroman 314
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSPRIMMESetBlockSize_C","",PETSC_NULL);CHKERRQ(ierr);
315
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSPRIMMESetMethod_C","",PETSC_NULL);CHKERRQ(ierr);
316
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSPRIMMEGetBlockSize_C","",PETSC_NULL);CHKERRQ(ierr);
317
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSPRIMMEGetMethod_C","",PETSC_NULL);CHKERRQ(ierr);
318
 
1187 slepc 319
  PetscFunctionReturn(0);
320
}
321
 
322
#undef __FUNCT__  
323
#define __FUNCT__ "EPSView_PRIMME"
324
PetscErrorCode EPSView_PRIMME(EPS eps,PetscViewer viewer)
325
{
1212 slepc 326
  PetscErrorCode ierr;
327
  PetscTruth isascii;
1189 slepc 328
  primme_params *primme = &((EPS_PRIMME *)eps->data)->primme;
1239 slepc 329
  EPSPRIMMEMethod methodn;
330
 
1187 slepc 331
  PetscFunctionBegin;
1189 slepc 332
  ierr = PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);CHKERRQ(ierr);
333
  if (!isascii) {
1201 slepc 334
    SETERRQ1(1,"Viewer type %s not supported for EPSPRIMME",((PetscObject)viewer)->type_name);
1189 slepc 335
  }
336
 
1207 slepc 337
  ierr = PetscViewerASCIIPrintf(viewer,"PRIMME solver block size: %d\n",primme->maxBlockSize);CHKERRQ(ierr);
1239 slepc 338
  ierr = EPSPRIMMEGetMethod(eps, &methodn);CHKERRQ(ierr);
339
  ierr = PetscViewerASCIIPrintf(viewer,"PRIMME solver method: %s\n", methodList[methodn]);CHKERRQ(ierr);
1189 slepc 340
 
1700 eromero 341
  /* Display PRIMME params */
1634 slepc 342
  primme_display_params(*primme);
1700 eromero 343
 
1187 slepc 344
  PetscFunctionReturn(0);
345
}
346
 
347
#undef __FUNCT__  
348
#define __FUNCT__ "EPSSetFromOptions_PRIMME"
349
PetscErrorCode EPSSetFromOptions_PRIMME(EPS eps)
350
{
351
  PetscErrorCode ierr;
352
  EPS_PRIMME    *ops = (EPS_PRIMME *)eps->data;
353
  PetscInt       op;
354
  PetscTruth     flg;
355
 
356
  PetscFunctionBegin;
357
 
2102 eromero 358
  ierr = PetscOptionsBegin(((PetscObject)eps)->comm,((PetscObject)eps)->prefix,"PRIMME Options","EPS");CHKERRQ(ierr);
1187 slepc 359
 
360
  op = ops->primme.maxBlockSize;
1203 slepc 361
  ierr = PetscOptionsInt("-eps_primme_block_size"," maximum block size","EPSPRIMMESetBlockSize",op,&op,&flg); CHKERRQ(ierr);
1187 slepc 362
  if (flg) {ierr = EPSPRIMMESetBlockSize(eps,op);CHKERRQ(ierr);}
363
  op = 0;
364
  ierr = PetscOptionsEList("-eps_primme_method","set method for solving the eigenproblem",
1446 slepc 365
                           "EPSPRIMMESetMethod",methodList,15,methodList[1],&op,&flg); CHKERRQ(ierr);
1187 slepc 366
  if (flg) {ierr = EPSPRIMMESetMethod(eps, methodN[op]);CHKERRQ(ierr);}
367
 
2102 eromero 368
  ierr = PetscOptionsEnd();CHKERRQ(ierr);
1187 slepc 369
 
370
  PetscFunctionReturn(0);
371
}
372
 
373
EXTERN_C_BEGIN
374
#undef __FUNCT__  
375
#define __FUNCT__ "EPSPRIMMESetBlockSize_PRIMME"
1509 slepc 376
PetscErrorCode EPSPRIMMESetBlockSize_PRIMME(EPS eps,PetscInt bs)
1187 slepc 377
{
378
  EPS_PRIMME *ops = (EPS_PRIMME *) eps->data;
379
 
380
  PetscFunctionBegin;
381
 
382
  if (bs == PETSC_DEFAULT) ops->primme.maxBlockSize = 1;
383
  else if (bs <= 0) {
384
    SETERRQ(1, "PRIMME: wrong block size");
385
  } else ops->primme.maxBlockSize = bs;
386
 
387
  PetscFunctionReturn(0);
388
}
389
EXTERN_C_END
390
 
391
#undef __FUNCT__  
392
#define __FUNCT__ "EPSPRIMMESetBlockSize"
1201 slepc 393
/*@
1212 slepc 394
    EPSPRIMMESetBlockSize - The maximum block size the code will try to use.
395
    The user should set
1187 slepc 396
    this based on the architecture specifics of the target computer,
397
    as well as any a priori knowledge of multiplicities. The code does
398
    NOT require BlockSize > 1 to find multiple eigenvalues.  For some
399
    methods, keeping BlockSize = 1 yields the best overall performance.
400
 
401
   Collective on EPS
402
 
403
   Input Parameters:
404
+  eps - the eigenproblem solver context
405
-  bs - block size
406
 
407
   Options Database Key:
1212 slepc 408
.  -eps_primme_block_size - Sets the max allowed block size value
1187 slepc 409
 
1212 slepc 410
   Notes:
411
   If the block size is not set, the value established by primme_initialize
412
   is used.
1187 slepc 413
 
414
   Level: advanced
415
.seealso: EPSPRIMMEGetBlockSize()
416
@*/
1509 slepc 417
PetscErrorCode EPSPRIMMESetBlockSize(EPS eps,PetscInt bs)
1187 slepc 418
{
1509 slepc 419
  PetscErrorCode ierr, (*f)(EPS,PetscInt);
1187 slepc 420
 
421
  PetscFunctionBegin;
422
 
423
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
424
  ierr = PetscObjectQueryFunction((PetscObject)eps,"EPSPRIMMESetBlockSize_C",(void (**)())&f);CHKERRQ(ierr);
425
  if (f) {
426
    ierr = (*f)(eps,bs);CHKERRQ(ierr);
427
  }
428
 
429
  PetscFunctionReturn(0);
430
}
431
 
432
EXTERN_C_BEGIN
433
#undef __FUNCT__  
434
#define __FUNCT__ "EPSPRIMMEGetBlockSize_PRIMME"
1509 slepc 435
PetscErrorCode EPSPRIMMEGetBlockSize_PRIMME(EPS eps,PetscInt *bs)
1187 slepc 436
{
437
  EPS_PRIMME *ops = (EPS_PRIMME *) eps->data;
438
 
439
  PetscFunctionBegin;
440
 
441
  if (bs) *bs = ops->primme.maxBlockSize;
442
 
443
  PetscFunctionReturn(0);
444
}
445
EXTERN_C_END
446
 
447
#undef __FUNCT__  
448
#define __FUNCT__ "EPSPRIMMEGetBlockSize"
1201 slepc 449
/*@
1187 slepc 450
    EPSPRIMMEGetBlockSize - Get the maximum block size the code will try to use.
451
 
452
    Collective on EPS
453
 
454
   Input Parameters:
1206 slepc 455
.  eps - the eigenproblem solver context
1187 slepc 456
 
457
   Output Parameters:  
1206 slepc 458
.  bs - returned block size
1187 slepc 459
 
460
   Level: advanced
461
.seealso: EPSPRIMMESetBlockSize()
462
@*/
1509 slepc 463
PetscErrorCode EPSPRIMMEGetBlockSize(EPS eps,PetscInt *bs)
1187 slepc 464
{
1509 slepc 465
  PetscErrorCode ierr, (*f)(EPS,PetscInt*);
1187 slepc 466
 
467
  PetscFunctionBegin;
468
 
469
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
470
  ierr = PetscObjectQueryFunction((PetscObject)eps,"EPSPRIMMEGetBlockSize_C",(void (**)())&f);CHKERRQ(ierr);
471
  if (f) {
472
    ierr = (*f)(eps,bs);CHKERRQ(ierr);
473
  }
474
 
475
  PetscFunctionReturn(0);
476
}
477
 
478
EXTERN_C_BEGIN
479
#undef __FUNCT__  
480
#define __FUNCT__ "EPSPRIMMESetMethod_PRIMME"
1190 slepc 481
PetscErrorCode EPSPRIMMESetMethod_PRIMME(EPS eps, EPSPRIMMEMethod method)
1187 slepc 482
{
483
  EPS_PRIMME *ops = (EPS_PRIMME *) eps->data;
484
 
485
  PetscFunctionBegin;
486
 
1446 slepc 487
  if (method == PETSC_DEFAULT) ops->method = DEFAULT_MIN_TIME;
1187 slepc 488
  else ops->method = (primme_preset_method)method;
1239 slepc 489
 
1187 slepc 490
  PetscFunctionReturn(0);
491
}
492
EXTERN_C_END
493
 
494
#undef __FUNCT__  
495
#define __FUNCT__ "EPSPRIMMESetMethod"
1201 slepc 496
/*@
1187 slepc 497
   EPSPRIMMESetMethod - Sets the method for the PRIMME library.
498
 
499
   Collective on EPS
500
 
501
   Input Parameters:
1206 slepc 502
+  eps - the eigenproblem solver context
1212 slepc 503
-  method - method that will be used by PRIMME. It must be one of:
1940 jroman 504
    EPS_PRIMME_DYNAMIC, EPS_PRIMME_DEFAULT_MIN_TIME(EPS_PRIMME_JDQMR_ETOL),
505
    EPS_PRIMME_DEFAULT_MIN_MATVECS(EPS_PRIMME_GD_OLSEN_PLUSK), EPS_PRIMME_ARNOLDI,
506
    EPS_PRIMME_GD, EPS_PRIMME_GD_PLUSK, EPS_PRIMME_GD_OLSEN_PLUSK,
507
    EPS_PRIMME_JD_OLSEN_PLUSK, EPS_PRIMME_RQI, EPS_PRIMME_JDQR, EPS_PRIMME_JDQMR,
508
    EPS_PRIMME_JDQMR_ETOL, EPS_PRIMME_SUBSPACE_ITERATION,
509
    EPS_PRIMME_LOBPCG_ORTHOBASIS, EPS_PRIMME_LOBPCG_ORTHOBASISW
1187 slepc 510
 
511
   Options Database Key:
1206 slepc 512
.  -eps_primme_set_method - Sets the method for the PRIMME library.
1187 slepc 513
 
1212 slepc 514
   Note:
1940 jroman 515
   If not set, the method defaults to EPS_PRIMME_DEFAULT_MIN_TIME.
1187 slepc 516
 
517
   Level: advanced
1364 slepc 518
 
519
.seealso: EPSPRIMMEGetMethod(), EPSPRIMMEMethod
1187 slepc 520
@*/
1190 slepc 521
PetscErrorCode EPSPRIMMESetMethod(EPS eps, EPSPRIMMEMethod method)
1187 slepc 522
{
1190 slepc 523
  PetscErrorCode ierr, (*f)(EPS,EPSPRIMMEMethod);
1187 slepc 524
 
525
  PetscFunctionBegin;
526
 
527
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
528
  ierr = PetscObjectQueryFunction((PetscObject)eps,"EPSPRIMMESetMethod_C",(void (**)())&f);CHKERRQ(ierr);
529
  if (f) {
530
    ierr = (*f)(eps,method); CHKERRQ(ierr);
531
  }
532
 
533
  PetscFunctionReturn(0);
534
}
535
 
536
EXTERN_C_BEGIN
537
#undef __FUNCT__  
538
#define __FUNCT__ "EPSPRIMMEGetMethod_PRIMME"
1190 slepc 539
PetscErrorCode EPSPRIMMEGetMethod_PRIMME(EPS eps, EPSPRIMMEMethod *method)
1187 slepc 540
{
541
  EPS_PRIMME *ops = (EPS_PRIMME *) eps->data;
542
 
543
  PetscFunctionBegin;
544
 
1239 slepc 545
  if (method)
546
    *method = (EPSPRIMMEMethod)ops->method;
547
 
1187 slepc 548
  PetscFunctionReturn(0);
549
}
550
EXTERN_C_END
551
 
552
#undef __FUNCT__  
553
#define __FUNCT__ "EPSPRIMMEGetMethod"
554
/*@C
555
    EPSPRIMMEGetMethod - Gets the method for the PRIMME library.
556
 
557
    Mon Collective on EPS
558
 
559
   Input Parameters:
1206 slepc 560
.  eps - the eigenproblem solver context
1187 slepc 561
 
562
   Output Parameters:
1212 slepc 563
.  method - method that will be used by PRIMME. It must be one of:
1940 jroman 564
    EPS_PRIMME_DYNAMIC, EPS_PRIMME_DEFAULT_MIN_TIME(EPS_PRIMME_JDQMR_ETOL),
565
    EPS_PRIMME_DEFAULT_MIN_MATVECS(EPS_PRIMME_GD_OLSEN_PLUSK), EPS_PRIMME_ARNOLDI,
566
    EPS_PRIMME_GD, EPS_PRIMME_GD_PLUSK, EPS_PRIMME_GD_OLSEN_PLUSK,
567
    EPS_PRIMME_JD_OLSEN_PLUSK, EPS_PRIMME_RQI, EPS_PRIMME_JDQR, EPS_PRIMME_JDQMR,
568
    EPS_PRIMME_JDQMR_ETOL, EPS_PRIMME_SUBSPACE_ITERATION,
569
    EPS_PRIMME_LOBPCG_ORTHOBASIS, EPS_PRIMME_LOBPCG_ORTHOBASISW
1187 slepc 570
 
571
    Level: advanced
1364 slepc 572
 
573
.seealso: EPSPRIMMESetMethod(), EPSPRIMMEMethod
1187 slepc 574
@*/
1190 slepc 575
PetscErrorCode EPSPRIMMEGetMethod(EPS eps, EPSPRIMMEMethod *method)
1187 slepc 576
{
1190 slepc 577
  PetscErrorCode ierr, (*f)(EPS,EPSPRIMMEMethod*);
1187 slepc 578
 
579
  PetscFunctionBegin;
580
 
581
  PetscValidHeaderSpecific(eps,EPS_COOKIE,1);
582
  ierr = PetscObjectQueryFunction((PetscObject)eps,"EPSPRIMMEGetMethod_C",(void (**)())&f);CHKERRQ(ierr);
583
  if (f) {
584
    ierr = (*f)(eps,method); CHKERRQ(ierr);
585
  }
586
 
587
  PetscFunctionReturn(0);
588
}
589
 
590
EXTERN_C_BEGIN
591
#undef __FUNCT__  
592
#define __FUNCT__ "EPSCreate_PRIMME"
593
PetscErrorCode EPSCreate_PRIMME(EPS eps)
594
{
595
  PetscErrorCode ierr;
596
  EPS_PRIMME     *primme;
597
 
598
  PetscFunctionBegin;
599
 
2001 eromero 600
  ierr = STSetType(eps->OP, STPRECOND); CHKERRQ(ierr);
2020 eromero 601
  ierr = STPrecondSetKSPHasMat(eps->OP, PETSC_TRUE); CHKERRQ(ierr);
2001 eromero 602
 
1187 slepc 603
  ierr = PetscNew(EPS_PRIMME,&primme);CHKERRQ(ierr);
604
  PetscLogObjectMemory(eps,sizeof(EPS_PRIMME));
605
  eps->data                      = (void *) primme;
606
  eps->ops->setup                = EPSSetUp_PRIMME;
607
  eps->ops->setfromoptions       = EPSSetFromOptions_PRIMME;
608
  eps->ops->destroy              = EPSDestroy_PRIMME;
609
  eps->ops->view                 = EPSView_PRIMME;
610
  eps->ops->backtransform        = EPSBackTransform_Default;
611
  eps->ops->computevectors       = EPSComputeVectors_Default;
612
 
613
  primme_initialize(&primme->primme);
614
  primme->primme.matrixMatvec = multMatvec_PRIMME;
1239 slepc 615
  primme->primme.globalSumDouble = par_GlobalSumDouble;
1940 jroman 616
  primme->method = (primme_preset_method)EPS_PRIMME_DEFAULT_MIN_TIME;
1942 jroman 617
 
1187 slepc 618
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSPRIMMESetBlockSize_C","EPSPRIMMESetBlockSize_PRIMME",EPSPRIMMESetBlockSize_PRIMME);CHKERRQ(ierr);
619
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSPRIMMESetMethod_C","EPSPRIMMESetMethod_PRIMME",EPSPRIMMESetMethod_PRIMME);CHKERRQ(ierr);
620
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSPRIMMEGetBlockSize_C","EPSPRIMMEGetBlockSize_PRIMME",EPSPRIMMEGetBlockSize_PRIMME);CHKERRQ(ierr);
621
  ierr = PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSPRIMMEGetMethod_C","EPSPRIMMEGetMethod_PRIMME",EPSPRIMMEGetMethod_PRIMME);CHKERRQ(ierr);
622
  PetscFunctionReturn(0);
623
}
624
EXTERN_C_END