Actual source code: qepbasic.c

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

  4:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  5:    SLEPc - Scalable Library for Eigenvalue Problem Computations
  6:    Copyright (c) 2002-2011, Universitat 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/qepimpl.h>      /*I "slepcqep.h" I*/

 26: PetscFList       QEPList = 0;
 27: PetscBool        QEPRegisterAllCalled = PETSC_FALSE;
 28: PetscClassId     QEP_CLASSID = 0;
 29: PetscLogEvent    QEP_SetUp = 0,QEP_Solve = 0,QEP_Dense = 0;
 30: static PetscBool QEPPackageInitialized = PETSC_FALSE;

 34: /*@C
 35:    QEPFinalizePackage - This function destroys everything in the Slepc interface
 36:    to the QEP package. It is called from SlepcFinalize().

 38:    Level: developer

 40: .seealso: SlepcFinalize()
 41: @*/
 42: PetscErrorCode QEPFinalizePackage(void)
 43: {
 45:   QEPPackageInitialized = PETSC_FALSE;
 46:   QEPList               = 0;
 47:   QEPRegisterAllCalled  = PETSC_FALSE;
 48:   return(0);
 49: }

 53: /*@C
 54:    QEPInitializePackage - This function initializes everything in the QEP package. It is called
 55:    from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to QEPCreate()
 56:    when using static libraries.

 58:    Input Parameter:
 59: .  path - The dynamic library path, or PETSC_NULL

 61:    Level: developer

 63: .seealso: SlepcInitialize()
 64: @*/
 65: PetscErrorCode QEPInitializePackage(const char *path)
 66: {
 67:   char           logList[256];
 68:   char           *className;
 69:   PetscBool      opt;

 73:   if (QEPPackageInitialized) return(0);
 74:   QEPPackageInitialized = PETSC_TRUE;
 75:   /* Register Classes */
 76:   PetscClassIdRegister("Quadratic Eigenproblem Solver",&QEP_CLASSID);
 77:   /* Register Constructors */
 78:   QEPRegisterAll(path);
 79:   /* Register Events */
 80:   PetscLogEventRegister("QEPSetUp",QEP_CLASSID,&QEP_SetUp);
 81:   PetscLogEventRegister("QEPSolve",QEP_CLASSID,&QEP_Solve);
 82:   PetscLogEventRegister("QEPDense",QEP_CLASSID,&QEP_Dense);
 83:   /* Process info exclusions */
 84:   PetscOptionsGetString(PETSC_NULL,"-info_exclude",logList,256,&opt);
 85:   if (opt) {
 86:     PetscStrstr(logList,"qep",&className);
 87:     if (className) {
 88:       PetscInfoDeactivateClass(QEP_CLASSID);
 89:     }
 90:   }
 91:   /* Process summary exclusions */
 92:   PetscOptionsGetString(PETSC_NULL,"-log_summary_exclude",logList,256,&opt);
 93:   if (opt) {
 94:     PetscStrstr(logList,"qep",&className);
 95:     if (className) {
 96:       PetscLogEventDeactivateClass(QEP_CLASSID);
 97:     }
 98:   }
 99:   PetscRegisterFinalize(QEPFinalizePackage);
100:   return(0);
101: }

105: /*@C
106:    QEPView - Prints the QEP data structure.

108:    Collective on QEP

110:    Input Parameters:
111: +  qep - the quadratic eigenproblem solver context
112: -  viewer - optional visualization context

114:    Options Database Key:
115: .  -qep_view -  Calls QEPView() at end of QEPSolve()

117:    Note:
118:    The available visualization contexts include
119: +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
120: -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
121:          output where only the first processor opens
122:          the file.  All other processors send their 
123:          data to the first processor to print. 

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

128:    Level: beginner

130: .seealso: PetscViewerASCIIOpen()
131: @*/
132: PetscErrorCode QEPView(QEP qep,PetscViewer viewer)
133: {
135:   const char     *type;
136:   PetscBool      isascii;

140:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(((PetscObject)qep)->comm);

144: #if defined(PETSC_USE_COMPLEX)
145: #define HERM "hermitian"
146: #else
147: #define HERM "symmetric"
148: #endif
149:   PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
150:   if (isascii) {
151:     PetscObjectPrintClassNamePrefixType((PetscObject)qep,viewer,"QEP Object");
152:     if (qep->ops->view) {
153:       PetscViewerASCIIPushTab(viewer);
154:       (*qep->ops->view)(qep,viewer);
155:       PetscViewerASCIIPopTab(viewer);
156:     }
157:     if (qep->problem_type) {
158:       switch (qep->problem_type) {
159:         case QEP_GENERAL:    type = "general quadratic eigenvalue problem"; break;
160:         case QEP_HERMITIAN:  type = HERM " quadratic eigenvalue problem"; break;
161:         case QEP_GYROSCOPIC: type = "gyroscopic quadratic eigenvalue problem"; break;
162:         default: SETERRQ(((PetscObject)qep)->comm,1,"Wrong value of qep->problem_type");
163:       }
164:     } else type = "not yet set";
165:     PetscViewerASCIIPrintf(viewer,"  problem type: %s\n",type);
166:     PetscViewerASCIIPrintf(viewer,"  selected portion of the spectrum: ");
167:     if (!qep->which) {
168:       PetscViewerASCIIPrintf(viewer,"not yet set\n");
169:     } else switch (qep->which) {
170:       case QEP_LARGEST_MAGNITUDE:
171:         PetscViewerASCIIPrintf(viewer,"largest eigenvalues in magnitude\n");
172:         break;
173:       case QEP_SMALLEST_MAGNITUDE:
174:         PetscViewerASCIIPrintf(viewer,"smallest eigenvalues in magnitude\n");
175:         break;
176:       case QEP_LARGEST_REAL:
177:         PetscViewerASCIIPrintf(viewer,"largest real parts\n");
178:         break;
179:       case QEP_SMALLEST_REAL:
180:         PetscViewerASCIIPrintf(viewer,"smallest real parts\n");
181:         break;
182:       case QEP_LARGEST_IMAGINARY:
183:         PetscViewerASCIIPrintf(viewer,"largest imaginary parts\n");
184:         break;
185:       case QEP_SMALLEST_IMAGINARY:
186:         PetscViewerASCIIPrintf(viewer,"smallest imaginary parts\n");
187:         break;
188:       default: SETERRQ(((PetscObject)qep)->comm,1,"Wrong value of qep->which");
189:     }
190:     if (qep->leftvecs) {
191:       PetscViewerASCIIPrintf(viewer,"  computing left eigenvectors also\n");
192:     }
193:     PetscViewerASCIIPrintf(viewer,"  number of eigenvalues (nev): %D\n",qep->nev);
194:     PetscViewerASCIIPrintf(viewer,"  number of column vectors (ncv): %D\n",qep->ncv);
195:     PetscViewerASCIIPrintf(viewer,"  maximum dimension of projected problem (mpd): %D\n",qep->mpd);
196:     PetscViewerASCIIPrintf(viewer,"  maximum number of iterations: %D\n",qep->max_it);
197:     PetscViewerASCIIPrintf(viewer,"  tolerance: %G\n",qep->tol);
198:     PetscViewerASCIIPrintf(viewer,"  scaling factor: %G\n",qep->sfactor);
199:     if (qep->nini!=0) {
200:       PetscViewerASCIIPrintf(viewer,"  dimension of user-provided initial space: %D\n",PetscAbs(qep->nini));
201:     }
202:     if (qep->ninil!=0) {
203:       PetscViewerASCIIPrintf(viewer,"  dimension of user-provided initial left space: %D\n",PetscAbs(qep->ninil));
204:     }
205:   } else {
206:     if (qep->ops->view) {
207:       (*qep->ops->view)(qep,viewer);
208:     }
209:   }
210:   if (!qep->ip) { QEPGetIP(qep,&qep->ip); }
211:   IPView(qep->ip,viewer);
212:   return(0);
213: }

217: /*@
218:    QEPPrintSolution - Prints the computed eigenvalues.

220:    Collective on QEP

222:    Input Parameters:
223: +  qep - the eigensolver context
224: -  viewer - optional visualization context

226:    Options Database:
227: .  -qep_terse - print only minimal information

229:    Note:
230:    By default, this function prints a table with eigenvalues and associated
231:    relative errors. With -qep_terse only the eigenvalues are printed.

233:    Level: intermediate

235: .seealso: PetscViewerASCIIOpen()
236: @*/
237: PetscErrorCode QEPPrintSolution(QEP qep,PetscViewer viewer)
238: {
239:   PetscBool      terse,errok,isascii;
240:   PetscReal      error,re,im;
241:   PetscScalar    kr,ki;
242:   PetscInt       i,j;

247:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(((PetscObject)qep)->comm);
250:   if (!qep->eigr || !qep->eigi || !qep->V) {
251:     SETERRQ(((PetscObject)qep)->comm,PETSC_ERR_ARG_WRONGSTATE,"QEPSolve must be called first");
252:   }
253:   PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
254:   if (!isascii) return(0);

256:   PetscOptionsHasName(PETSC_NULL,"-qep_terse",&terse);
257:   if (terse) {
258:     if (qep->nconv<qep->nev) {
259:       PetscViewerASCIIPrintf(viewer," Problem: less than %D eigenvalues converged\n\n",qep->nev);
260:     } else {
261:       errok = PETSC_TRUE;
262:       for (i=0;i<qep->nev;i++) {
263:         QEPComputeRelativeError(qep,i,&error);
264:         errok = (errok && error<qep->tol)? PETSC_TRUE: PETSC_FALSE;
265:       }
266:       if (errok) {
267:         PetscViewerASCIIPrintf(viewer," All requested eigenvalues computed up to the required tolerance:");
268:         for (i=0;i<=(qep->nev-1)/8;i++) {
269:           PetscViewerASCIIPrintf(viewer,"\n     ");
270:           for (j=0;j<PetscMin(8,qep->nev-8*i);j++) {
271:             QEPGetEigenpair(qep,8*i+j,&kr,&ki,PETSC_NULL,PETSC_NULL);
272: #if defined(PETSC_USE_COMPLEX)
273:             re = PetscRealPart(kr);
274:             im = PetscImaginaryPart(kr);
275: #else
276:             re = kr;
277:             im = ki;
278: #endif 
279:             if (PetscAbs(re)/PetscAbs(im)<PETSC_SMALL) re = 0.0;
280:             if (PetscAbs(im)/PetscAbs(re)<PETSC_SMALL) im = 0.0;
281:             if (im!=0.0) {
282:               PetscViewerASCIIPrintf(viewer,"%.5F%+.5Fi",re,im);
283:             } else {
284:               PetscViewerASCIIPrintf(viewer,"%.5F",re);
285:             }
286:             if (8*i+j+1<qep->nev) { PetscViewerASCIIPrintf(viewer,", "); }
287:           }
288:         }
289:         PetscViewerASCIIPrintf(viewer,"\n\n");
290:       } else {
291:         PetscViewerASCIIPrintf(viewer," Problem: some of the first %D relative errors are higher than the tolerance\n\n",qep->nev);
292:       }
293:     }
294:   } else {
295:     PetscViewerASCIIPrintf(viewer," Number of converged approximate eigenpairs: %D\n\n",qep->nconv);
296:     if (qep->nconv>0) {
297:       PetscViewerASCIIPrintf(viewer,
298:            "           k          ||(k^2M+Ck+K)x||/||kx||\n"
299:            "   ----------------- -------------------------\n");
300:       for (i=0;i<qep->nconv;i++) {
301:         QEPGetEigenpair(qep,i,&kr,&ki,PETSC_NULL,PETSC_NULL);
302:         QEPComputeRelativeError(qep,i,&error);
303: #if defined(PETSC_USE_COMPLEX)
304:         re = PetscRealPart(kr);
305:         im = PetscImaginaryPart(kr);
306: #else
307:         re = kr;
308:         im = ki;
309: #endif 
310:         if (im!=0.0) {
311:           PetscViewerASCIIPrintf(viewer," % 9F%+9F i     %12G\n",re,im,error);
312:         } else {
313:           PetscViewerASCIIPrintf(viewer,"   % 12F           %12G\n",re,error);
314:         }
315:       }
316:       PetscViewerASCIIPrintf(viewer,"\n");
317:     }
318:   }
319:   return(0);
320: }

324: /*@C
325:    QEPCreate - Creates the default QEP context.

327:    Collective on MPI_Comm

329:    Input Parameter:
330: .  comm - MPI communicator

332:    Output Parameter:
333: .  qep - location to put the QEP context

335:    Note:
336:    The default QEP type is QEPLINEAR

338:    Level: beginner

340: .seealso: QEPSetUp(), QEPSolve(), QEPDestroy(), QEP
341: @*/
342: PetscErrorCode QEPCreate(MPI_Comm comm,QEP *outqep)
343: {
345:   QEP            qep;

349:   *outqep = 0;
350:   PetscHeaderCreate(qep,_p_QEP,struct _QEPOps,QEP_CLASSID,-1,"QEP","Quadratic Eigenvalue Problem","QEP",comm,QEPDestroy,QEPView);

352:   qep->M               = 0;
353:   qep->C               = 0;
354:   qep->K               = 0;
355:   qep->max_it          = 0;
356:   qep->nev             = 1;
357:   qep->ncv             = 0;
358:   qep->mpd             = 0;
359:   qep->nini            = 0;
360:   qep->ninil           = 0;
361:   qep->allocated_ncv   = 0;
362:   qep->tol             = PETSC_DEFAULT;
363:   qep->sfactor         = 0.0;
364:   qep->conv_func       = QEPDefaultConverged;
365:   qep->conv_ctx        = PETSC_NULL;
366:   qep->which           = (QEPWhich)0;
367:   qep->which_func      = PETSC_NULL;
368:   qep->which_ctx       = PETSC_NULL;
369:   qep->leftvecs        = PETSC_FALSE;
370:   qep->problem_type    = (QEPProblemType)0;
371:   qep->V               = PETSC_NULL;
372:   qep->W               = PETSC_NULL;
373:   qep->IS              = PETSC_NULL;
374:   qep->ISL             = PETSC_NULL;
375:   qep->T               = PETSC_NULL;
376:   qep->eigr            = PETSC_NULL;
377:   qep->eigi            = PETSC_NULL;
378:   qep->errest          = PETSC_NULL;
379:   qep->data            = PETSC_NULL;
380:   qep->t               = PETSC_NULL;
381:   qep->nconv           = 0;
382:   qep->its             = 0;
383:   qep->perm            = PETSC_NULL;
384:   qep->matvecs         = 0;
385:   qep->linits          = 0;
386:   qep->nwork           = 0;
387:   qep->work            = PETSC_NULL;
388:   qep->setupcalled     = 0;
389:   qep->reason          = QEP_CONVERGED_ITERATING;
390:   qep->numbermonitors  = 0;
391:   qep->trackall        = PETSC_FALSE;
392:   qep->rand            = 0;

394:   PetscRandomCreate(comm,&qep->rand);
395:   PetscLogObjectParent(qep,qep->rand);
396:   *outqep = qep;
397:   return(0);
398: }
399: 
402: /*@C
403:    QEPSetType - Selects the particular solver to be used in the QEP object. 

405:    Logically Collective on QEP

407:    Input Parameters:
408: +  qep      - the quadratic eigensolver context
409: -  type     - a known method

411:    Options Database Key:
412: .  -qep_type <method> - Sets the method; use -help for a list 
413:     of available methods 
414:     
415:    Notes:  
416:    See "slepc/include/slepcqep.h" for available methods. The default
417:    is QEPLINEAR.

419:    Normally, it is best to use the QEPSetFromOptions() command and
420:    then set the QEP type from the options database rather than by using
421:    this routine.  Using the options database provides the user with
422:    maximum flexibility in evaluating the different available methods.
423:    The QEPSetType() routine is provided for those situations where it
424:    is necessary to set the iterative solver independently of the command
425:    line or options database. 

427:    Level: intermediate

429: .seealso: QEPType
430: @*/
431: PetscErrorCode QEPSetType(QEP qep,const QEPType type)
432: {
433:   PetscErrorCode ierr,(*r)(QEP);
434:   PetscBool      match;


440:   PetscTypeCompare((PetscObject)qep,type,&match);
441:   if (match) return(0);

443:   PetscFListFind(QEPList,((PetscObject)qep)->comm,type,PETSC_TRUE,(void (**)(void))&r);
444:   if (!r) SETERRQ1(((PetscObject)qep)->comm,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown QEP type given: %s",type);

446:   if (qep->ops->destroy) { (*qep->ops->destroy)(qep); }
447:   PetscMemzero(qep->ops,sizeof(struct _QEPOps));

449:   qep->setupcalled = 0;
450:   PetscObjectChangeTypeName((PetscObject)qep,type);
451:   (*r)(qep);
452:   return(0);
453: }

457: /*@C
458:    QEPGetType - Gets the QEP type as a string from the QEP object.

460:    Not Collective

462:    Input Parameter:
463: .  qep - the eigensolver context 

465:    Output Parameter:
466: .  name - name of QEP method 

468:    Level: intermediate

470: .seealso: QEPSetType()
471: @*/
472: PetscErrorCode QEPGetType(QEP qep,const QEPType *type)
473: {
477:   *type = ((PetscObject)qep)->type_name;
478:   return(0);
479: }

483: /*@C
484:   QEPRegister - See QEPRegisterDynamic()

486:   Level: advanced
487: @*/
488: PetscErrorCode QEPRegister(const char *sname,const char *path,const char *name,PetscErrorCode (*function)(QEP))
489: {
491:   char           fullname[PETSC_MAX_PATH_LEN];

494:   PetscFListConcat(path,name,fullname);
495:   PetscFListAdd(&QEPList,sname,fullname,(void (*)(void))function);
496:   return(0);
497: }

501: /*@
502:    QEPRegisterDestroy - Frees the list of QEP methods that were
503:    registered by QEPRegisterDynamic().

505:    Not Collective

507:    Level: advanced

509: .seealso: QEPRegisterDynamic(), QEPRegisterAll()
510: @*/
511: PetscErrorCode QEPRegisterDestroy(void)
512: {

516:   PetscFListDestroy(&QEPList);
517:   QEPRegisterAllCalled = PETSC_FALSE;
518:   return(0);
519: }

523: /*@C
524:    QEPReset - Resets the QEP context to the setupcalled=0 state and removes any
525:    allocated objects.

527:    Collective on QEP

529:    Input Parameter:
530: .  qep - eigensolver context obtained from QEPCreate()

532:    Level: advanced

534: .seealso: QEPDestroy()
535: @*/
536: PetscErrorCode QEPReset(QEP qep)
537: {

542:   if (qep->ops->reset) { (qep->ops->reset)(qep); }
543:   if (qep->ip) { IPReset(qep->ip); }
544:   MatDestroy(&qep->M);
545:   MatDestroy(&qep->C);
546:   MatDestroy(&qep->K);
547:   VecDestroy(&qep->t);
548:   QEPFreeSolution(qep);
549:   qep->matvecs     = 0;
550:   qep->linits      = 0;
551:   qep->setupcalled = 0;
552:   return(0);
553: }

557: /*@C
558:    QEPDestroy - Destroys the QEP context.

560:    Collective on QEP

562:    Input Parameter:
563: .  qep - eigensolver context obtained from QEPCreate()

565:    Level: beginner

567: .seealso: QEPCreate(), QEPSetUp(), QEPSolve()
568: @*/
569: PetscErrorCode QEPDestroy(QEP *qep)
570: {

574:   if (!*qep) return(0);
576:   if (--((PetscObject)(*qep))->refct > 0) { *qep = 0; return(0); }
577:   QEPReset(*qep);
578:   PetscObjectDepublish(*qep);
579:   if ((*qep)->ops->destroy) { (*(*qep)->ops->destroy)(*qep); }
580:   IPDestroy(&(*qep)->ip);
581:   PetscRandomDestroy(&(*qep)->rand);
582:   QEPMonitorCancel(*qep);
583:   PetscHeaderDestroy(qep);
584:   return(0);
585: }

589: /*@
590:    QEPSetIP - Associates an inner product object to the quadratic eigensolver. 

592:    Collective on QEP

594:    Input Parameters:
595: +  qep - eigensolver context obtained from QEPCreate()
596: -  ip  - the inner product object

598:    Note:
599:    Use QEPGetIP() to retrieve the inner product context (for example,
600:    to free it at the end of the computations).

602:    Level: advanced

604: .seealso: QEPGetIP()
605: @*/
606: PetscErrorCode QEPSetIP(QEP qep,IP ip)
607: {

614:   PetscObjectReference((PetscObject)ip);
615:   IPDestroy(&qep->ip);
616:   qep->ip = ip;
617:   PetscLogObjectParent(qep,qep->ip);
618:   return(0);
619: }

623: /*@C
624:    QEPGetIP - Obtain the inner product object associated
625:    to the quadratic eigensolver object.

627:    Not Collective

629:    Input Parameters:
630: .  qep - eigensolver context obtained from QEPCreate()

632:    Output Parameter:
633: .  ip - inner product context

635:    Level: advanced

637: .seealso: QEPSetIP()
638: @*/
639: PetscErrorCode QEPGetIP(QEP qep,IP *ip)
640: {

646:   if (!qep->ip) {
647:     IPCreate(((PetscObject)qep)->comm,&qep->ip);
648:     PetscLogObjectParent(qep,qep->ip);
649:   }
650:   *ip = qep->ip;
651:   return(0);
652: }