Actual source code: epsbasic.c

slepc-3.14.2 2021-02-01
Report Typos and Errors
  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: }