Actual source code: stfunc.c

  1: /*
  2:     The ST (spectral transformation) interface routines, callable by users.

  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/stimpl.h

 26: PetscCookie ST_COOKIE = 0;
 27: PetscLogEvent ST_SetUp = 0, ST_Apply = 0, ST_ApplyTranspose = 0;
 28: static PetscTruth STPackageInitialized = PETSC_FALSE;

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

 36:   Level: developer

 38: .seealso: SlepcFinalize()
 39: @*/
 40: PetscErrorCode STFinalizePackage(void)
 41: {
 43:   STPackageInitialized = PETSC_FALSE;
 44:   STList               = 0;
 45:   return(0);
 46: }

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

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

 58:   Level: developer

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

 69:   if (STPackageInitialized) return(0);
 70:   STPackageInitialized = PETSC_TRUE;
 71:   /* Register Classes */
 72:   PetscCookieRegister("Spectral Transform",&ST_COOKIE);
 73:   /* Register Constructors */
 74:   STRegisterAll(path);
 75:   /* Register Events */
 76:   PetscLogEventRegister("STSetUp",ST_COOKIE,&ST_SetUp);
 77:   PetscLogEventRegister("STApply",ST_COOKIE,&ST_Apply);
 78:   PetscLogEventRegister("STApplyTranspose",ST_COOKIE,&ST_ApplyTranspose);
 79:   /* Process info exclusions */
 80:   PetscOptionsGetString(PETSC_NULL, "-log_info_exclude", logList, 256, &opt);
 81:   if (opt) {
 82:     PetscStrstr(logList, "st", &className);
 83:     if (className) {
 84:       PetscInfoDeactivateClass(ST_COOKIE);
 85:     }
 86:   }
 87:   /* Process summary exclusions */
 88:   PetscOptionsGetString(PETSC_NULL, "-log_summary_exclude", logList, 256, &opt);
 89:   if (opt) {
 90:     PetscStrstr(logList, "st", &className);
 91:     if (className) {
 92:       PetscLogEventDeactivateClass(ST_COOKIE);
 93:     }
 94:   }
 95:   PetscRegisterFinalize(STFinalizePackage);
 96:   return(0);
 97: }

101: /*@
102:    STDestroy - Destroys ST context that was created with STCreate().

104:    Collective on ST

106:    Input Parameter:
107: .  st - the spectral transformation context

109:    Level: beginner

111: .seealso: STCreate(), STSetUp()
112: @*/
113: PetscErrorCode STDestroy(ST st)
114: {

119:   if (--((PetscObject)st)->refct > 0) return(0);

121:   /* if memory was published with AMS then destroy it */
122:   PetscObjectDepublish(st);

124:   if (st->ops->destroy) { (*st->ops->destroy)(st); }
125:   if (st->A) { MatDestroy(st->A); }
126:   if (st->B) { MatDestroy(st->B); }
127:   if (st->ksp) { KSPDestroy(st->ksp); }
128:   if (st->w) { VecDestroy(st->w); }
129:   if (st->D) { VecDestroy(st->D); }
130:   if (st->wb){ VecDestroy(st->wb); }
131:   if (st->shift_matrix != ST_MATMODE_INPLACE && st->mat) {
132:     MatDestroy(st->mat);
133:   }

135:   PetscHeaderDestroy(st);
136:   return(0);
137: }

141: /*@C
142:    STCreate - Creates a spectral transformation context.

144:    Collective on MPI_Comm

146:    Input Parameter:
147: .  comm - MPI communicator 

149:    Output Parameter:
150: .  st - location to put the spectral transformation context

152:    Level: beginner

154: .seealso: STSetUp(), STApply(), STDestroy(), ST
155: @*/
156: PetscErrorCode STCreate(MPI_Comm comm,ST *newst)
157: {
159:   ST             st;
160:   const char     *prefix;

164:   *newst = 0;

166:   PetscHeaderCreate(st,_p_ST,struct _STOps,ST_COOKIE,-1,"ST",comm,STDestroy,STView);
167:   PetscMemzero(st->ops,sizeof(struct _STOps));

169:   st->A                   = 0;
170:   st->B                   = 0;
171:   st->sigma               = 0.0;
172:   st->sigma_set           = PETSC_FALSE;
173:   st->defsigma            = 0.0;
174:   st->data                = 0;
175:   st->setupcalled         = 0;
176:   st->w                   = 0;
177:   st->D                   = 0;
178:   st->wb                  = 0;
179:   st->shift_matrix        = ST_MATMODE_COPY;
180:   st->str                 = DIFFERENT_NONZERO_PATTERN;
181: 
182:   KSPCreate(((PetscObject)st)->comm,&st->ksp);
183:   STGetOptionsPrefix(st,&prefix);
184:   KSPSetOptionsPrefix(st->ksp,prefix);
185:   KSPAppendOptionsPrefix(st->ksp,"st_");
186:   PetscObjectIncrementTabLevel((PetscObject)st->ksp,(PetscObject)st,1);
187: 
188:   *newst                  = st;
189:   PetscPublishAll(st);
190:   return(0);

192: }

196: /*@
197:    STSetOperators - Sets the matrices associated with the eigenvalue problem. 

199:    Collective on ST and Mat

201:    Input Parameters:
202: +  st - the spectral transformation context
203: .  A  - the matrix associated with the eigensystem
204: -  B  - the second matrix in the case of generalized eigenproblems

206:    Notes:
207:    To specify a standard eigenproblem, use PETSC_NULL for B.

209:    Level: intermediate

211: .seealso: STGetOperators()
212:  @*/
213: PetscErrorCode STSetOperators(ST st,Mat A,Mat B)
214: {
222:   PetscObjectReference((PetscObject)A);
223:   if (st->A) { MatDestroy(st->A); }
224:   st->A = A;
225:   if (B) { PetscObjectReference((PetscObject)B); }
226:   if (st->B) { MatDestroy(st->B); }
227:   st->B = B;
228:   st->setupcalled = 0;
229:   return(0);
230: }

234: /*@C
235:    STGetOperators - Gets the matrices associated with the eigensystem.

237:    Not collective, though parallel Mats are returned if the ST is parallel

239:    Input Parameter:
240: .  st - the spectral transformation context

242:    Output Parameters:
243: .  A - the matrix associated with the eigensystem
244: -  B - the second matrix in the case of generalized eigenproblems

246:    Level: intermediate

248: .seealso: STSetOperators()
249: @*/
250: PetscErrorCode STGetOperators(ST st,Mat *A,Mat *B)
251: {
254:   if (A) *A = st->A;
255:   if (B) *B = st->B;
256:   return(0);
257: }

261: /*@
262:    STSetShift - Sets the shift associated with the spectral transformation.

264:    Collective on ST

266:    Input Parameters:
267: +  st - the spectral transformation context
268: -  shift - the value of the shift

270:    Note:
271:    In some spectral transformations, changing the shift may have associated
272:    a lot of work, for example recomputing a factorization.
273:    
274:    Level: beginner

276: @*/
277: PetscErrorCode STSetShift(ST st,PetscScalar shift)
278: {

283:   if (st->sigma != shift) {
284:     if (st->ops->setshift) {
285:       (*st->ops->setshift)(st,shift);
286:     }
287:   }
288:   st->sigma = shift;
289:   st->sigma_set = PETSC_TRUE;
290:   return(0);
291: }

295: /*@
296:    STGetShift - Gets the shift associated with the spectral transformation.

298:    Not collective

300:    Input Parameter:
301: .  st - the spectral transformation context

303:    Output Parameter:
304: .  shift - the value of the shift

306:    Level: beginner

308: @*/
309: PetscErrorCode STGetShift(ST st,PetscScalar* shift)
310: {
313:   if (shift)  *shift = st->sigma;
314:   return(0);
315: }

319: /*@
320:    STSetDefaultShift - Sets the value of the shift that should be employed if
321:    the user did not specify one.

323:    Collective on ST

325:    Input Parameters:
326: +  st - the spectral transformation context
327: -  defaultshift - the default value of the shift

329:    Level: developer

331: @*/
332: PetscErrorCode STSetDefaultShift(ST st,PetscScalar defaultshift)
333: {
336:   st->defsigma = defaultshift;
337:   return(0);
338: }

342: /*@
343:    STSetBalanceMatrix - Sets the diagonal matrix to be used for balancing.

345:    Collective on ST and Vec

347:    Input Parameters:
348: +  st - the spectral transformation context
349: -  D  - the diagonal matrix (represented as a vector)

351:    Notes:
352:    If this matrix is set, STApply will effectively apply D*OP*D^{-1}.

354:    Balancing is usually set via EPSSetBalance, but the advanced user may use
355:    this function to bypass the usual balancing methods.
356:    
357:    Level: developer

359: .seealso: EPSSetBalance(), STApply(), STGetBalanceMatrix()
360: @*/
361: PetscErrorCode STSetBalanceMatrix(ST st,Vec D)
362: {

369:   PetscObjectReference((PetscObject)D);
370:   if (st->D) {
371:     VecDestroy(st->D);
372:   }
373:   st->D = D;
374:   if (!st->wb) {
375:     VecDuplicate(st->D,&st->wb);
376:   }
377:   return(0);
378: }

382: /*@
383:    STGetBalanceMatrix - Gets the balance matrix used by the spectral transformation.

385:    Not collective, but vector is shared by all processors that share the ST

387:    Input Parameter:
388: .  st - the spectral transformation context

390:    Output Parameter:
391: .  D  - the diagonal matrix (represented as a vector)

393:    Note:
394:    If the matrix was not set, a null pointer will be returned.

396:    Level: developer

398: .seealso: STSetBalanceMatrix()
399: @*/
400: PetscErrorCode STGetBalanceMatrix(ST st,Vec *D)
401: {
405:   *D = st->D;
406:   return(0);
407: }

411: /*@C
412:    STSetOptionsPrefix - Sets the prefix used for searching for all 
413:    ST options in the database.

415:    Collective on ST

417:    Input Parameters:
418: +  st     - the spectral transformation context
419: -  prefix - the prefix string to prepend to all ST option requests

421:    Notes:
422:    A hyphen (-) must NOT be given at the beginning of the prefix name.
423:    The first character of all runtime options is AUTOMATICALLY the
424:    hyphen.

426:    Level: advanced

428: .seealso: STAppendOptionsPrefix(), STGetOptionsPrefix()
429: @*/
430: PetscErrorCode STSetOptionsPrefix(ST st,const char *prefix)
431: {

436:   PetscObjectSetOptionsPrefix((PetscObject)st,prefix);
437:   KSPSetOptionsPrefix(st->ksp,prefix);
438:   KSPAppendOptionsPrefix(st->ksp,"st_");
439:   return(0);
440: }

444: /*@C
445:    STAppendOptionsPrefix - Appends to the prefix used for searching for all 
446:    ST options in the database.

448:    Collective on ST

450:    Input Parameters:
451: +  st     - the spectral transformation context
452: -  prefix - the prefix string to prepend to all ST option requests

454:    Notes:
455:    A hyphen (-) must NOT be given at the beginning of the prefix name.
456:    The first character of all runtime options is AUTOMATICALLY the
457:    hyphen.

459:    Level: advanced

461: .seealso: STSetOptionsPrefix(), STGetOptionsPrefix()
462: @*/
463: PetscErrorCode STAppendOptionsPrefix(ST st,const char *prefix)
464: {

469:   PetscObjectAppendOptionsPrefix((PetscObject)st,prefix);
470:   KSPSetOptionsPrefix(st->ksp,((PetscObject)st)->prefix);
471:   KSPAppendOptionsPrefix(st->ksp,"st_");
472:   return(0);
473: }

477: /*@C
478:    STGetOptionsPrefix - Gets the prefix used for searching for all 
479:    ST options in the database.

481:    Not Collective

483:    Input Parameters:
484: .  st - the spectral transformation context

486:    Output Parameters:
487: .  prefix - pointer to the prefix string used, is returned

489:    Notes: On the Fortran side, the user should pass in a string 'prefix' of
490:    sufficient length to hold the prefix.

492:    Level: advanced

494: .seealso: STSetOptionsPrefix(), STAppendOptionsPrefix()
495: @*/
496: PetscErrorCode STGetOptionsPrefix(ST st,const char *prefix[])
497: {

502:   PetscObjectGetOptionsPrefix((PetscObject)st, prefix);
503:   return(0);
504: }

508: /*@C
509:    STView - Prints the ST data structure.

511:    Collective on ST

513:    Input Parameters:
514: +  ST - the ST context
515: -  viewer - optional visualization context

517:    Note:
518:    The available visualization contexts include
519: +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
520: -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
521:          output where only the first processor opens
522:          the file.  All other processors send their 
523:          data to the first processor to print. 

525:    The user can open an alternative visualization contexts with
526:    PetscViewerASCIIOpen() (output to a specified file).

528:    Level: beginner

530: .seealso: EPSView(), PetscViewerASCIIOpen()
531: @*/
532: PetscErrorCode STView(ST st,PetscViewer viewer)
533: {
534:   PetscErrorCode    ierr;
535:   const STType      cstr;
536:   const char*       str;
537:   PetscTruth        isascii,isstring;
538:   PetscViewerFormat format;

542:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(((PetscObject)st)->comm);

546:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
547:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);
548:   if (isascii) {
549:     PetscViewerGetFormat(viewer,&format);
550:     PetscViewerASCIIPrintf(viewer,"ST Object:\n");
551:     STGetType(st,&cstr);
552:     if (cstr) {
553:       PetscViewerASCIIPrintf(viewer,"  type: %s\n",cstr);
554:     } else {
555:       PetscViewerASCIIPrintf(viewer,"  type: not yet set\n");
556:     }
557: #if !defined(PETSC_USE_COMPLEX)
558:     PetscViewerASCIIPrintf(viewer,"  shift: %g\n",st->sigma);
559: #else
560:     PetscViewerASCIIPrintf(viewer,"  shift: %g+%g i\n",PetscRealPart(st->sigma),PetscImaginaryPart(st->sigma));
561: #endif
562:     switch (st->shift_matrix) {
563:     case ST_MATMODE_COPY:
564:       break;
565:     case ST_MATMODE_INPLACE:
566:       PetscViewerASCIIPrintf(viewer,"Shifting the matrix and unshifting at exit\n");
567:       break;
568:     case ST_MATMODE_SHELL:
569:       PetscViewerASCIIPrintf(viewer,"Using a shell matrix\n");
570:       break;
571:     }
572:     if (st->B && st->shift_matrix != ST_MATMODE_SHELL) {
573:       switch (st->str) {
574:         case SAME_NONZERO_PATTERN:      str = "same nonzero pattern";break;
575:         case DIFFERENT_NONZERO_PATTERN: str = "different nonzero pattern";break;
576:         case SUBSET_NONZERO_PATTERN:    str = "subset nonzero pattern";break;
577:         default:                        SETERRQ(1,"Wrong structure flag");
578:       }
579:       PetscViewerASCIIPrintf(viewer,"Matrices A and B have %s\n",str);
580:     }
581:     if (st->ops->view) {
582:       PetscViewerASCIIPushTab(viewer);
583:       (*st->ops->view)(st,viewer);
584:       PetscViewerASCIIPopTab(viewer);
585:     }
586:   } else if (isstring) {
587:     STGetType(st,&cstr);
588:     PetscViewerStringSPrintf(viewer," %-7.7s",cstr);
589:     if (st->ops->view) {(*st->ops->view)(st,viewer);}
590:   } else {
591:     SETERRQ1(1,"Viewer type %s not supported by ST",((PetscObject)viewer)->type_name);
592:   }
593:   return(0);
594: }

598: PetscErrorCode STView_Default(ST st,PetscViewer viewer)
599: {
601:   PetscTruth     isascii,isstring;

604:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
605:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);
606:   if (isascii) {
607:     PetscViewerASCIIPushTab(viewer);
608:     PetscViewerASCIIPrintf(viewer,"Associated KSP object\n");
609:     PetscViewerASCIIPrintf(viewer,"------------------------------\n");
610:     KSPView(st->ksp,viewer);
611:     PetscViewerASCIIPrintf(viewer,"------------------------------\n");
612:     PetscViewerASCIIPopTab(viewer);
613:   } else if (isstring) {
614:     KSPView(st->ksp,viewer);
615:   }
616:   return(0);
617: }

619: /*MC
620:    STRegisterDynamic - Adds a method to the spectral transformation package.

622:    Synopsis:
623:    STRegisterDynamic(char *name_solver,char *path,char *name_create,PetscErrorCode (*routine_create)(ST))

625:    Not collective

627:    Input Parameters:
628: +  name_solver - name of a new user-defined solver
629: .  path - path (either absolute or relative) the library containing this solver
630: .  name_create - name of routine to create method context
631: -  routine_create - routine to create method context

633:    Notes:
634:    STRegisterDynamic() may be called multiple times to add several user-defined spectral transformations.

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

639:    Sample usage:
640: .vb
641:    STRegisterDynamic("my_solver","/home/username/my_lib/lib/libO/solaris/mylib.a",
642:               "MySolverCreate",MySolverCreate);
643: .ve

645:    Then, your solver can be chosen with the procedural interface via
646: $     STSetType(st,"my_solver")
647:    or at runtime via the option
648: $     -st_type my_solver

650:    Level: advanced

652:    $PETSC_DIR, $PETSC_ARCH and $PETSC_LIB_DIR occuring in pathname will be replaced with appropriate values.

654: .seealso: STRegisterDestroy(), STRegisterAll()
655: M*/

659: /*@C
660:   STRegister - See STRegisterDynamic()

662:   Level: advanced
663: @*/
664: PetscErrorCode STRegister(const char *sname,const char *path,const char *name,PetscErrorCode (*function)(ST))
665: {
667:   char           fullname[256];

670:   PetscFListConcat(path,name,fullname);
671:   PetscFListAdd(&STList,sname,fullname,(void (*)(void))function);
672:   return(0);
673: }

677: /*@
678:    STRegisterDestroy - Frees the list of ST methods that were
679:    registered by STRegisterDynamic().

681:    Not Collective

683:    Level: advanced

685: .seealso: STRegisterDynamic(), STRegisterAll()
686: @*/
687: PetscErrorCode STRegisterDestroy(void)
688: {

692:   PetscFListDestroy(&STList);
693:   STRegisterAll(PETSC_NULL);
694:   return(0);
695: }