Actual source code: stfunc.c

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

 6:  #include src/st/stimpl.h

  8: PetscCookie ST_COOKIE = 0;
  9: PetscEvent ST_SetUp = 0, ST_Apply = 0, ST_ApplyB = 0, ST_ApplyNoB = 0, ST_ApplyTranspose = 0, ST_InnerProduct = 0;

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

 18:   Input Parameter:
 19:   path - The dynamic library path, or PETSC_NULL

 21:   Level: developer

 23: .seealso: SlepcInitialize()
 24: @*/
 25: PetscErrorCode STInitializePackage(char *path) {
 26:   static PetscTruth initialized = PETSC_FALSE;
 27:   char              logList[256];
 28:   char             *className;
 29:   PetscTruth        opt;

 33:   if (initialized) return(0);
 34:   initialized = PETSC_TRUE;
 35:   /* Register Classes */
 36:   PetscLogClassRegister(&ST_COOKIE,"Spectral Transform");
 37:   /* Register Constructors */
 38:   STRegisterAll(path);
 39:   /* Register Events */
 40:   PetscLogEventRegister(&ST_SetUp,"STSetUp",ST_COOKIE);
 41:   PetscLogEventRegister(&ST_Apply,"STApply",ST_COOKIE);
 42:   PetscLogEventRegister(&ST_ApplyB,"STApplyB",ST_COOKIE);
 43:   PetscLogEventRegister(&ST_ApplyNoB,"STApplyNoB",ST_COOKIE);
 44:   PetscLogEventRegister(&ST_ApplyTranspose,"STApplyTranspose",ST_COOKIE);
 45:   PetscLogEventRegister(&ST_InnerProduct,"STInnerProduct",ST_COOKIE);
 46:   /* Process info exclusions */
 47:   PetscOptionsGetString(PETSC_NULL, "-log_info_exclude", logList, 256, &opt);
 48:   if (opt) {
 49:     PetscStrstr(logList, "st", &className);
 50:     if (className) {
 51:       PetscInfoDeactivateClass(ST_COOKIE);
 52:     }
 53:   }
 54:   /* Process summary exclusions */
 55:   PetscOptionsGetString(PETSC_NULL, "-log_summary_exclude", logList, 256, &opt);
 56:   if (opt) {
 57:     PetscStrstr(logList, "st", &className);
 58:     if (className) {
 59:       PetscLogEventDeactivateClass(ST_COOKIE);
 60:     }
 61:   }
 62:   return(0);
 63: }

 67: /*@C
 68:    STDestroy - Destroys ST context that was created with STCreate().

 70:    Collective on ST

 72:    Input Parameter:
 73: .  st - the spectral transformation context

 75:    Level: beginner

 77: .seealso: STCreate(), STSetUp()
 78: @*/
 79: PetscErrorCode STDestroy(ST st)
 80: {

 85:   if (--st->refct > 0) return(0);

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

 90:   if (st->ops->destroy) { (*st->ops->destroy)(st); }
 91:   if (st->ksp) { KSPDestroy(st->ksp); }
 92:   if (st->w) { VecDestroy(st->w); }
 93:   if (st->Bx) { VecDestroy(st->Bx); }
 94:   if (st->shift_matrix != STMATMODE_INPLACE && st->mat) {
 95:     MatDestroy(st->mat);
 96:   }

 98:   PetscLogObjectDestroy(st);
 99:   PetscHeaderDestroy(st);
100:   return(0);
101: }

105: static PetscErrorCode STPublish_Petsc(PetscObject object)
106: {
108:   return(0);
109: }

113: /*@C
114:    STCreate - Creates a spectral transformation context.

116:    Collective on MPI_Comm

118:    Input Parameter:
119: .  comm - MPI communicator 

121:    Output Parameter:
122: .  st - location to put the spectral transformation context

124:    Level: beginner

126: .seealso: STSetUp(), STApply(), STDestroy()
127: @*/
128: PetscErrorCode STCreate(MPI_Comm comm,ST *newst)
129: {
131:   ST             st;
132:   const char     *prefix;

136:   *newst = 0;

138:   PetscHeaderCreate(st,_p_ST,struct _STOps,ST_COOKIE,-1,"ST",comm,STDestroy,STView);
139:   PetscLogObjectCreate(st);
140:   st->bops->publish       = STPublish_Petsc;
141:   PetscMemzero(st->ops,sizeof(struct _STOps));

143:   st->A                   = 0;
144:   st->B                   = 0;
145:   st->sigma               = 0.0;
146:   st->data                = 0;
147:   st->setupcalled         = 0;
148:   st->w                   = 0;
149:   st->shift_matrix        = STMATMODE_COPY;
150:   st->bilinear_form       = STINNER_HERMITIAN;
151:   st->str                 = DIFFERENT_NONZERO_PATTERN;
152: 
153:   KSPCreate(st->comm,&st->ksp);
154:   STGetOptionsPrefix(st,&prefix);
155:   KSPSetOptionsPrefix(st->ksp,prefix);
156:   KSPAppendOptionsPrefix(st->ksp,"st_");
157: 
158:   *newst                  = st;
159:   PetscPublishAll(st);
160:   return(0);

162: }

166: /*@
167:    STSetOperators - Sets the matrices associated with the eigenvalue problem. 

169:    Collective on ST and Mat

171:    Input Parameters:
172: +  st - the spectral transformation context
173: .  A  - the matrix associated with the eigensystem
174: -  B  - the second matrix in the case of generalized eigenproblems

176:    Notes:
177:    To specify a standard eigenproblem, use PETSC_NULL for B.

179:    Level: intermediate

181: .seealso: STGetOperators()
182:  @*/
183: PetscErrorCode STSetOperators(ST st,Mat A,Mat B)
184: {
191:   st->A = A;
192:   st->B = B;
193:   st->setupcalled = 0;
194:   return(0);
195: }

199: /*@C
200:    STGetOperators - Gets the matrices associated with the eigensystem.

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

204:    Input Parameter:
205: .  st - the spectral transformation context

207:    Output Parameters:
208: .  A - the matrix associated with the eigensystem
209: -  B - the second matrix in the case of generalized eigenproblems

211:    Level: intermediate

213: .seealso: STSetOperators()
214: @*/
215: PetscErrorCode STGetOperators(ST st,Mat *A,Mat *B)
216: {
219:   if (A) *A = st->A;
220:   if (B) *B = st->B;
221:   return(0);
222: }

226: /*@
227:    STSetShift - Sets the shift associated with the spectral transformation

229:    Not collective

231:    Input Parameters:
232: +  st - the spectral transformation context
233: -  shift - the value of the shift

235:    Note:
236:    In some spectral transformations, changing the shift may have associated
237:    a lot of work, for example recomputing a factorization.
238:    
239:    Level: beginner

241: @*/
242: PetscErrorCode STSetShift(ST st,PetscScalar shift)
243: {

248:   if (st->sigma != shift) {
249:     if (st->ops->setshift) {
250:       (*st->ops->setshift)(st,shift);
251:     }
252:   }
253:   st->sigma = shift;
254:   return(0);
255: }

259: /*@
260:    STGetShift - Gets the shift associated with the spectral transformation.

262:    Not collective

264:    Input Parameter:
265: .  st - the spectral transformation context

267:    Output Parameter:
268: .  shift - the value of the shift

270:    Level: beginner

272: @*/
273: PetscErrorCode STGetShift(ST st,PetscScalar* shift)
274: {
277:   if (shift)  *shift = st->sigma;
278:   return(0);
279: }

283: /*@C
284:    STSetOptionsPrefix - Sets the prefix used for searching for all 
285:    ST options in the database.

287:    Collective on ST

289:    Input Parameters:
290: +  st     - the spectral transformation context
291: -  prefix - the prefix string to prepend to all ST option requests

293:    Notes:
294:    A hyphen (-) must NOT be given at the beginning of the prefix name.
295:    The first character of all runtime options is AUTOMATICALLY the
296:    hyphen.

298:    Level: advanced

300: .seealso: STAppendOptionsPrefix(), STGetOptionsPrefix()
301: @*/
302: PetscErrorCode STSetOptionsPrefix(ST st,char *prefix)
303: {

308:   PetscObjectSetOptionsPrefix((PetscObject)st, prefix);
309:   return(0);
310: }

314: /*@C
315:    STAppendOptionsPrefix - Appends to the prefix used for searching for all 
316:    ST options in the database.

318:    Collective on ST

320:    Input Parameters:
321: +  st     - the spectral transformation context
322: -  prefix - the prefix string to prepend to all ST option requests

324:    Notes:
325:    A hyphen (-) must NOT be given at the beginning of the prefix name.
326:    The first character of all runtime options is AUTOMATICALLY the
327:    hyphen.

329:    Level: advanced

331: .seealso: STSetOptionsPrefix(), STGetOptionsPrefix()
332: @*/
333: PetscErrorCode STAppendOptionsPrefix(ST st,char *prefix)
334: {

339:   PetscObjectAppendOptionsPrefix((PetscObject)st, prefix);
340:   return(0);
341: }

345: /*@C
346:    STGetOptionsPrefix - Gets the prefix used for searching for all 
347:    ST options in the database.

349:    Not Collective

351:    Input Parameters:
352: .  st - the spectral transformation context

354:    Output Parameters:
355: .  prefix - pointer to the prefix string used, is returned

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

360:    Level: advanced

362: .seealso: STSetOptionsPrefix(), STAppendOptionsPrefix()
363: @*/
364: PetscErrorCode STGetOptionsPrefix(ST st,const char *prefix[])
365: {

370:   PetscObjectGetOptionsPrefix((PetscObject)st, prefix);
371:   return(0);
372: }

376: /*@C
377:    STView - Prints the ST data structure.

379:    Collective on ST

381:    Input Parameters:
382: +  ST - the ST context
383: -  viewer - optional visualization context

385:    Note:
386:    The available visualization contexts include
387: +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
388: -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
389:          output where only the first processor opens
390:          the file.  All other processors send their 
391:          data to the first processor to print. 

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

396:    Level: beginner

398: .seealso: EPSView(), PetscViewerASCIIOpen()
399: @*/
400: PetscErrorCode STView(ST st,PetscViewer viewer)
401: {
402:   PetscErrorCode    ierr;
403:   STType            cstr;
404:   const char*       str;
405:   PetscTruth        isascii,isstring;
406:   PetscViewerFormat format;

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

414:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
415:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);
416:   if (isascii) {
417:     PetscViewerGetFormat(viewer,&format);
418:     PetscViewerASCIIPrintf(viewer,"ST Object:\n");
419:     STGetType(st,&cstr);
420:     if (cstr) {
421:       PetscViewerASCIIPrintf(viewer,"  type: %s\n",cstr);
422:     } else {
423:       PetscViewerASCIIPrintf(viewer,"  type: not yet set\n");
424:     }
425: #if !defined(PETSC_USE_COMPLEX)
426:     PetscViewerASCIIPrintf(viewer,"  shift: %g\n",st->sigma);
427: #else
428:     PetscViewerASCIIPrintf(viewer,"  shift: %g+%g i\n",PetscRealPart(st->sigma),PetscImaginaryPart(st->sigma));
429: #endif
430:     switch (st->shift_matrix) {
431:     case STMATMODE_COPY:
432:       break;
433:     case STMATMODE_INPLACE:
434:       PetscViewerASCIIPrintf(viewer,"Shifting the matrix and unshifting at exit\n");
435:       break;
436:     case STMATMODE_SHELL:
437:       PetscViewerASCIIPrintf(viewer,"Using a shell matrix\n");
438:       break;
439:     }
440:     if (st->B && st->shift_matrix != STMATMODE_SHELL) {
441:       switch (st->str) {
442:         case SAME_NONZERO_PATTERN:      str = "same nonzero pattern";break;
443:         case DIFFERENT_NONZERO_PATTERN: str = "different nonzero pattern";break;
444:         case SUBSET_NONZERO_PATTERN:    str = "subset nonzero pattern";break;
445:         default:                        SETERRQ(1,"Wrong structure flag");
446:       }
447:       PetscViewerASCIIPrintf(viewer,"Matrices A and B have %s\n",str);
448:     }
449:     if (st->ops->view) {
450:       PetscViewerASCIIPushTab(viewer);
451:       (*st->ops->view)(st,viewer);
452:       PetscViewerASCIIPopTab(viewer);
453:     }
454:   } else if (isstring) {
455:     STGetType(st,&cstr);
456:     PetscViewerStringSPrintf(viewer," %-7.7s",cstr);
457:     if (st->ops->view) {(*st->ops->view)(st,viewer);}
458:   } else {
459:     SETERRQ1(1,"Viewer type %s not supported by ST",((PetscObject)viewer)->type_name);
460:   }
461:   return(0);
462: }

466: PetscErrorCode STView_Default(ST st,PetscViewer viewer)
467: {
469:   PetscTruth     isascii,isstring;

472:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
473:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_STRING,&isstring);
474:   if (isascii) {
475:     PetscViewerASCIIPushTab(viewer);
476:     PetscViewerASCIIPrintf(viewer,"Associated KSP object\n");
477:     PetscViewerASCIIPrintf(viewer,"------------------------------\n");
478:     KSPView(st->ksp,viewer);
479:     PetscViewerASCIIPrintf(viewer,"------------------------------\n");
480:     PetscViewerASCIIPopTab(viewer);
481:   } else if (isstring) {
482:     KSPView(st->ksp,viewer);
483:   }
484:   return(0);
485: }

487: /*MC
488:    STRegisterDynamic - Adds a method to the spectral transformation package.

490:    Synopsis:
491:    STRegisterDynamic(char *name_solver,char *path,char *name_create,int (*routine_create)(ST))

493:    Not collective

495:    Input Parameters:
496: +  name_solver - name of a new user-defined solver
497: .  path - path (either absolute or relative) the library containing this solver
498: .  name_create - name of routine to create method context
499: -  routine_create - routine to create method context

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

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

507:    Sample usage:
508: .vb
509:    STRegisterDynamic("my_solver","/home/username/my_lib/lib/libO/solaris/mylib.a",
510:               "MySolverCreate",MySolverCreate);
511: .ve

513:    Then, your solver can be chosen with the procedural interface via
514: $     STSetType(st,"my_solver")
515:    or at runtime via the option
516: $     -st_type my_solver

518:    Level: advanced

520:    $SLEPC_DIR, $PETSC_ARCH and $BOPT occuring in pathname will be replaced with appropriate values.

522: .seealso: STRegisterAll(), STRegister()
523: M*/

527: PetscErrorCode STRegister(const char *sname,const char *path,const char *name,int (*function)(ST))
528: {
530:   char           fullname[256];

533:   PetscFListConcat(path,name,fullname);
534:   PetscFListAdd(&STList,sname,fullname,(void (*)(void))function);
535:   return(0);
536: }