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-2010, Universidad 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

 26: PetscFList QEPList = 0;
 27: PetscCookie QEP_COOKIE = 0;
 28: PetscLogEvent QEP_SetUp = 0, QEP_Solve = 0, QEP_Dense = 0;
 29: static PetscTruth QEPPackageInitialized = PETSC_FALSE;

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

 37:   Level: developer

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

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

 56:   Input Parameter:
 57:   path - The dynamic library path, or PETSC_NULL

 59:   Level: developer

 61: .seealso: SlepcInitialize()
 62: @*/
 63: PetscErrorCode QEPInitializePackage(char *path) {
 64:   char           logList[256];
 65:   char           *className;
 66:   PetscTruth     opt;

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

102: /*@C
103:    QEPView - Prints the QEP data structure.

105:    Collective on QEP

107:    Input Parameters:
108: +  qep - the quadratic eigenproblem solver context
109: -  viewer - optional visualization context

111:    Options Database Key:
112: .  -qep_view -  Calls QEPView() at end of QEPSolve()

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

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

125:    Level: beginner

127: .seealso: PetscViewerASCIIOpen()
128: @*/
129: PetscErrorCode QEPView(QEP qep,PetscViewer viewer)
130: {
132:   const char     *type;
133:   PetscTruth     isascii;

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

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

220: /*@C
221:    QEPCreate - Creates the default QEP context.

223:    Collective on MPI_Comm

225:    Input Parameter:
226: .  comm - MPI communicator

228:    Output Parameter:
229: .  qep - location to put the QEP context

231:    Note:
232:    The default QEP type is QEPLINEAR

234:    Level: beginner

236: .seealso: QEPSetUp(), QEPSolve(), QEPDestroy(), QEP
237: @*/
238: PetscErrorCode QEPCreate(MPI_Comm comm,QEP *outqep)
239: {
241:   QEP            qep;

245:   *outqep = 0;

247:   PetscHeaderCreate(qep,_p_QEP,struct _QEPOps,QEP_COOKIE,-1,"QEP",comm,QEPDestroy,QEPView);
248:   *outqep = qep;

250:   PetscMemzero(qep->ops,sizeof(struct _QEPOps));

252:   qep->max_it          = 0;
253:   qep->nev             = 1;
254:   qep->ncv             = 0;
255:   qep->mpd             = 0;
256:   qep->nini            = 0;
257:   qep->ninil           = 0;
258:   qep->tol             = 1e-7;
259:   qep->sfactor         = 0.0;
260:   qep->conv_func       = QEPDefaultConverged;
261:   qep->conv_ctx        = PETSC_NULL;
262:   qep->which           = (QEPWhich)0;
263:   qep->which_func      = PETSC_NULL;
264:   qep->which_ctx       = PETSC_NULL;
265:   qep->leftvecs        = PETSC_FALSE;
266:   qep->problem_type    = (QEPProblemType)0;
267:   qep->V               = PETSC_NULL;
268:   qep->IS              = PETSC_NULL;
269:   qep->ISL             = PETSC_NULL;
270:   qep->T               = PETSC_NULL;
271:   qep->eigr            = PETSC_NULL;
272:   qep->eigi            = PETSC_NULL;
273:   qep->errest          = PETSC_NULL;
274:   qep->data            = PETSC_NULL;
275:   qep->nconv           = 0;
276:   qep->its             = 0;
277:   qep->perm            = PETSC_NULL;
278:   qep->matvecs         = 0;
279:   qep->linits          = 0;
280:   qep->nwork           = 0;
281:   qep->work            = PETSC_NULL;
282:   qep->setupcalled     = 0;
283:   qep->reason          = QEP_CONVERGED_ITERATING;
284:   qep->numbermonitors  = 0;
285:   qep->trackall        = PETSC_FALSE;

287:   IPCreate(comm,&qep->ip);
288:   IPSetOptionsPrefix(qep->ip,((PetscObject)qep)->prefix);
289:   IPAppendOptionsPrefix(qep->ip,"qep_");
290:   PetscLogObjectParent(qep,qep->ip);
291:   PetscPublishAll(qep);
292:   return(0);
293: }
294: 
297: /*@C
298:    QEPSetType - Selects the particular solver to be used in the QEP object. 

300:    Collective on QEP

302:    Input Parameters:
303: +  qep      - the quadratic eigensolver context
304: -  type     - a known method

306:    Options Database Key:
307: .  -qep_type <method> - Sets the method; use -help for a list 
308:     of available methods 
309:     
310:    Notes:  
311:    See "slepc/include/slepcqep.h" for available methods. The default
312:    is QEPLINEAR.

314:    Normally, it is best to use the QEPSetFromOptions() command and
315:    then set the QEP type from the options database rather than by using
316:    this routine.  Using the options database provides the user with
317:    maximum flexibility in evaluating the different available methods.
318:    The QEPSetType() routine is provided for those situations where it
319:    is necessary to set the iterative solver independently of the command
320:    line or options database. 

322:    Level: intermediate

324: .seealso: QEPType
325: @*/
326: PetscErrorCode QEPSetType(QEP qep,const QEPType type)
327: {
328:   PetscErrorCode ierr,(*r)(QEP);
329:   PetscTruth match;


335:   PetscTypeCompare((PetscObject)qep,type,&match);
336:   if (match) return(0);

338:   if (qep->data) {
339:     /* destroy the old private QEP context */
340:     (*qep->ops->destroy)(qep);
341:     qep->data = 0;
342:   }

344:   PetscFListFind(QEPList,((PetscObject)qep)->comm,type,(void (**)(void))&r);

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

348:   qep->setupcalled = 0;
349:   PetscMemzero(qep->ops,sizeof(struct _QEPOps));
350:   (*r)(qep);

352:   PetscObjectChangeTypeName((PetscObject)qep,type);
353:   return(0);
354: }

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

361:    Not Collective

363:    Input Parameter:
364: .  qep - the eigensolver context 

366:    Output Parameter:
367: .  name - name of QEP method 

369:    Level: intermediate

371: .seealso: QEPSetType()
372: @*/
373: PetscErrorCode QEPGetType(QEP qep,const QEPType *type)
374: {
378:   *type = ((PetscObject)qep)->type_name;
379:   return(0);
380: }

382: /*MC
383:    QEPRegisterDynamic - Adds a method to the quadratic eigenproblem solver package.

385:    Synopsis:
386:    QEPRegisterDynamic(char *name_solver,char *path,char *name_create,PetscErrorCode (*routine_create)(QEP))

388:    Not Collective

390:    Input Parameters:
391: +  name_solver - name of a new user-defined solver
392: .  path - path (either absolute or relative) the library containing this solver
393: .  name_create - name of routine to create the solver context
394: -  routine_create - routine to create the solver context

396:    Notes:
397:    QEPRegisterDynamic() may be called multiple times to add several user-defined solvers.

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

402:    Sample usage:
403: .vb
404:    QEPRegisterDynamic("my_solver",/home/username/my_lib/lib/libO/solaris/mylib.a,
405:                "MySolverCreate",MySolverCreate);
406: .ve

408:    Then, your solver can be chosen with the procedural interface via
409: $     QEPSetType(qep,"my_solver")
410:    or at runtime via the option
411: $     -qep_type my_solver

413:    Level: advanced

415:    Environmental variables such as ${PETSC_ARCH}, ${SLEPC_DIR},
416:    and others of the form ${any_environmental_variable} occuring in pathname will be 
417:    replaced with appropriate values.

419: .seealso: QEPRegisterDestroy(), QEPRegisterAll()

421: M*/

425: /*@C
426:   QEPRegister - See QEPRegisterDynamic()

428:   Level: advanced
429: @*/
430: PetscErrorCode QEPRegister(const char *sname,const char *path,const char *name,PetscErrorCode (*function)(QEP))
431: {
433:   char           fullname[256];

436:   PetscFListConcat(path,name,fullname);
437:   PetscFListAdd(&QEPList,sname,fullname,(void (*)(void))function);
438:   return(0);
439: }

443: /*@
444:    QEPRegisterDestroy - Frees the list of QEP methods that were
445:    registered by QEPRegisterDynamic().

447:    Not Collective

449:    Level: advanced

451: .seealso: QEPRegisterDynamic(), QEPRegisterAll()
452: @*/
453: PetscErrorCode QEPRegisterDestroy(void)
454: {

458:   PetscFListDestroy(&QEPList);
459:   QEPRegisterAll(PETSC_NULL);
460:   return(0);
461: }

465: /*@
466:    QEPDestroy - Destroys the QEP context.

468:    Collective on QEP

470:    Input Parameter:
471: .  qep - eigensolver context obtained from QEPCreate()

473:    Level: beginner

475: .seealso: QEPCreate(), QEPSetUp(), QEPSolve()
476: @*/
477: PetscErrorCode QEPDestroy(QEP qep)
478: {
480:   PetscScalar    *pV;
481:   PetscInt       i;

485:   if (--((PetscObject)qep)->refct > 0) return(0);

487:   /* if memory was published with AMS then destroy it */
488:   PetscObjectDepublish(qep);

490:   if (qep->ops->destroy) {
491:     (*qep->ops->destroy)(qep);
492:   }
493: 
494:   PetscFree(qep->T);

496:   if (qep->eigr) {
497:     PetscFree(qep->eigr);
498:     PetscFree(qep->eigi);
499:     PetscFree(qep->perm);
500:     PetscFree(qep->errest);
501:     VecGetArray(qep->V[0],&pV);
502:     for (i=0;i<qep->ncv;i++) {
503:       VecDestroy(qep->V[i]);
504:     }
505:     PetscFree(pV);
506:     PetscFree(qep->V);
507:   }

509:   QEPMonitorCancel(qep);

511:   IPDestroy(qep->ip);
512:   PetscRandomDestroy(qep->rand);

514:   if (qep->M) { MatDestroy(qep->M); }
515:   if (qep->C) { MatDestroy(qep->C); }
516:   if (qep->K) { MatDestroy(qep->K); }

518:   PetscHeaderDestroy(qep);
519:   return(0);
520: }

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

527:    Collective on QEP and IP

529:    Input Parameters:
530: +  qep - eigensolver context obtained from QEPCreate()
531: -  ip  - the inner product object

533:    Note:
534:    Use QEPGetIP() to retrieve the inner product context (for example,
535:    to free it at the end of the computations).

537:    Level: advanced

539: .seealso: QEPGetIP()
540: @*/
541: PetscErrorCode QEPSetIP(QEP qep,IP ip)
542: {

549:   PetscObjectReference((PetscObject)ip);
550:   IPDestroy(qep->ip);
551:   qep->ip = ip;
552:   return(0);
553: }

557: /*@C
558:    QEPGetIP - Obtain the inner product object associated
559:    to the quadratic eigensolver object.

561:    Not Collective

563:    Input Parameters:
564: .  qep - eigensolver context obtained from QEPCreate()

566:    Output Parameter:
567: .  ip - inner product context

569:    Level: advanced

571: .seealso: QEPSetIP()
572: @*/
573: PetscErrorCode QEPGetIP(QEP qep,IP *ip)
574: {
578:   *ip = qep->ip;
579:   return(0);
580: }