Actual source code: basic.c

  1: /*
  2:      The basic EPS routines, Create, View, etc. are here.

  4:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  5:       SLEPc - Scalable Library for Eigenvalue Problem Computations
  6:       Copyright (c) 2002-2007, Universidad Politecnica de Valencia, Spain

  8:       This file is part of SLEPc. See the README file for conditions of use
  9:       and additional information.
 10:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 11: */

 13:  #include src/eps/epsimpl.h

 15: PetscFList EPSList = 0;
 16: PetscCookie EPS_COOKIE = 0;
 17: PetscEvent EPS_SetUp = 0, EPS_Solve = 0, EPS_Dense = 0;

 21: /*@C
 22:   EPSInitializePackage - This function initializes everything in the EPS package. It is called
 23:   from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to EPSCreate()
 24:   when using static libraries.

 26:   Input Parameter:
 27:   path - The dynamic library path, or PETSC_NULL

 29:   Level: developer

 31: .seealso: SlepcInitialize()
 32: @*/
 33: PetscErrorCode EPSInitializePackage(char *path) {
 34:   static PetscTruth initialized = PETSC_FALSE;
 35:   char              logList[256];
 36:   char             *className;
 37:   PetscTruth        opt;

 41:   if (initialized) return(0);
 42:   initialized = PETSC_TRUE;
 43:   /* Register Classes */
 44:   PetscLogClassRegister(&EPS_COOKIE,"Eigenproblem Solver");
 45:   /* Register Constructors */
 46:   EPSRegisterAll(path);
 47:   /* Register Events */
 48:   PetscLogEventRegister(&EPS_SetUp,"EPSSetUp",EPS_COOKIE);
 49:   PetscLogEventRegister(&EPS_Solve,"EPSSolve",EPS_COOKIE);
 50:   PetscLogEventRegister(&EPS_Dense,"EPSDense",EPS_COOKIE);
 51:   /* Process info exclusions */
 52:   PetscOptionsGetString(PETSC_NULL, "-log_info_exclude", logList, 256, &opt);
 53:   if (opt) {
 54:     PetscStrstr(logList, "eps", &className);
 55:     if (className) {
 56:       PetscInfoDeactivateClass(EPS_COOKIE);
 57:     }
 58:   }
 59:   /* Process summary exclusions */
 60:   PetscOptionsGetString(PETSC_NULL, "-log_summary_exclude", logList, 256, &opt);
 61:   if (opt) {
 62:     PetscStrstr(logList, "eps", &className);
 63:     if (className) {
 64:       PetscLogEventDeactivateClass(EPS_COOKIE);
 65:     }
 66:   }
 67:   return(0);
 68: }

 72: /*@C
 73:    EPSView - Prints the EPS data structure.

 75:    Collective on EPS

 77:    Input Parameters:
 78: +  eps - the eigenproblem solver context
 79: -  viewer - optional visualization context

 81:    Options Database Key:
 82: .  -eps_view -  Calls EPSView() at end of EPSSolve()

 84:    Note:
 85:    The available visualization contexts include
 86: +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
 87: -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
 88:          output where only the first processor opens
 89:          the file.  All other processors send their 
 90:          data to the first processor to print. 

 92:    The user can open an alternative visualization context with
 93:    PetscViewerASCIIOpen() - output to a specified file.

 95:    Level: beginner

 97: .seealso: STView(), PetscViewerASCIIOpen()
 98: @*/
 99: PetscErrorCode EPSView(EPS eps,PetscViewer viewer)
100: {
102:   const char     *type, *which;
103:   PetscTruth     isascii;

107:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(eps->comm);

111: #if defined(PETSC_USE_COMPLEX)
112: #define HERM "hermitian"
113: #else
114: #define HERM "symmetric"
115: #endif
116:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
117:   if (isascii) {
118:     PetscViewerASCIIPrintf(viewer,"EPS Object:\n");
119:     switch (eps->problem_type) {
120:       case EPS_HEP:   type = HERM " eigenvalue problem"; break;
121:       case EPS_GHEP:  type = "generalized " HERM " eigenvalue problem"; break;
122:       case EPS_NHEP:  type = "non-" HERM " eigenvalue problem"; break;
123:       case EPS_GNHEP: type = "generalized non-" HERM " eigenvalue problem"; break;
124:       case 0:         type = "not yet set"; break;
125:       default: SETERRQ(1,"Wrong value of eps->problem_type");
126:     }
127:     PetscViewerASCIIPrintf(viewer,"  problem type: %s\n",type);
128:     EPSGetType(eps,&type);
129:     if (type) {
130:       PetscViewerASCIIPrintf(viewer,"  method: %s",type);
131:       switch (eps->solverclass) {
132:         case EPS_ONE_SIDE:
133:           PetscViewerASCIIPrintf(viewer,"\n",type); break;
134:         case EPS_TWO_SIDE:
135:           PetscViewerASCIIPrintf(viewer," (two-sided)\n",type); break;
136:         default: SETERRQ(1,"Wrong value of eps->solverclass");
137:       }
138:     } else {
139:       PetscViewerASCIIPrintf(viewer,"  method: not yet set\n");
140:     }
141:     if (eps->ops->view) {
142:       PetscViewerASCIIPushTab(viewer);
143:       (*eps->ops->view)(eps,viewer);
144:       PetscViewerASCIIPopTab(viewer);
145:     }
146:     switch (eps->which) {
147:       case EPS_LARGEST_MAGNITUDE:  which = "largest eigenvalues in magnitude"; break;
148:       case EPS_SMALLEST_MAGNITUDE: which = "smallest eigenvalues in magnitude"; break;
149:       case EPS_LARGEST_REAL:       which = "largest real parts"; break;
150:       case EPS_SMALLEST_REAL:      which = "smallest real parts"; break;
151:       case EPS_LARGEST_IMAGINARY:  which = "largest imaginary parts"; break;
152:       case EPS_SMALLEST_IMAGINARY: which = "smallest imaginary parts"; break;
153:       default: SETERRQ(1,"Wrong value of eps->which");
154:     }
155:     PetscViewerASCIIPrintf(viewer,"  selected portion of the spectrum: %s\n",which);
156:     PetscViewerASCIIPrintf(viewer,"  number of eigenvalues (nev): %d\n",eps->nev);
157:     PetscViewerASCIIPrintf(viewer,"  number of column vectors (ncv): %d\n",eps->ncv);
158:     PetscViewerASCIIPrintf(viewer,"  maximum number of iterations: %d\n", eps->max_it);
159:     PetscViewerASCIIPrintf(viewer,"  tolerance: %g\n",eps->tol);
160:     PetscViewerASCIIPrintf(viewer,"  dimension of user-provided deflation space: %d\n",eps->nds);
161:     PetscViewerASCIIPushTab(viewer);
162:     IPView(eps->ip,viewer);
163:     STView(eps->OP,viewer);
164:     PetscViewerASCIIPopTab(viewer);
165:   } else {
166:     if (eps->ops->view) {
167:       (*eps->ops->view)(eps,viewer);
168:     }
169:     STView(eps->OP,viewer);
170:   }
171:   return(0);
172: }

176: static PetscErrorCode EPSPublish_Petsc(PetscObject object)
177: {
179:   return(0);
180: }

184: /*@C
185:    EPSCreate - Creates the default EPS context.

187:    Collective on MPI_Comm

189:    Input Parameter:
190: .  comm - MPI communicator

192:    Output Parameter:
193: .  eps - location to put the EPS context

195:    Note:
196:    The default EPS type is EPSKRYLOVSCHUR

198:    Level: beginner

200: .seealso: EPSSetUp(), EPSSolve(), EPSDestroy(), EPS
201: @*/
202: PetscErrorCode EPSCreate(MPI_Comm comm,EPS *outeps)
203: {
205:   EPS            eps;

209:   *outeps = 0;

211:   PetscHeaderCreate(eps,_p_EPS,struct _EPSOps,EPS_COOKIE,-1,"EPS",comm,EPSDestroy,EPSView);
212:   *outeps = eps;

214:   eps->bops->publish   = EPSPublish_Petsc;
215:   PetscMemzero(eps->ops,sizeof(struct _EPSOps));

217:   eps->type            = -1;
218:   eps->max_it          = 0;
219:   eps->nev             = 1;
220:   eps->ncv             = 0;
221:   eps->allocated_ncv   = 0;
222:   eps->nds             = 0;
223:   eps->tol             = 1e-7;
224:   eps->which           = EPS_LARGEST_MAGNITUDE;
225:   eps->evecsavailable  = PETSC_FALSE;
226:   eps->problem_type    = (EPSProblemType)0;
227:   eps->solverclass     = (EPSClass)0;

229:   eps->vec_initial     = 0;
230:   eps->vec_initial_left= 0;
231:   eps->V               = 0;
232:   eps->AV              = 0;
233:   eps->W               = 0;
234:   eps->AW              = 0;
235:   eps->T               = 0;
236:   eps->DS              = 0;
237:   eps->ds_ortho        = PETSC_TRUE;
238:   eps->eigr            = 0;
239:   eps->eigi            = 0;
240:   eps->errest          = 0;
241:   eps->errest_left     = 0;
242:   eps->OP              = 0;
243:   eps->ip              = 0;
244:   eps->data            = 0;
245:   eps->nconv           = 0;
246:   eps->its             = 0;
247:   eps->perm            = PETSC_NULL;

249:   eps->nwork           = 0;
250:   eps->work            = 0;
251:   eps->isgeneralized   = PETSC_FALSE;
252:   eps->ishermitian     = PETSC_FALSE;
253:   eps->ispositive      = PETSC_FALSE;
254:   eps->setupcalled     = 0;
255:   eps->reason          = EPS_CONVERGED_ITERATING;

257:   eps->numbermonitors  = 0;

259:   STCreate(comm,&eps->OP);
260:   PetscLogObjectParent(eps,eps->OP);
261:   IPCreate(comm,&eps->ip);
262:   IPSetOptionsPrefix(eps->ip,eps->prefix);
263:   IPAppendOptionsPrefix(eps->ip,"eps_");
264:   PetscLogObjectParent(eps,eps->ip);
265:   PetscPublishAll(eps);
266:   return(0);
267: }
268: 
271: /*@C
272:    EPSSetType - Selects the particular solver to be used in the EPS object. 

274:    Collective on EPS

276:    Input Parameters:
277: +  eps      - the eigensolver context
278: -  type     - a known method

280:    Options Database Key:
281: .  -eps_type <method> - Sets the method; use -help for a list 
282:     of available methods 
283:     
284:    Notes:  
285:    See "slepc/include/slepceps.h" for available methods. The default
286:    is EPSKRYLOVSCHUR.

288:    Normally, it is best to use the EPSSetFromOptions() command and
289:    then set the EPS type from the options database rather than by using
290:    this routine.  Using the options database provides the user with
291:    maximum flexibility in evaluating the different available methods.
292:    The EPSSetType() routine is provided for those situations where it
293:    is necessary to set the iterative solver independently of the command
294:    line or options database. 

296:    Level: intermediate

298: .seealso: STSetType(), EPSType
299: @*/
300: PetscErrorCode EPSSetType(EPS eps,EPSType type)
301: {
302:   PetscErrorCode ierr,(*r)(EPS);
303:   PetscTruth match;


309:   PetscTypeCompare((PetscObject)eps,type,&match);
310:   if (match) return(0);

312:   if (eps->data) {
313:     /* destroy the old private EPS context */
314:     (*eps->ops->destroy)(eps);
315:     eps->data = 0;
316:   }

318:   PetscFListFind(EPSList,eps->comm,type,(void (**)(void)) &r);

320:   if (!r) SETERRQ1(1,"Unknown EPS type given: %s",type);

322:   eps->setupcalled = 0;
323:   PetscMemzero(eps->ops,sizeof(struct _EPSOps));
324:   (*r)(eps);

326:   PetscObjectChangeTypeName((PetscObject)eps,type);
327:   return(0);
328: }

332: /*@C
333:    EPSGetType - Gets the EPS type as a string from the EPS object.

335:    Not Collective

337:    Input Parameter:
338: .  eps - the eigensolver context 

340:    Output Parameter:
341: .  name - name of EPS method 

343:    Level: intermediate

345: .seealso: EPSSetType()
346: @*/
347: PetscErrorCode EPSGetType(EPS eps,EPSType *type)
348: {
351:   *type = eps->type_name;
352:   return(0);
353: }

355: /*MC
356:    EPSRegisterDynamic - Adds a method to the eigenproblem solver package.

358:    Synopsis:
359:    EPSRegisterDynamic(char *name_solver,char *path,char *name_create,int (*routine_create)(EPS))

361:    Not Collective

363:    Input Parameters:
364: +  name_solver - name of a new user-defined solver
365: .  path - path (either absolute or relative) the library containing this solver
366: .  name_create - name of routine to create the solver context
367: -  routine_create - routine to create the solver context

369:    Notes:
370:    EPSRegisterDynamic() may be called multiple times to add several user-defined solvers.

372:    If dynamic libraries are used, then the fourth input argument (routine_create)
373:    is ignored.

375:    Sample usage:
376: .vb
377:    EPSRegisterDynamic("my_solver",/home/username/my_lib/lib/libO/solaris/mylib.a,
378:                "MySolverCreate",MySolverCreate);
379: .ve

381:    Then, your solver can be chosen with the procedural interface via
382: $     EPSSetType(eps,"my_solver")
383:    or at runtime via the option
384: $     -eps_type my_solver

386:    Level: advanced

388:    Environmental variables such as ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR},
389:    and others of the form ${any_environmental_variable} occuring in pathname will be 
390:    replaced with appropriate values.

392: .seealso: EPSRegisterDestroy(), EPSRegisterAll()

394: M*/

398: /*@C
399:   EPSRegister - See EPSRegisterDynamic()

401:   Level: advanced
402: @*/
403: PetscErrorCode EPSRegister(const char *sname,const char *path,const char *name,int (*function)(EPS))
404: {
406:   char           fullname[256];

409:   PetscFListConcat(path,name,fullname);
410:   PetscFListAdd(&EPSList,sname,fullname,(void (*)(void))function);
411:   return(0);
412: }

416: /*@
417:    EPSRegisterDestroy - Frees the list of EPS methods that were
418:    registered by EPSRegisterDynamic().

420:    Not Collective

422:    Level: advanced

424: .seealso: EPSRegisterDynamic(), EPSRegisterAll()
425: @*/
426: PetscErrorCode EPSRegisterDestroy(void)
427: {

431:   PetscFListDestroy(&EPSList);
432:   EPSRegisterAll(PETSC_NULL);
433:   return(0);
434: }

438: /*@
439:    EPSDestroy - Destroys the EPS context.

441:    Collective on EPS

443:    Input Parameter:
444: .  eps - eigensolver context obtained from EPSCreate()

446:    Level: beginner

448: .seealso: EPSCreate(), EPSSetUp(), EPSSolve()
449: @*/
450: PetscErrorCode EPSDestroy(EPS eps)
451: {

456:   if (--eps->refct > 0) return(0);

458:   /* if memory was published with AMS then destroy it */
459:   PetscObjectDepublish(eps);

461:   STDestroy(eps->OP);
462:   IPDestroy(eps->ip);

464:   if (eps->ops->destroy) {
465:     (*eps->ops->destroy)(eps);
466:   }
467: 
468:   PetscFree(eps->T);
469:   PetscFree(eps->Tl);
470:   PetscFree(eps->perm);

472:   if (eps->vec_initial) {
473:     VecDestroy(eps->vec_initial);
474:   }

476:   if (eps->vec_initial_left) {
477:     VecDestroy(eps->vec_initial_left);
478:   }

480:   if (eps->nds > 0) {
481:     VecDestroyVecs(eps->DS, eps->nds);
482:   }
483: 
484:   PetscFree(eps->DSV);

486:   EPSMonitorCancel(eps);

488:   PetscHeaderDestroy(eps);
489:   return(0);
490: }

494: /*@
495:    EPSSetST - Associates a spectral transformation object to the
496:    eigensolver. 

498:    Collective on EPS

500:    Input Parameters:
501: +  eps - eigensolver context obtained from EPSCreate()
502: -  st   - the spectral transformation object

504:    Note:
505:    Use EPSGetST() to retrieve the spectral transformation context (for example,
506:    to free it at the end of the computations).

508:    Level: advanced

510: .seealso: EPSGetST()
511: @*/
512: PetscErrorCode EPSSetST(EPS eps,ST st)
513: {

520:   PetscObjectReference((PetscObject)st);
521:   STDestroy(eps->OP);
522:   eps->OP = st;
523:   return(0);
524: }

528: /*@C
529:    EPSGetST - Obtain the spectral transformation (ST) object associated
530:    to the eigensolver object.

532:    Not Collective

534:    Input Parameters:
535: .  eps - eigensolver context obtained from EPSCreate()

537:    Output Parameter:
538: .  st - spectral transformation context

540:    Level: beginner

542: .seealso: EPSSetST()
543: @*/
544: PetscErrorCode EPSGetST(EPS eps, ST *st)
545: {
549:   *st = eps->OP;
550:   return(0);
551: }

555: /*@
556:    EPSSetIP - Associates an inner product object to the
557:    eigensolver. 

559:    Collective on EPS

561:    Input Parameters:
562: +  eps - eigensolver context obtained from EPSCreate()
563: -  ip  - the inner product object

565:    Note:
566:    Use EPSGetIP() to retrieve the inner product context (for example,
567:    to free it at the end of the computations).

569:    Level: advanced

571: .seealso: EPSGetIP()
572: @*/
573: PetscErrorCode EPSSetIP(EPS eps,IP ip)
574: {

581:   PetscObjectReference((PetscObject)ip);
582:   IPDestroy(eps->ip);
583:   eps->ip = ip;
584:   return(0);
585: }

589: /*@C
590:    EPSGetIP - Obtain the inner product object associated
591:    to the eigensolver object.

593:    Not Collective

595:    Input Parameters:
596: .  eps - eigensolver context obtained from EPSCreate()

598:    Output Parameter:
599: .  ip - inner product context

601:    Level: advanced

603: .seealso: EPSSetIP()
604: @*/
605: PetscErrorCode EPSGetIP(EPS eps,IP *ip)
606: {
610:   *ip = eps->ip;
611:   return(0);
612: }

616: /*@
617:    EPSIsGeneralized - Ask if the EPS object corresponds to a generalized 
618:    eigenvalue problem.

620:    Not collective

622:    Input Parameter:
623: .  eps - the eigenproblem solver context

625:    Output Parameter:
626: .  is - the answer

628:    Level: intermediate

630: @*/
631: PetscErrorCode EPSIsGeneralized(EPS eps,PetscTruth* is)
632: {
634:   Mat            B;

638:   STGetOperators(eps->OP,PETSC_NULL,&B);
639:   if( B ) *is = PETSC_TRUE;
640:   else *is = PETSC_FALSE;
641:   if( eps->setupcalled ) {
642:     if( eps->isgeneralized != *is ) {
643:       SETERRQ(0,"Warning: Inconsistent EPS state");
644:     }
645:   }
646:   return(0);
647: }

651: /*@
652:    EPSIsHermitian - Ask if the EPS object corresponds to a Hermitian 
653:    eigenvalue problem.

655:    Not collective

657:    Input Parameter:
658: .  eps - the eigenproblem solver context

660:    Output Parameter:
661: .  is - the answer

663:    Level: intermediate

665: @*/
666: PetscErrorCode EPSIsHermitian(EPS eps,PetscTruth* is)
667: {
670:   if( eps->ishermitian ) *is = PETSC_TRUE;
671:   else *is = PETSC_FALSE;
672:   return(0);
673: }