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