Actual source code: epsbasic.c
slepc-3.14.2 2021-02-01
1: /*
2: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3: SLEPc - Scalable Library for Eigenvalue Problem Computations
4: Copyright (c) 2002-2020, Universitat Politecnica de Valencia, Spain
6: This file is part of SLEPc.
7: SLEPc is distributed under a 2-clause BSD license (see LICENSE).
8: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
9: */
10: /*
11: Basic EPS routines
12: */
14: #include <slepc/private/epsimpl.h>
16: PetscFunctionList EPSList = 0;
17: PetscBool EPSRegisterAllCalled = PETSC_FALSE;
18: PetscClassId EPS_CLASSID = 0;
19: PetscLogEvent EPS_SetUp = 0,EPS_Solve = 0;
21: /*@
22: EPSCreate - Creates the default EPS context.
24: Collective
26: Input Parameter:
27: . comm - MPI communicator
29: Output Parameter:
30: . eps - location to put the EPS context
32: Note:
33: The default EPS type is EPSKRYLOVSCHUR
35: Level: beginner
37: .seealso: EPSSetUp(), EPSSolve(), EPSDestroy(), EPS
38: @*/
39: PetscErrorCode EPSCreate(MPI_Comm comm,EPS *outeps)
40: {
42: EPS eps;
46: *outeps = 0;
47: EPSInitializePackage();
48: SlepcHeaderCreate(eps,EPS_CLASSID,"EPS","Eigenvalue Problem Solver","EPS",comm,EPSDestroy,EPSView);
50: eps->max_it = PETSC_DEFAULT;
51: eps->nev = 1;
52: eps->ncv = PETSC_DEFAULT;
53: eps->mpd = PETSC_DEFAULT;
54: eps->nini = 0;
55: eps->nds = 0;
56: eps->target = 0.0;
57: eps->tol = PETSC_DEFAULT;
58: eps->conv = EPS_CONV_REL;
59: eps->stop = EPS_STOP_BASIC;
60: eps->which = (EPSWhich)0;
61: eps->inta = 0.0;
62: eps->intb = 0.0;
63: eps->problem_type = (EPSProblemType)0;
64: eps->extraction = EPS_RITZ;
65: eps->balance = EPS_BALANCE_NONE;
66: eps->balance_its = 5;
67: eps->balance_cutoff = 1e-8;
68: eps->trueres = PETSC_FALSE;
69: eps->trackall = PETSC_FALSE;
70: eps->purify = PETSC_TRUE;
71: eps->twosided = PETSC_FALSE;
73: eps->converged = EPSConvergedRelative;
74: eps->convergeduser = NULL;
75: eps->convergeddestroy= NULL;
76: eps->stopping = EPSStoppingBasic;
77: eps->stoppinguser = NULL;
78: eps->stoppingdestroy = NULL;
79: eps->arbitrary = NULL;
80: eps->convergedctx = NULL;
81: eps->stoppingctx = NULL;
82: eps->arbitraryctx = NULL;
83: eps->numbermonitors = 0;
85: eps->st = NULL;
86: eps->ds = NULL;
87: eps->dsts = NULL;
88: eps->V = NULL;
89: eps->W = NULL;
90: eps->rg = NULL;
91: eps->D = NULL;
92: eps->IS = NULL;
93: eps->ISL = NULL;
94: eps->defl = NULL;
95: eps->eigr = NULL;
96: eps->eigi = NULL;
97: eps->errest = NULL;
98: eps->rr = NULL;
99: eps->ri = NULL;
100: eps->perm = NULL;
101: eps->nwork = 0;
102: eps->work = NULL;
103: eps->data = NULL;
105: eps->state = EPS_STATE_INITIAL;
106: eps->categ = EPS_CATEGORY_KRYLOV;
107: eps->nconv = 0;
108: eps->its = 0;
109: eps->nloc = 0;
110: eps->nrma = 0.0;
111: eps->nrmb = 0.0;
112: eps->useds = PETSC_FALSE;
113: eps->isgeneralized = PETSC_FALSE;
114: eps->ispositive = PETSC_FALSE;
115: eps->ishermitian = PETSC_FALSE;
116: eps->reason = EPS_CONVERGED_ITERATING;
118: PetscNewLog(eps,&eps->sc);
119: *outeps = eps;
120: return(0);
121: }
123: /*@C
124: EPSSetType - Selects the particular solver to be used in the EPS object.
126: Logically Collective on eps
128: Input Parameters:
129: + eps - the eigensolver context
130: - type - a known method
132: Options Database Key:
133: . -eps_type <method> - Sets the method; use -help for a list
134: of available methods
136: Notes:
137: See "slepc/include/slepceps.h" for available methods. The default
138: is EPSKRYLOVSCHUR.
140: Normally, it is best to use the EPSSetFromOptions() command and
141: then set the EPS type from the options database rather than by using
142: this routine. Using the options database provides the user with
143: maximum flexibility in evaluating the different available methods.
144: The EPSSetType() routine is provided for those situations where it
145: is necessary to set the iterative solver independently of the command
146: line or options database.
148: Level: intermediate
150: .seealso: STSetType(), EPSType
151: @*/
152: PetscErrorCode EPSSetType(EPS eps,EPSType type)
153: {
154: PetscErrorCode ierr,(*r)(EPS);
155: PetscBool match;
161: PetscObjectTypeCompare((PetscObject)eps,type,&match);
162: if (match) return(0);
164: PetscFunctionListFind(EPSList,type,&r);
165: if (!r) SETERRQ1(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown EPS type given: %s",type);
167: if (eps->ops->destroy) { (*eps->ops->destroy)(eps); }
168: PetscMemzero(eps->ops,sizeof(struct _EPSOps));
170: eps->state = EPS_STATE_INITIAL;
171: PetscObjectChangeTypeName((PetscObject)eps,type);
172: (*r)(eps);
173: return(0);
174: }
176: /*@C
177: EPSGetType - Gets the EPS type as a string from the EPS object.
179: Not Collective
181: Input Parameter:
182: . eps - the eigensolver context
184: Output Parameter:
185: . name - name of EPS method
187: Level: intermediate
189: .seealso: EPSSetType()
190: @*/
191: PetscErrorCode EPSGetType(EPS eps,EPSType *type)
192: {
196: *type = ((PetscObject)eps)->type_name;
197: return(0);
198: }
200: /*@C
201: EPSRegister - Adds a method to the eigenproblem solver package.
203: Not Collective
205: Input Parameters:
206: + name - name of a new user-defined solver
207: - function - routine to create the solver context
209: Notes:
210: EPSRegister() may be called multiple times to add several user-defined solvers.
212: Sample usage:
213: .vb
214: EPSRegister("my_solver",MySolverCreate);
215: .ve
217: Then, your solver can be chosen with the procedural interface via
218: $ EPSSetType(eps,"my_solver")
219: or at runtime via the option
220: $ -eps_type my_solver
222: Level: advanced
224: .seealso: EPSRegisterAll()
225: @*/
226: PetscErrorCode EPSRegister(const char *name,PetscErrorCode (*function)(EPS))
227: {
231: EPSInitializePackage();
232: PetscFunctionListAdd(&EPSList,name,function);
233: return(0);
234: }
236: /*@
237: EPSReset - Resets the EPS context to the initial state (prior to setup)
238: and destroys any allocated Vecs and Mats.
240: Collective on eps
242: Input Parameter:
243: . eps - eigensolver context obtained from EPSCreate()
245: Note:
246: This can be used when a problem of different matrix size wants to be solved.
247: All options that have previously been set are preserved, so in a next use
248: the solver configuration is the same, but new sizes for matrices and vectors
249: are allowed.
251: Level: advanced
253: .seealso: EPSDestroy()
254: @*/
255: PetscErrorCode EPSReset(EPS eps)
256: {
261: if (!eps) return(0);
262: if (eps->ops->reset) { (eps->ops->reset)(eps); }
263: if (eps->st) { STReset(eps->st); }
264: VecDestroy(&eps->D);
265: BVDestroy(&eps->V);
266: BVDestroy(&eps->W);
267: VecDestroyVecs(eps->nwork,&eps->work);
268: eps->nwork = 0;
269: eps->state = EPS_STATE_INITIAL;
270: return(0);
271: }
273: /*@
274: EPSDestroy - Destroys the EPS context.
276: Collective on eps
278: Input Parameter:
279: . eps - eigensolver context obtained from EPSCreate()
281: Level: beginner
283: .seealso: EPSCreate(), EPSSetUp(), EPSSolve()
284: @*/
285: PetscErrorCode EPSDestroy(EPS *eps)
286: {
290: if (!*eps) return(0);
292: if (--((PetscObject)(*eps))->refct > 0) { *eps = 0; return(0); }
293: EPSReset(*eps);
294: if ((*eps)->ops->destroy) { (*(*eps)->ops->destroy)(*eps); }
295: if ((*eps)->eigr) {
296: PetscFree4((*eps)->eigr,(*eps)->eigi,(*eps)->errest,(*eps)->perm);
297: }
298: if ((*eps)->rr) {
299: PetscFree2((*eps)->rr,(*eps)->ri);
300: }
301: STDestroy(&(*eps)->st);
302: RGDestroy(&(*eps)->rg);
303: DSDestroy(&(*eps)->ds);
304: DSDestroy(&(*eps)->dsts);
305: PetscFree((*eps)->sc);
306: /* just in case the initial vectors have not been used */
307: SlepcBasisDestroy_Private(&(*eps)->nds,&(*eps)->defl);
308: SlepcBasisDestroy_Private(&(*eps)->nini,&(*eps)->IS);
309: SlepcBasisDestroy_Private(&(*eps)->ninil,&(*eps)->ISL);
310: if ((*eps)->convergeddestroy) {
311: (*(*eps)->convergeddestroy)((*eps)->convergedctx);
312: }
313: EPSMonitorCancel(*eps);
314: PetscHeaderDestroy(eps);
315: return(0);
316: }
318: /*@
319: EPSSetTarget - Sets the value of the target.
321: Logically Collective on eps
323: Input Parameters:
324: + eps - eigensolver context
325: - target - the value of the target
327: Options Database Key:
328: . -eps_target <scalar> - the value of the target
330: Notes:
331: The target is a scalar value used to determine the portion of the spectrum
332: of interest. It is used in combination with EPSSetWhichEigenpairs().
334: In the case of complex scalars, a complex value can be provided in the
335: command line with [+/-][realnumber][+/-]realnumberi with no spaces, e.g.
336: -eps_target 1.0+2.0i
338: Level: intermediate
340: .seealso: EPSGetTarget(), EPSSetWhichEigenpairs()
341: @*/
342: PetscErrorCode EPSSetTarget(EPS eps,PetscScalar target)
343: {
349: eps->target = target;
350: if (!eps->st) { EPSGetST(eps,&eps->st); }
351: STSetDefaultShift(eps->st,target);
352: return(0);
353: }
355: /*@
356: EPSGetTarget - Gets the value of the target.
358: Not Collective
360: Input Parameter:
361: . eps - eigensolver context
363: Output Parameter:
364: . target - the value of the target
366: Note:
367: If the target was not set by the user, then zero is returned.
369: Level: intermediate
371: .seealso: EPSSetTarget()
372: @*/
373: PetscErrorCode EPSGetTarget(EPS eps,PetscScalar* target)
374: {
378: *target = eps->target;
379: return(0);
380: }
382: /*@
383: EPSSetInterval - Defines the computational interval for spectrum slicing.
385: Logically Collective on eps
387: Input Parameters:
388: + eps - eigensolver context
389: . inta - left end of the interval
390: - intb - right end of the interval
392: Options Database Key:
393: . -eps_interval <a,b> - set [a,b] as the interval of interest
395: Notes:
396: Spectrum slicing is a technique employed for computing all eigenvalues of
397: symmetric eigenproblems in a given interval. This function provides the
398: interval to be considered. It must be used in combination with EPS_ALL, see
399: EPSSetWhichEigenpairs().
401: In the command-line option, two values must be provided. For an open interval,
402: one can give an infinite, e.g., -eps_interval 1.0,inf or -eps_interval -inf,1.0.
403: An open interval in the programmatic interface can be specified with
404: PETSC_MAX_REAL and -PETSC_MAX_REAL.
406: Level: intermediate
408: .seealso: EPSGetInterval(), EPSSetWhichEigenpairs()
409: @*/
410: PetscErrorCode EPSSetInterval(EPS eps,PetscReal inta,PetscReal intb)
411: {
416: if (inta>=intb) SETERRQ(PetscObjectComm((PetscObject)eps),PETSC_ERR_ARG_WRONG,"Badly defined interval, must be inta<intb");
417: if (eps->inta != inta || eps->intb != intb) {
418: eps->inta = inta;
419: eps->intb = intb;
420: eps->state = EPS_STATE_INITIAL;
421: }
422: return(0);
423: }
425: /*@
426: EPSGetInterval - Gets the computational interval for spectrum slicing.
428: Not Collective
430: Input Parameter:
431: . eps - eigensolver context
433: Output Parameters:
434: + inta - left end of the interval
435: - intb - right end of the interval
437: Level: intermediate
439: Note:
440: If the interval was not set by the user, then zeros are returned.
442: .seealso: EPSSetInterval()
443: @*/
444: PetscErrorCode EPSGetInterval(EPS eps,PetscReal* inta,PetscReal* intb)
445: {
448: if (inta) *inta = eps->inta;
449: if (intb) *intb = eps->intb;
450: return(0);
451: }
453: /*@
454: EPSSetST - Associates a spectral transformation object to the eigensolver.
456: Collective on eps
458: Input Parameters:
459: + eps - eigensolver context obtained from EPSCreate()
460: - st - the spectral transformation object
462: Note:
463: Use EPSGetST() to retrieve the spectral transformation context (for example,
464: to free it at the end of the computations).
466: Level: advanced
468: .seealso: EPSGetST()
469: @*/
470: PetscErrorCode EPSSetST(EPS eps,ST st)
471: {
478: PetscObjectReference((PetscObject)st);
479: STDestroy(&eps->st);
480: eps->st = st;
481: PetscLogObjectParent((PetscObject)eps,(PetscObject)eps->st);
482: return(0);
483: }
485: /*@
486: EPSGetST - Obtain the spectral transformation (ST) object associated
487: to the eigensolver object.
489: Not Collective
491: Input Parameters:
492: . eps - eigensolver context obtained from EPSCreate()
494: Output Parameter:
495: . st - spectral transformation context
497: Level: intermediate
499: .seealso: EPSSetST()
500: @*/
501: PetscErrorCode EPSGetST(EPS eps,ST *st)
502: {
508: if (!eps->st) {
509: STCreate(PetscObjectComm((PetscObject)eps),&eps->st);
510: PetscObjectIncrementTabLevel((PetscObject)eps->st,(PetscObject)eps,0);
511: PetscLogObjectParent((PetscObject)eps,(PetscObject)eps->st);
512: PetscObjectSetOptions((PetscObject)eps->st,((PetscObject)eps)->options);
513: }
514: *st = eps->st;
515: return(0);
516: }
518: /*@
519: EPSSetBV - Associates a basis vectors object to the eigensolver.
521: Collective on eps
523: Input Parameters:
524: + eps - eigensolver context obtained from EPSCreate()
525: - V - the basis vectors object
527: Level: advanced
529: .seealso: EPSGetBV()
530: @*/
531: PetscErrorCode EPSSetBV(EPS eps,BV V)
532: {
539: PetscObjectReference((PetscObject)V);
540: BVDestroy(&eps->V);
541: eps->V = V;
542: PetscLogObjectParent((PetscObject)eps,(PetscObject)eps->V);
543: return(0);
544: }
546: /*@
547: EPSGetBV - Obtain the basis vectors object associated to the eigensolver object.
549: Not Collective
551: Input Parameters:
552: . eps - eigensolver context obtained from EPSCreate()
554: Output Parameter:
555: . V - basis vectors context
557: Level: advanced
559: .seealso: EPSSetBV()
560: @*/
561: PetscErrorCode EPSGetBV(EPS eps,BV *V)
562: {
568: if (!eps->V) {
569: BVCreate(PetscObjectComm((PetscObject)eps),&eps->V);
570: PetscObjectIncrementTabLevel((PetscObject)eps->V,(PetscObject)eps,0);
571: PetscLogObjectParent((PetscObject)eps,(PetscObject)eps->V);
572: PetscObjectSetOptions((PetscObject)eps->V,((PetscObject)eps)->options);
573: }
574: *V = eps->V;
575: return(0);
576: }
578: /*@
579: EPSSetRG - Associates a region object to the eigensolver.
581: Collective on eps
583: Input Parameters:
584: + eps - eigensolver context obtained from EPSCreate()
585: - rg - the region object
587: Note:
588: Use EPSGetRG() to retrieve the region context (for example,
589: to free it at the end of the computations).
591: Level: advanced
593: .seealso: EPSGetRG()
594: @*/
595: PetscErrorCode EPSSetRG(EPS eps,RG rg)
596: {
603: PetscObjectReference((PetscObject)rg);
604: RGDestroy(&eps->rg);
605: eps->rg = rg;
606: PetscLogObjectParent((PetscObject)eps,(PetscObject)eps->rg);
607: return(0);
608: }
610: /*@
611: EPSGetRG - Obtain the region object associated to the eigensolver.
613: Not Collective
615: Input Parameters:
616: . eps - eigensolver context obtained from EPSCreate()
618: Output Parameter:
619: . rg - region context
621: Level: advanced
623: .seealso: EPSSetRG()
624: @*/
625: PetscErrorCode EPSGetRG(EPS eps,RG *rg)
626: {
632: if (!eps->rg) {
633: RGCreate(PetscObjectComm((PetscObject)eps),&eps->rg);
634: PetscObjectIncrementTabLevel((PetscObject)eps->rg,(PetscObject)eps,0);
635: PetscLogObjectParent((PetscObject)eps,(PetscObject)eps->rg);
636: PetscObjectSetOptions((PetscObject)eps->rg,((PetscObject)eps)->options);
637: }
638: *rg = eps->rg;
639: return(0);
640: }
642: /*@
643: EPSSetDS - Associates a direct solver object to the eigensolver.
645: Collective on eps
647: Input Parameters:
648: + eps - eigensolver context obtained from EPSCreate()
649: - ds - the direct solver object
651: Note:
652: Use EPSGetDS() to retrieve the direct solver context (for example,
653: to free it at the end of the computations).
655: Level: advanced
657: .seealso: EPSGetDS()
658: @*/
659: PetscErrorCode EPSSetDS(EPS eps,DS ds)
660: {
667: PetscObjectReference((PetscObject)ds);
668: DSDestroy(&eps->ds);
669: eps->ds = ds;
670: PetscLogObjectParent((PetscObject)eps,(PetscObject)eps->ds);
671: return(0);
672: }
674: /*@
675: EPSGetDS - Obtain the direct solver object associated to the eigensolver object.
677: Not Collective
679: Input Parameters:
680: . eps - eigensolver context obtained from EPSCreate()
682: Output Parameter:
683: . ds - direct solver context
685: Level: advanced
687: .seealso: EPSSetDS()
688: @*/
689: PetscErrorCode EPSGetDS(EPS eps,DS *ds)
690: {
696: if (!eps->ds) {
697: DSCreate(PetscObjectComm((PetscObject)eps),&eps->ds);
698: PetscObjectIncrementTabLevel((PetscObject)eps->ds,(PetscObject)eps,0);
699: PetscLogObjectParent((PetscObject)eps,(PetscObject)eps->ds);
700: PetscObjectSetOptions((PetscObject)eps->ds,((PetscObject)eps)->options);
701: }
702: *ds = eps->ds;
703: return(0);
704: }
706: /*@
707: EPSIsGeneralized - Ask if the EPS object corresponds to a generalized
708: eigenvalue problem.
710: Not collective
712: Input Parameter:
713: . eps - the eigenproblem solver context
715: Output Parameter:
716: . is - the answer
718: Level: intermediate
720: .seealso: EPSIsHermitian(), EPSIsPositive()
721: @*/
722: PetscErrorCode EPSIsGeneralized(EPS eps,PetscBool* is)
723: {
727: *is = eps->isgeneralized;
728: return(0);
729: }
731: /*@
732: EPSIsHermitian - Ask if the EPS object corresponds to a Hermitian
733: eigenvalue problem.
735: Not collective
737: Input Parameter:
738: . eps - the eigenproblem solver context
740: Output Parameter:
741: . is - the answer
743: Level: intermediate
745: .seealso: EPSIsGeneralized(), EPSIsPositive()
746: @*/
747: PetscErrorCode EPSIsHermitian(EPS eps,PetscBool* is)
748: {
752: *is = eps->ishermitian;
753: return(0);
754: }
756: /*@
757: EPSIsPositive - Ask if the EPS object corresponds to an eigenvalue
758: problem type that requires a positive (semi-) definite matrix B.
760: Not collective
762: Input Parameter:
763: . eps - the eigenproblem solver context
765: Output Parameter:
766: . is - the answer
768: Level: intermediate
770: .seealso: EPSIsGeneralized(), EPSIsHermitian()
771: @*/
772: PetscErrorCode EPSIsPositive(EPS eps,PetscBool* is)
773: {
777: *is = eps->ispositive;
778: return(0);
779: }