Actual source code: itcreate.c

  1: /*$Id: itcreate.c,v 1.206 2001/08/06 21:16:38 bsmith Exp $*/
  2: /*
  3:      The basic KSP routines, Create, View etc. are here.
  4: */
 5:  #include src/sles/ksp/kspimpl.h
 6:  #include petscsys.h

  8: /* Logging support */
  9: int KSP_COOKIE;
 10: int KSP_GMRESOrthogonalization;

 12: EXTERN int SLESInitializePackage(char *);

 14: PetscTruth KSPRegisterAllCalled = PETSC_FALSE;

 16: /*@C 
 17:    KSPView - Prints the KSP data structure.

 19:    Collective on KSP

 21:    Input Parameters:
 22: +  ksp - the Krylov space context
 23: -  viewer - visualization context

 25:    Note:
 26:    The available visualization contexts include
 27: +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
 28: -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
 29:          output where only the first processor opens
 30:          the file.  All other processors send their 
 31:          data to the first processor to print. 

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

 36:    Level: developer

 38: .keywords: KSP, view

 40: .seealso: PCView(), PetscViewerASCIIOpen()
 41: @*/
 42: int KSPView(KSP ksp,PetscViewer viewer)
 43: {
 44:   char        *type;
 45:   int         ierr;
 46:   PetscTruth  isascii;

 50:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(ksp->comm);

 54:   PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
 55:   if (isascii) {
 56:     KSPGetType(ksp,&type);
 57:     if (ksp->prefix) {
 58:       PetscViewerASCIIPrintf(viewer,"KSP Object:(%s)n",ksp->prefix);
 59:     } else {
 60:       PetscViewerASCIIPrintf(viewer,"KSP Object:n");
 61:     }
 62:     if (type) {
 63:       PetscViewerASCIIPrintf(viewer,"  type: %sn",type);
 64:     } else {
 65:       PetscViewerASCIIPrintf(viewer,"  type: not yet setn");
 66:     }
 67:     if (ksp->ops->view) {
 68:       PetscViewerASCIIPushTab(viewer);
 69:       (*ksp->ops->view)(ksp,viewer);
 70:       PetscViewerASCIIPopTab(viewer);
 71:     }
 72:     if (ksp->guess_zero) {PetscViewerASCIIPrintf(viewer,"  maximum iterations=%d, initial guess is zeron",ksp->max_it);}
 73:     else                 {PetscViewerASCIIPrintf(viewer,"  maximum iterations=%dn", ksp->max_it);}
 74:     PetscViewerASCIIPrintf(viewer,"  tolerances:  relative=%g, absolute=%g, divergence=%gn",ksp->rtol,ksp->atol,ksp->divtol);
 75:     if (ksp->pc_side == PC_RIGHT)          {PetscViewerASCIIPrintf(viewer,"  right preconditioningn");}
 76:     else if (ksp->pc_side == PC_SYMMETRIC) {PetscViewerASCIIPrintf(viewer,"  symmetric preconditioningn");}
 77:     else                                   {PetscViewerASCIIPrintf(viewer,"  left preconditioningn");}
 78:   } else {
 79:     if (ksp->ops->view) {
 80:       (*ksp->ops->view)(ksp,viewer);
 81:     }
 82:   }
 83:   return(0);
 84: }

 86: /*
 87:    Contains the list of registered KSP routines
 88: */
 89: PetscFList KSPList = 0;

 91: /*@C
 92:    KSPSetNormType - Sets the norm that is used for convergence testing.

 94:    Collective on KSP

 96:    Input Parameter:
 97: +  ksp - Krylov solver context
 98: -  normtype - one of 
 99: $   KSP_NO_NORM - skips computing the norm, this should only be used if you are using
100: $                 the Krylov method as a smoother with a fixed small number of iterations.
101: $                 You must also call KSPSetConvergenceTest(ksp,KSPSkipConverged,PETSC_NULL);
102: $                 supported only by CG, Richardson, Bi-CG-stab, CR, and CGS methods.
103: $   KSP_PRECONDITIONED_NORM - the default for left preconditioned solves, uses the l2 norm
104: $                 of the preconditioned residual
105: $   KSP_UNPRECONDITIONED_NORM - uses the l2 norm of the true b - Ax residual, supported only by
106: $                 CG, CHEBYCHEV, and RICHARDSON  
107: $   KSP_NATURAL_NORM - supported  by cg, cr, and cgs 


110:    Notes: 
111:    Currently only works with the CG, Richardson, Bi-CG-stab, CR, and CGS methods.

113:    Level: advanced

115: .keywords: KSP, create, context, norms

117: .seealso: KSPSetUp(), KSPSolve(), KSPDestroy(), KSPSkipConverged()                               
118: @*/
119: int KSPSetNormType(KSP ksp,KSPNormType normtype)
120: {

124:   ksp->normtype = normtype;
125:   if (normtype == KSP_NO_NORM) {
126:     PetscLogInfo(ksp,"KSPSetNormType:Warning seting KSPNormType to skip computing the normn
127:   make sure you set the KSP convergence test to KSPSkipConvergencen");
128:   }
129:   return(0);
130: }

132: static int KSPPublish_Petsc(PetscObject obj)
133: {
134: #if defined(PETSC_HAVE_AMS)
135:   KSP          v = (KSP) obj;
136:   int          ierr;
137: #endif


141: #if defined(PETSC_HAVE_AMS)
142:   /* if it is already published then return */
143:   if (v->amem >=0) return(0);

145:   PetscObjectPublishBaseBegin(obj);
146:   AMS_Memory_add_field((AMS_Memory)v->amem,"Iteration",&v->its,1,AMS_INT,AMS_READ,
147:                                 AMS_COMMON,AMS_REDUCT_UNDEF);
148:   AMS_Memory_add_field((AMS_Memory)v->amem,"Residual",&v->rnorm,1,AMS_DOUBLE,AMS_READ,
149:                                 AMS_COMMON,AMS_REDUCT_UNDEF);

151:   if (v->res_hist_max > 0) {
152:     AMS_Memory_add_field((AMS_Memory)v->amem,"ResidualNormsCount",&v->res_hist_len,1,AMS_INT,AMS_READ,
153:                                 AMS_COMMON,AMS_REDUCT_UNDEF);
154:     AMS_Memory_add_field((AMS_Memory)v->amem,"ResidualNormsCountMax",&v->res_hist_max,1,AMS_INT,AMS_READ,
155:                                 AMS_COMMON,AMS_REDUCT_UNDEF);
156:     AMS_Memory_add_field((AMS_Memory)v->amem,"ResidualNorms",v->res_hist,v->res_hist_max,AMS_DOUBLE,AMS_READ,
157:                                 AMS_COMMON,AMS_REDUCT_UNDEF);
158:   }

160:   PetscObjectPublishBaseEnd(obj);
161: #endif

163:   return(0);
164: }


167: /*@C
168:    KSPCreate - Creates the default KSP context.

170:    Collective on MPI_Comm

172:    Input Parameter:
173: .  comm - MPI communicator

175:    Output Parameter:
176: .  ksp - location to put the KSP context

178:    Notes:
179:    The default KSP type is GMRES with a restart of 30, using modified Gram-Schmidt
180:    orthogonalization.

182:    Level: developer

184: .keywords: KSP, create, context

186: .seealso: KSPSetUp(), KSPSolve(), KSPDestroy(), KSP
187: @*/
188: int KSPCreate(MPI_Comm comm,KSP *inksp)
189: {
190:   KSP ksp;

195:   *inksp = 0;
196: #ifndef PETSC_USE_DYNAMIC_LIBRARIES
197:   SLESInitializePackage(PETSC_NULL);
198: #endif

200:   PetscHeaderCreate(ksp,_p_KSP,struct _KSPOps,KSP_COOKIE,-1,"KSP",comm,KSPDestroy,KSPView);
201:   PetscLogObjectCreate(ksp);
202:   *inksp             = ksp;
203:   ksp->bops->publish = KSPPublish_Petsc;

205:   ksp->type          = -1;
206:   ksp->max_it        = 10000;
207:   ksp->pc_side       = PC_LEFT;
208:   ksp->rtol          = 1.e-5;
209:   ksp->atol          = 1.e-50;
210:   ksp->divtol        = 1.e4;

212:   ksp->normtype            = KSP_PRECONDITIONED_NORM;
213:   ksp->rnorm               = 0.0;
214:   ksp->its                 = 0;
215:   ksp->guess_zero          = PETSC_TRUE;
216:   ksp->calc_sings          = PETSC_FALSE;
217:   ksp->res_hist            = PETSC_NULL;
218:   ksp->res_hist_len        = 0;
219:   ksp->res_hist_max        = 0;
220:   ksp->res_hist_reset      = PETSC_TRUE;
221:   ksp->numbermonitors      = 0;
222:   ksp->converged           = KSPDefaultConverged;
223:   ksp->ops->buildsolution  = KSPDefaultBuildSolution;
224:   ksp->ops->buildresidual  = KSPDefaultBuildResidual;

226:   ksp->ops->setfromoptions = 0;

228:   ksp->vec_sol         = 0;
229:   ksp->vec_rhs         = 0;
230:   ksp->B               = 0;

232:   ksp->ops->solve      = 0;
233:   ksp->ops->setup      = 0;
234:   ksp->ops->destroy    = 0;

236:   ksp->data            = 0;
237:   ksp->nwork           = 0;
238:   ksp->work            = 0;

240:   ksp->cnvP            = 0;

242:   ksp->reason          = KSP_CONVERGED_ITERATING;

244:   ksp->setupcalled     = 0;
245:   PetscPublishAll(ksp);
246:   return(0);
247: }
248: 
249: /*@C
250:    KSPSetType - Builds KSP for a particular solver. 

252:    Collective on KSP

254:    Input Parameters:
255: +  ksp      - the Krylov space context
256: -  type - a known method

258:    Options Database Key:
259: .  -ksp_type  <method> - Sets the method; use -help for a list 
260:     of available methods (for instance, cg or gmres)

262:    Notes:  
263:    See "petsc/include/petscksp.h" for available methods (for instance,
264:    KSPCG or KSPGMRES).

266:   Normally, it is best to use the SLESSetFromOptions() command and
267:   then set the KSP type from the options database rather than by using
268:   this routine.  Using the options database provides the user with
269:   maximum flexibility in evaluating the many different Krylov methods.
270:   The KSPSetType() routine is provided for those situations where it
271:   is necessary to set the iterative solver independently of the command
272:   line or options database.  This might be the case, for example, when
273:   the choice of iterative solver changes during the execution of the
274:   program, and the user's application is taking responsibility for
275:   choosing the appropriate method.  In other words, this routine is
276:   not for beginners.

278:   Level: intermediate

280: .keywords: KSP, set, method

282: .seealso: PCSetType(), KSPType

284: @*/
285: int KSPSetType(KSP ksp,KSPType type)
286: {
287:   int        ierr,(*r)(KSP);
288:   PetscTruth match;


294:   PetscTypeCompare((PetscObject)ksp,type,&match);
295:   if (match) return(0);

297:   if (ksp->data) {
298:     /* destroy the old private KSP context */
299:     (*ksp->ops->destroy)(ksp);
300:     ksp->data = 0;
301:   }
302:   /* Get the function pointers for the iterative method requested */
303:   if (!KSPRegisterAllCalled) {KSPRegisterAll(PETSC_NULL);}

305:    PetscFListFind(ksp->comm,KSPList,type,(void (**)(void)) &r);

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

309:   ksp->setupcalled = 0;
310:   (*r)(ksp);

312:   PetscObjectChangeTypeName((PetscObject)ksp,type);
313:   return(0);
314: }

316: /*@C
317:    KSPRegisterDestroy - Frees the list of KSP methods that were
318:    registered by KSPRegisterDynamic().

320:    Not Collective

322:    Level: advanced

324: .keywords: KSP, register, destroy

326: .seealso: KSPRegisterDynamic(), KSPRegisterAll()
327: @*/
328: int KSPRegisterDestroy(void)
329: {

333:   if (KSPList) {
334:     PetscFListDestroy(&KSPList);
335:     KSPList = 0;
336:   }
337:   KSPRegisterAllCalled = PETSC_FALSE;
338:   return(0);
339: }

341: /*@C
342:    KSPGetType - Gets the KSP type as a string from the KSP object.

344:    Not Collective

346:    Input Parameter:
347: .  ksp - Krylov context 

349:    Output Parameter:
350: .  name - name of KSP method 

352:    Level: intermediate

354: .keywords: KSP, get, method, name

356: .seealso: KSPSetType()
357: @*/
358: int KSPGetType(KSP ksp,KSPType *type)
359: {
362:   *type = ksp->type_name;
363:   return(0);
364: }

366: /*@
367:    KSPSetFromOptions - Sets KSP options from the options database.
368:    This routine must be called before KSPSetUp() if the user is to be 
369:    allowed to set the Krylov type. 

371:    Collective on KSP

373:    Input Parameters:
374: .  ksp - the Krylov space context

376:    Options Database Keys:
377: +   -ksp_max_it - maximum number of linear iterations
378: .   -ksp_rtol rtol - relative tolerance used in default determination of convergence, i.e.
379:                 if residual norm decreases by this factor than convergence is declared
380: .   -ksp_atol atol - absolute tolerance used in default convergence test, i.e. if residual 
381:                 norm is less than this then convergence is declared
382: .   -ksp_divtol tol - if residual norm increases by this factor than divergence is declared
383: .   -ksp_norm_type - none - skip norms used in convergence tests (useful only when not using 
384: $                       convergence test (say you always want to run with 5 iterations) to 
385: $                       save on communication overhead
386: $                    preconditioned - default for left preconditioning 
387: $                    unpreconditioned - see KSPSetNormType()
388: $                    natural - see KSPSetNormType()
389: .   -ksp_cancelmonitors - cancel all previous convergene monitor routines set
390: .   -ksp_monitor - print residual norm at each iteration
391: .   -ksp_xmonitor - plot residual norm at each iteration
392: .   -ksp_vecmonitor - plot solution at each iteration
393: -   -ksp_singmonitor - monitor extremem singular values at each iteration

395:    Notes:  
396:    To see all options, run your program with the -help option
397:    or consult the users manual.

399:    Level: developer

401: .keywords: KSP, set, from, options, database

403: .seealso: 
404: @*/
405: int KSPSetFromOptions(KSP ksp)
406: {
407:   int        ierr;
408:   char       type[256],*stype[] = {"none","preconditioned","unpreconditioned","natural"};
409:   PetscTruth flg;

413:   if (!KSPRegisterAllCalled) {KSPRegisterAll(PETSC_NULL);}
414:   PetscOptionsBegin(ksp->comm,ksp->prefix,"Krylov Method (KSP) Options","KSP");
415:     PetscOptionsList("-ksp_type","Krylov method","KSPSetType",KSPList,(char*)(ksp->type_name?ksp->type_name:KSPGMRES),type,256,&flg);
416:     if (flg) {
417:       KSPSetType(ksp,type);
418:     }
419:     /*
420:       Set the type if it was never set.
421:     */
422:     if (!ksp->type_name) {
423:       KSPSetType(ksp,KSPGMRES);
424:     }

426:     PetscOptionsInt("-ksp_max_it","Maximum number of iterations","KSPSetTolerances",ksp->max_it,&ksp->max_it,PETSC_NULL);
427:     PetscOptionsReal("-ksp_rtol","Relative decrease in residual norm","KSPSetTolerances",ksp->rtol,&ksp->rtol,PETSC_NULL);
428:     PetscOptionsReal("-ksp_atol","Absolute value of residual norm","KSPSetTolerances",ksp->atol,&ksp->atol,PETSC_NULL);
429:     PetscOptionsReal("-ksp_divtol","Residual norm increase cause divergence","KSPSetTolerances",ksp->divtol,&ksp->divtol,PETSC_NULL);

431:     PetscOptionsEList("-ksp_norm_type","KSP Norm type","KSPSetNormType",stype,4,"preconditioned",type,256,&flg);
432:     if (flg) {
433:       PetscTruth isnone,ispreconditioned,isunpreconditioned,isnatural;

435:       PetscStrcmp(type,stype[0],&isnone);
436:       PetscStrcmp(type,stype[1],&ispreconditioned);
437:       PetscStrcmp(type,stype[2],&isunpreconditioned);
438:       PetscStrcmp(type,stype[3],&isnatural);

440:       if (isnone) {
441:         KSPSetNormType(ksp,KSP_NO_NORM);
442:         KSPSetConvergenceTest(ksp,KSPSkipConverged,0);
443:       } else if (ispreconditioned) {
444:         KSPSetNormType(ksp,KSP_PRECONDITIONED_NORM);
445:       } else if (isunpreconditioned) {
446:         KSPSetNormType(ksp,KSP_UNPRECONDITIONED_NORM);
447:       } else if (isnatural) {
448:         KSPSetNormType(ksp,KSP_NATURAL_NORM);
449:       } else {
450:         SETERRQ1(1,"Unknown KSP normtype %s",type);
451:       }
452:     }

454:     PetscOptionsName("-ksp_cancelmonitors","Remove any hardwired monitor routines","KSPClearMonitor",&flg);
455:     /* -----------------------------------------------------------------------*/
456:     /*
457:       Cancels all monitors hardwired into code before call to KSPSetFromOptions()
458:     */
459:     if (flg) {
460:       KSPClearMonitor(ksp);
461:     }
462:     /*
463:       Prints preconditioned residual norm at each iteration
464:     */
465:     PetscOptionsName("-ksp_monitor","Monitor preconditioned residual norm","KSPSetMonitor",&flg);
466:     if (flg) {
467:       KSPSetMonitor(ksp,KSPDefaultMonitor,PETSC_NULL,PETSC_NULL);
468:     }
469:     /*
470:       Plots the vector solution 
471:     */
472:     PetscOptionsName("-ksp_vecmonitor","Monitor solution graphically","KSPSetMonitor",&flg);
473:     if (flg) {
474:       KSPSetMonitor(ksp,KSPVecViewMonitor,PETSC_NULL,PETSC_NULL);
475:     }
476:     /*
477:       Prints preconditioned and true residual norm at each iteration
478:     */
479:     PetscOptionsName("-ksp_truemonitor","Monitor true (unpreconditioned) residual norm","KSPSetMonitor",&flg);
480:     if (flg) {
481:       KSPSetMonitor(ksp,KSPTrueMonitor,PETSC_NULL,PETSC_NULL);
482:     }
483:     /*
484:       Prints extreme eigenvalue estimates at each iteration
485:     */
486:     PetscOptionsName("-ksp_singmonitor","Monitor singular values","KSPSetMonitor",&flg);
487:     if (flg) {
488:       KSPSetComputeSingularValues(ksp,PETSC_TRUE);
489:       KSPSetMonitor(ksp,KSPSingularValueMonitor,PETSC_NULL,PETSC_NULL);
490:     }
491:     /*
492:       Prints preconditioned residual norm with fewer digits
493:     */
494:     PetscOptionsName("-ksp_smonitor","Monitor preconditioned residual norm with fewer digitis","KSPSetMonitor",&flg);
495:     if (flg) {
496:       KSPSetMonitor(ksp,KSPDefaultSMonitor,PETSC_NULL,PETSC_NULL);
497:     }
498:     /*
499:       Graphically plots preconditioned residual norm
500:     */
501:     PetscOptionsName("-ksp_xmonitor","Monitor graphically preconditioned residual norm","KSPSetMonitor",&flg);
502:     if (flg) {
503:       KSPSetMonitor(ksp,KSPLGMonitor,PETSC_NULL,PETSC_NULL);
504:     }
505:     /*
506:       Graphically plots preconditioned and true residual norm
507:     */
508:     PetscOptionsName("-ksp_xtruemonitor","Monitor graphically true residual norm","KSPSetMonitor",&flg);
509:     if (flg){
510:       KSPSetMonitor(ksp,KSPLGTrueMonitor,PETSC_NULL,PETSC_NULL);
511:     }

513:     /* -----------------------------------------------------------------------*/

515:     PetscOptionsLogicalGroupBegin("-ksp_left_pc","Use left preconditioning","KSPSetPreconditionerSide",&flg);
516:     if (flg) { KSPSetPreconditionerSide(ksp,PC_LEFT); }
517:     PetscOptionsLogicalGroup("-ksp_right_pc","Use right preconditioning","KSPSetPreconditionerSide",&flg);
518:     if (flg) { KSPSetPreconditionerSide(ksp,PC_RIGHT);}
519:     PetscOptionsLogicalGroupEnd("-ksp_symmetric_pc","Use symmetric (factorized) preconditioning","KSPSetPreconditionerSide",&flg);
520:     if (flg) { KSPSetPreconditionerSide(ksp,PC_SYMMETRIC);}

522:     PetscOptionsName("-ksp_compute_singularvalues","Compute singular values of preconditioned operator","KSPSetComputeSingularValues",&flg);
523:     if (flg) { KSPSetComputeSingularValues(ksp,PETSC_TRUE); }
524:     PetscOptionsName("-ksp_compute_eigenvalues","Compute eigenvalues of preconditioned operator","KSPSetComputeSingularValues",&flg);
525:     if (flg) { KSPSetComputeSingularValues(ksp,PETSC_TRUE); }
526:     PetscOptionsName("-ksp_plot_eigenvalues","Scatter plot extreme eigenvalues","KSPSetComputeSingularValues",&flg);
527:     if (flg) { KSPSetComputeSingularValues(ksp,PETSC_TRUE); }

529:     if (ksp->ops->setfromoptions) {
530:       (*ksp->ops->setfromoptions)(ksp);
531:     }
532:   PetscOptionsEnd();


535:   return(0);
536: }

538: /*MC
539:    KSPRegisterDynamic - Adds a method to the Krylov subspace solver package.

541:    Synopsis:
542:    int KSPRegisterDynamic(char *name_solver,char *path,char *name_create,int (*routine_create)(KSP))

544:    Not Collective

546:    Input Parameters:
547: +  name_solver - name of a new user-defined solver
548: .  path - path (either absolute or relative) the library containing this solver
549: .  name_create - name of routine to create method context
550: -  routine_create - routine to create method context

552:    Notes:
553:    KSPRegisterDynamic() may be called multiple times to add several user-defined solvers.

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

558:    Sample usage:
559: .vb
560:    KSPRegisterDynamic("my_solver",/home/username/my_lib/lib/libO/solaris/mylib.a,
561:                "MySolverCreate",MySolverCreate);
562: .ve

564:    Then, your solver can be chosen with the procedural interface via
565: $     KSPSetType(ksp,"my_solver")
566:    or at runtime via the option
567: $     -ksp_type my_solver

569:    Level: advanced

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

575: .keywords: KSP, register

577: .seealso: KSPRegisterAll(), KSPRegisterDestroy()

579: M*/

581: int KSPRegister(char *sname,char *path,char *name,int (*function)(KSP))
582: {
583:   int  ierr;
584:   char fullname[256];

587:   PetscFListConcat(path,name,fullname);
588:   PetscFListAdd(&KSPList,sname,fullname,(void (*)(void))function);
589:   return(0);
590: }