Actual source code: primmes.c
1: /*
2: This file implements a wrapper to the PRIMME library
4: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
5: SLEPc - Scalable Library for Eigenvalue Problem Computations
6: Copyright (c) 2002-2009, Universidad Politecnica de Valencia, Spain
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.
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.
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/>.
21: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
22: */
24: #include private/epsimpl.h
25: #include private/stimpl.h
28: #include "primme.h"
31: typedef struct {
32: primme_params primme; /* param struc */
33: primme_preset_method method; /* primme method */
34: Mat A; /* problem matrix */
35: Vec w; /* store reciprocal A diagonal */
36: Vec x,y; /* auxiliar vectors */
37: } EPS_PRIMME;
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[] = {
58: EPSPRIMME_DYNAMIC,
59: EPSPRIMME_DEFAULT_MIN_TIME,
60: EPSPRIMME_DEFAULT_MIN_MATVECS,
61: EPSPRIMME_ARNOLDI,
62: EPSPRIMME_GD,
63: EPSPRIMME_GD_PLUSK,
64: EPSPRIMME_GD_OLSEN_PLUSK,
65: EPSPRIMME_JD_OLSEN_PLUSK,
66: EPSPRIMME_RQI,
67: EPSPRIMME_JDQR,
68: EPSPRIMME_JDQMR,
69: EPSPRIMME_JDQMR_ETOL,
70: EPSPRIMME_SUBSPACE_ITERATION,
71: EPSPRIMME_LOBPCG_ORTHOBASIS,
72: EPSPRIMME_LOBPCG_ORTHOBASISW
73: };
74: EPSPRIMMEPrecond precondN[] = {EPSPRIMME_NONE, EPSPRIMME_DIAGONAL};
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);
79: void par_GlobalSumDouble(void *sendBuf, void *recvBuf, int *count, primme_params *primme) {
81: MPI_Allreduce((double*)sendBuf, (double*)recvBuf, *count, MPI_DOUBLE, MPI_SUM, ((PetscObject)(primme->commInfo))->comm);CHKERRABORT(((PetscObject)(primme->commInfo))->comm,ierr);
82: }
86: PetscErrorCode EPSSetUp_PRIMME(EPS eps)
87: {
89: PetscInt N, n;
90: PetscMPIInt numProcs, procID;
91: EPS_PRIMME *ops = (EPS_PRIMME *)eps->data;
92: primme_params *primme = &(((EPS_PRIMME *)eps->data)->primme);
96: MPI_Comm_size(((PetscObject)eps)->comm,&numProcs);
97: MPI_Comm_rank(((PetscObject)eps)->comm,&procID);
98:
99: /* Check some constraints and set some default values */
100: VecGetSize(eps->vec_initial,&N);
101: VecGetLocalSize(eps->vec_initial,&n);
103: if (!eps->max_it) eps->max_it = PetscMax(1000,N);
104: STGetOperators(eps->OP, &ops->A, PETSC_NULL);
105: if (!ops->A) SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"The problem matrix has to be specified first");
106: if (!eps->ishermitian)
107: SETERRQ(PETSC_ERR_SUP,"PRIMME is only available for Hermitian problems");
108: if (eps->isgeneralized)
109: SETERRQ(PETSC_ERR_SUP,"PRIMME is not available for generalized problems");
111: /* Transfer SLEPc options to PRIMME options */
112: primme->n = N;
113: primme->nLocal = n;
114: primme->numEvals = eps->nev;
115: primme->matrix = ops;
116: primme->commInfo = eps;
117: primme->maxMatvecs = eps->max_it;
118: primme->eps = eps->tol;
119: primme->numProcs = numProcs;
120: primme->procID = procID;
121: primme->printLevel = 5;
123: switch(eps->which) {
124: case EPS_LARGEST_REAL:
125: primme->target = primme_largest;
126: break;
128: case EPS_SMALLEST_REAL:
129: primme->target = primme_smallest;
130: break;
131:
132: default:
133: SETERRQ(PETSC_ERR_SUP,"PRIMME only allows EPS_LARGEST_REAL and EPS_SMALLEST_REAL for 'which' value");
134: break;
135: }
136:
137: if (primme_set_method(ops->method, primme) < 0)
138: SETERRQ(PETSC_ERR_SUP,"PRIMME method not valid");
139:
140: /* If user sets ncv, maxBasisSize is modified. If not, ncv is set as maxBasisSize */
141: if (eps->ncv) primme->maxBasisSize = eps->ncv;
142: else eps->ncv = primme->maxBasisSize;
143: if (eps->ncv < eps->nev+primme->maxBlockSize)
144: SETERRQ(PETSC_ERR_SUP,"PRIMME needs ncv >= nev+maxBlockSize");
145: if (eps->mpd) PetscInfo(eps,"Warning: parameter mpd ignored\n");
147: if (eps->extraction) {
148: PetscInfo(eps,"Warning: extraction type ignored\n");
149: }
151: /* Set workspace */
152: EPSAllocateSolution(eps);
154: if (primme->correctionParams.precondition) {
155: /* Calc reciprocal A diagonal */
156: VecDuplicate(eps->vec_initial, &ops->w);
157: MatGetDiagonal(ops->A, ops->w);
158: VecReciprocal(ops->w);
159: primme->preconditioner = PETSC_NULL;
160: primme->applyPreconditioner = applyPreconditioner_PRIMME;
161: }
163: /* Prepare auxiliary vectors */
164: VecCreateMPIWithArray(PETSC_COMM_WORLD,n,N,PETSC_NULL,&ops->x);
165: VecCreateMPIWithArray(PETSC_COMM_WORLD,n,N,PETSC_NULL,&ops->y);
166:
167: return(0);
168: }
172: PetscErrorCode EPSSolve_PRIMME(EPS eps)
173: {
175: EPS_PRIMME *ops = (EPS_PRIMME *)eps->data;
176: PetscScalar *a;
177: #ifdef PETSC_USE_COMPLEX
178: PetscInt i;
179: PetscReal *evals;
180: #endif
184: /* Reset some parameters left from previous runs */
185: ops->primme.aNorm = 0.0;
186: ops->primme.initSize = 1;
187: ops->primme.iseed[0] = -1;
189: /* Copy vec_initial to V[0] vector */
190: VecCopy(eps->vec_initial, eps->V[0]);
191:
192: /* Call PRIMME solver */
193: VecGetArray(eps->V[0], &a);
194: #ifndef PETSC_USE_COMPLEX
195: dprimme(eps->eigr, a, eps->errest, &ops->primme);
196: #else
197: /* PRIMME returns real eigenvalues, but SLEPc works with complex ones */
198: PetscMalloc(eps->ncv*sizeof(PetscReal),&evals);
199: zprimme(evals, (Complex_Z*)a, eps->errest, &ops->primme);
200: for (i=0;i<eps->ncv;i++)
201: eps->eigr[i] = evals[i];
202: PetscFree(evals);
203: #endif
204: VecRestoreArray(eps->V[0], &a);
205:
206: switch(ierr) {
207: case 0: /* Successful */
208: break;
210: case -1:
211: SETERRQ(PETSC_ERR_SUP,"PRIMME: Failed to open output file");
212: break;
214: case -2:
215: SETERRQ(PETSC_ERR_SUP,"PRIMME: Insufficient integer or real workspace allocated");
216: break;
218: case -3:
219: SETERRQ(PETSC_ERR_SUP,"PRIMME: main_iter encountered a problem");
220: break;
222: default:
223: SETERRQ(PETSC_ERR_SUP,"PRIMME: some parameters wrong configured");
224: break;
225: }
227: eps->nconv = ops->primme.initSize >= 0 ? ops->primme.initSize : 0;
228: eps->reason = eps->ncv >= eps->nev ? EPS_CONVERGED_TOL : EPS_DIVERGED_ITS;
229: eps->its = ops->primme.stats.numOuterIterations;
230: eps->OP->applys = ops->primme.stats.numMatvecs;
232: return(0);
233: }
237: static void multMatvec_PRIMME(void *in, void *out, int *blockSize, primme_params *primme)
238: {
240: PetscInt i, N = primme->n;
241: EPS_PRIMME *ops = (EPS_PRIMME *)primme->matrix;
242: Vec x = ops->x;
243: Vec y = ops->y;
244: Mat A = ops->A;
247: for (i=0;i<*blockSize;i++) {
248: /* build vectors using 'in' an 'out' workspace */
249: VecPlaceArray(x, (PetscScalar*)in+N*i ); CHKERRABORT(PETSC_COMM_WORLD,ierr);
250: VecPlaceArray(y, (PetscScalar*)out+N*i ); CHKERRABORT(PETSC_COMM_WORLD,ierr);
252: MatMult(A, x, y); CHKERRABORT(PETSC_COMM_WORLD,ierr);
253:
254: VecResetArray(x); CHKERRABORT(PETSC_COMM_WORLD,ierr);
255: VecResetArray(y); CHKERRABORT(PETSC_COMM_WORLD,ierr);
256: }
257: PetscFunctionReturnVoid();
258: }
262: static void applyPreconditioner_PRIMME(void *in, void *out, int *blockSize, struct primme_params *primme)
263: {
265: PetscInt i, N = primme->n;
266: EPS_PRIMME *ops = (EPS_PRIMME *)primme->matrix;
267: Vec x = ops->x;
268: Vec y = ops->y;
269: Vec w = ops->w;
270:
272: for (i=0;i<*blockSize;i++) {
273: /* build vectors using 'in' an 'out' workspace */
274: VecPlaceArray(x, (PetscScalar*)in+N*i ); CHKERRABORT(PETSC_COMM_WORLD,ierr);
275: VecPlaceArray(y, (PetscScalar*)out+N*i ); CHKERRABORT(PETSC_COMM_WORLD,ierr);
277: VecPointwiseMult(y, w, x); CHKERRABORT(PETSC_COMM_WORLD,ierr);
278:
279: VecResetArray(x); CHKERRABORT(PETSC_COMM_WORLD,ierr);
280: VecResetArray(y); CHKERRABORT(PETSC_COMM_WORLD,ierr);
281: }
282: PetscFunctionReturnVoid();
283: }
288: PetscErrorCode EPSDestroy_PRIMME(EPS eps)
289: {
291: EPS_PRIMME *ops = (EPS_PRIMME *)eps->data;
295:
296: if (ops->primme.correctionParams.precondition) {
297: VecDestroy(ops->w);
298: }
299: primme_Free(&ops->primme);
300: VecDestroy(ops->x);
301: VecDestroy(ops->y);
302: PetscFree(eps->data);
303: EPSFreeSolution(eps);
304:
305: return(0);
306: }
310: PetscErrorCode EPSView_PRIMME(EPS eps,PetscViewer viewer)
311: {
313: PetscTruth isascii;
314: primme_params *primme = &((EPS_PRIMME *)eps->data)->primme;
315: EPSPRIMMEMethod methodn;
316: EPSPRIMMEPrecond precondn;
319: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
320: if (!isascii) {
321: SETERRQ1(1,"Viewer type %s not supported for EPSPRIMME",((PetscObject)viewer)->type_name);
322: }
323:
324: PetscViewerASCIIPrintf(viewer,"PRIMME solver block size: %d\n",primme->maxBlockSize);
325: EPSPRIMMEGetMethod(eps, &methodn);
326: PetscViewerASCIIPrintf(viewer,"PRIMME solver method: %s\n", methodList[methodn]);
327: EPSPRIMMEGetPrecond(eps, &precondn);
328: PetscViewerASCIIPrintf(viewer,"PRIMME solver preconditioning: %s\n", precondList[precondn]);
330: primme_display_params(*primme);
331: return(0);
332: }
336: PetscErrorCode EPSSetFromOptions_PRIMME(EPS eps)
337: {
339: EPS_PRIMME *ops = (EPS_PRIMME *)eps->data;
340: PetscInt op;
341: PetscTruth flg;
344:
345: PetscOptionsHead("PRIMME options");
347: op = ops->primme.maxBlockSize;
348: PetscOptionsInt("-eps_primme_block_size"," maximum block size","EPSPRIMMESetBlockSize",op,&op,&flg);
349: if (flg) {EPSPRIMMESetBlockSize(eps,op);}
350: op = 0;
351: PetscOptionsEList("-eps_primme_method","set method for solving the eigenproblem",
352: "EPSPRIMMESetMethod",methodList,15,methodList[1],&op,&flg);
353: if (flg) {EPSPRIMMESetMethod(eps, methodN[op]);}
354: PetscOptionsEList("-eps_primme_precond","set preconditioner type",
355: "EPSPRIMMESetPrecond",precondList,2,precondList[0],&op,&flg);
356: if (flg) {EPSPRIMMESetPrecond(eps, precondN[op]);}
357:
358: PetscOptionsTail();
359:
360: return(0);
361: }
366: PetscErrorCode EPSPRIMMESetBlockSize_PRIMME(EPS eps,PetscInt bs)
367: {
368: EPS_PRIMME *ops = (EPS_PRIMME *) eps->data;
372: if (bs == PETSC_DEFAULT) ops->primme.maxBlockSize = 1;
373: else if (bs <= 0) {
374: SETERRQ(1, "PRIMME: wrong block size");
375: } else ops->primme.maxBlockSize = bs;
376:
377: return(0);
378: }
383: /*@
384: EPSPRIMMESetBlockSize - The maximum block size the code will try to use.
385: The user should set
386: this based on the architecture specifics of the target computer,
387: as well as any a priori knowledge of multiplicities. The code does
388: NOT require BlockSize > 1 to find multiple eigenvalues. For some
389: methods, keeping BlockSize = 1 yields the best overall performance.
391: Collective on EPS
393: Input Parameters:
394: + eps - the eigenproblem solver context
395: - bs - block size
397: Options Database Key:
398: . -eps_primme_block_size - Sets the max allowed block size value
400: Notes:
401: If the block size is not set, the value established by primme_initialize
402: is used.
404: Level: advanced
405: .seealso: EPSPRIMMEGetBlockSize()
406: @*/
407: PetscErrorCode EPSPRIMMESetBlockSize(EPS eps,PetscInt bs)
408: {
409: PetscErrorCode ierr, (*f)(EPS,PetscInt);
412:
414: PetscObjectQueryFunction((PetscObject)eps,"EPSPRIMMESetBlockSize_C",(void (**)())&f);
415: if (f) {
416: (*f)(eps,bs);
417: }
418:
419: return(0);
420: }
425: PetscErrorCode EPSPRIMMEGetBlockSize_PRIMME(EPS eps,PetscInt *bs)
426: {
427: EPS_PRIMME *ops = (EPS_PRIMME *) eps->data;
431: if (bs) *bs = ops->primme.maxBlockSize;
432:
433: return(0);
434: }
439: /*@
440: EPSPRIMMEGetBlockSize - Get the maximum block size the code will try to use.
441:
442: Collective on EPS
444: Input Parameters:
445: . eps - the eigenproblem solver context
446:
447: Output Parameters:
448: . bs - returned block size
450: Level: advanced
451: .seealso: EPSPRIMMESetBlockSize()
452: @*/
453: PetscErrorCode EPSPRIMMEGetBlockSize(EPS eps,PetscInt *bs)
454: {
455: PetscErrorCode ierr, (*f)(EPS,PetscInt*);
458:
460: PetscObjectQueryFunction((PetscObject)eps,"EPSPRIMMEGetBlockSize_C",(void (**)())&f);
461: if (f) {
462: (*f)(eps,bs);
463: }
464:
465: return(0);
466: }
471: PetscErrorCode EPSPRIMMESetMethod_PRIMME(EPS eps, EPSPRIMMEMethod method)
472: {
473: EPS_PRIMME *ops = (EPS_PRIMME *) eps->data;
477: if (method == PETSC_DEFAULT) ops->method = DEFAULT_MIN_TIME;
478: else ops->method = (primme_preset_method)method;
480: return(0);
481: }
486: /*@
487: EPSPRIMMESetMethod - Sets the method for the PRIMME library.
489: Collective on EPS
491: Input Parameters:
492: + eps - the eigenproblem solver context
493: - method - method that will be used by PRIMME. It must be one of:
494: EPSPRIMME_DYNAMIC, EPSPRIMME_DEFAULT_MIN_TIME(EPSPRIMME_JDQMR_ETOL),
495: EPSPRIMME_DEFAULT_MIN_MATVECS(EPSPRIMME_GD_OLSEN_PLUSK), EPSPRIMME_ARNOLDI,
496: EPSPRIMME_GD, EPSPRIMME_GD_PLUSK, EPSPRIMME_GD_OLSEN_PLUSK,
497: EPSPRIMME_JD_OLSEN_PLUSK, EPSPRIMME_RQI, EPSPRIMME_JDQR, EPSPRIMME_JDQMR,
498: EPSPRIMME_JDQMR_ETOL, EPSPRIMME_SUBSPACE_ITERATION,
499: EPSPRIMME_LOBPCG_ORTHOBASIS, EPSPRIMME_LOBPCG_ORTHOBASISW
501: Options Database Key:
502: . -eps_primme_set_method - Sets the method for the PRIMME library.
504: Note:
505: If not set, the method defaults to EPSPRIMME_DEFAULT_MIN_TIME.
507: Level: advanced
509: .seealso: EPSPRIMMEGetMethod(), EPSPRIMMEMethod
510: @*/
511: PetscErrorCode EPSPRIMMESetMethod(EPS eps, EPSPRIMMEMethod method)
512: {
513: PetscErrorCode ierr, (*f)(EPS,EPSPRIMMEMethod);
516:
518: PetscObjectQueryFunction((PetscObject)eps,"EPSPRIMMESetMethod_C",(void (**)())&f);
519: if (f) {
520: (*f)(eps,method);
521: }
522:
523: return(0);
524: }
529: PetscErrorCode EPSPRIMMEGetMethod_PRIMME(EPS eps, EPSPRIMMEMethod *method)
530: {
531: EPS_PRIMME *ops = (EPS_PRIMME *) eps->data;
535: if (method)
536: *method = (EPSPRIMMEMethod)ops->method;
538: return(0);
539: }
544: /*@C
545: EPSPRIMMEGetMethod - Gets the method for the PRIMME library.
547: Mon Collective on EPS
549: Input Parameters:
550: . eps - the eigenproblem solver context
551:
552: Output Parameters:
553: . method - method that will be used by PRIMME. It must be one of:
554: EPSPRIMME_DYNAMIC, EPSPRIMME_DEFAULT_MIN_TIME(EPSPRIMME_JDQMR_ETOL),
555: EPSPRIMME_DEFAULT_MIN_MATVECS(EPSPRIMME_GD_OLSEN_PLUSK), EPSPRIMME_ARNOLDI,
556: EPSPRIMME_GD, EPSPRIMME_GD_PLUSK, EPSPRIMME_GD_OLSEN_PLUSK,
557: EPSPRIMME_JD_OLSEN_PLUSK, EPSPRIMME_RQI, EPSPRIMME_JDQR, EPSPRIMME_JDQMR,
558: EPSPRIMME_JDQMR_ETOL, EPSPRIMME_SUBSPACE_ITERATION,
559: EPSPRIMME_LOBPCG_ORTHOBASIS, EPSPRIMME_LOBPCG_ORTHOBASISW
561: Level: advanced
563: .seealso: EPSPRIMMESetMethod(), EPSPRIMMEMethod
564: @*/
565: PetscErrorCode EPSPRIMMEGetMethod(EPS eps, EPSPRIMMEMethod *method)
566: {
567: PetscErrorCode ierr, (*f)(EPS,EPSPRIMMEMethod*);
570:
572: PetscObjectQueryFunction((PetscObject)eps,"EPSPRIMMEGetMethod_C",(void (**)())&f);
573: if (f) {
574: (*f)(eps,method);
575: }
576:
577: return(0);
578: }
584: PetscErrorCode EPSPRIMMESetPrecond_PRIMME(EPS eps, EPSPRIMMEPrecond precond)
585: {
586: EPS_PRIMME *ops = (EPS_PRIMME *) eps->data;
590: if (precond == EPSPRIMME_NONE) ops->primme.correctionParams.precondition = 0;
591: else ops->primme.correctionParams.precondition = 1;
592:
593: return(0);
594: }
599: /*@
600: EPSPRIMMESetPrecond - Sets the preconditioner to be used in the PRIMME
601: library. Currently, only diagonal preconditioning is supported.
603: Collective on EPS
605: Input Parameters:
606: + eps - the eigenproblem solver context
607: - precond - either EPSPRIMME_NONE (no preconditioning) or EPSPRIMME_DIAGONAL
608: (diagonal preconditioning)
610: Options Database Key:
611: . -eps_primme_precond - Sets either 'none' or 'diagonal' preconditioner
613: Note:
614: The default is no preconditioning.
615:
616: Level: advanced
618: .seealso: EPSPRIMMEGetPrecond(), EPSPRIMMEPrecond
619: @*/
620: PetscErrorCode EPSPRIMMESetPrecond(EPS eps, EPSPRIMMEPrecond precond)
621: {
622: PetscErrorCode ierr, (*f)(EPS, EPSPRIMMEPrecond);
625:
627: PetscObjectQueryFunction((PetscObject)eps,"EPSPRIMMESetPrecond_C",(void (**)())&f);
628: if (f) {
629: (*f)(eps, precond);
630: }
631:
632: return(0);
633: }
639: PetscErrorCode EPSPRIMMEGetPrecond_PRIMME(EPS eps, EPSPRIMMEPrecond *precond)
640: {
641: EPS_PRIMME *ops = (EPS_PRIMME *) eps->data;
645: if (precond)
646: *precond = ops->primme.correctionParams.precondition ? EPSPRIMME_DIAGONAL : EPSPRIMME_NONE;
647:
648: return(0);
649: }
654: /*@C
655: EPSPRIMMEGetPrecond - Gets the preconditioner to be used in the PRIMME
656: library.
658: Collective on EPS
660: Input Parameters:
661: . eps - the eigenproblem solver context
662:
663: Output Parameters:
664: . precond - either EPSPRIMME_NONE (no preconditioning) or EPSPRIMME_DIAGONAL
665: (diagonal preconditioning)
667: Level: advanced
669: .seealso: EPSPRIMMESetPrecond(), EPSPRIMMEPrecond
670: @*/
671: PetscErrorCode EPSPRIMMEGetPrecond(EPS eps, EPSPRIMMEPrecond *precond)
672: {
673: PetscErrorCode ierr, (*f)(EPS, EPSPRIMMEPrecond*);
676:
678: PetscObjectQueryFunction((PetscObject)eps,"EPSPRIMMEGetPrecond_C",(void (**)())&f);
679: if (f) {
680: (*f)(eps, precond);
681: }
682:
683: return(0);
684: }
690: PetscErrorCode EPSCreate_PRIMME(EPS eps)
691: {
693: EPS_PRIMME *primme;
696:
697: PetscNew(EPS_PRIMME,&primme);
698: PetscLogObjectMemory(eps,sizeof(EPS_PRIMME));
699: eps->data = (void *) primme;
700: eps->ops->solve = EPSSolve_PRIMME;
701: eps->ops->setup = EPSSetUp_PRIMME;
702: eps->ops->setfromoptions = EPSSetFromOptions_PRIMME;
703: eps->ops->destroy = EPSDestroy_PRIMME;
704: eps->ops->view = EPSView_PRIMME;
705: eps->ops->backtransform = EPSBackTransform_Default;
706: eps->ops->computevectors = EPSComputeVectors_Default;
708: primme_initialize(&primme->primme);
709: primme->primme.matrixMatvec = multMatvec_PRIMME;
710: primme->primme.globalSumDouble = par_GlobalSumDouble;
711: primme->method = (primme_preset_method)EPSPRIMME_DEFAULT_MIN_TIME;
712: PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSPRIMMESetBlockSize_C","EPSPRIMMESetBlockSize_PRIMME",EPSPRIMMESetBlockSize_PRIMME);
713: PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSPRIMMESetMethod_C","EPSPRIMMESetMethod_PRIMME",EPSPRIMMESetMethod_PRIMME);
714: PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSPRIMMESetPrecond_C","EPSPRIMMESetPrecond_PRIMME",EPSPRIMMESetPrecond_PRIMME);
715:
716: PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSPRIMMEGetBlockSize_C","EPSPRIMMEGetBlockSize_PRIMME",EPSPRIMMEGetBlockSize_PRIMME);
717: PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSPRIMMEGetMethod_C","EPSPRIMMEGetMethod_PRIMME",EPSPRIMMEGetMethod_PRIMME);
718: PetscObjectComposeFunctionDynamic((PetscObject)eps,"EPSPRIMMEGetPrecond_C","EPSPRIMMEGetPrecond_PRIMME",EPSPRIMMEGetPrecond_PRIMME);
720: eps->which = EPS_LARGEST_REAL;
722: return(0);
723: }