Actual source code: itcl.c

  1: #define PETSCKSP_DLL

  3: /*
  4:     Code for setting KSP options from the options database.
  5: */

 7:  #include private/kspimpl.h

  9: /*
 10:        We retain a list of functions that also take KSP command 
 11:     line options. These are called at the end KSPSetFromOptions()
 12: */
 13: #define MAXSETFROMOPTIONS 5
 14: PetscInt numberofsetfromoptions = 0;
 15: PetscErrorCode (*othersetfromoptions[MAXSETFROMOPTIONS])(KSP) = {0};


 21: /*@C
 22:     KSPAddOptionsChecker - Adds an additional function to check for KSP options.

 24:     Not Collective

 26:     Input Parameter:
 27: .   kspcheck - function that checks for options

 29:     Level: developer

 31: .keywords: KSP, add, options, checker

 33: .seealso: KSPSetFromOptions()
 34: @*/
 35: PetscErrorCode  KSPAddOptionsChecker(PetscErrorCode (*kspcheck)(KSP))
 36: {
 38:   if (numberofsetfromoptions >= MAXSETFROMOPTIONS) {
 39:     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Too many options checkers, only 5 allowed");
 40:   }

 42:   othersetfromoptions[numberofsetfromoptions++] = kspcheck;
 43:   return(0);
 44: }

 48: /*@C
 49:    KSPSetOptionsPrefix - Sets the prefix used for searching for all 
 50:    KSP options in the database.

 52:    Collective on KSP

 54:    Input Parameters:
 55: +  ksp - the Krylov context
 56: -  prefix - the prefix string to prepend to all KSP option requests

 58:    Notes:
 59:    A hyphen (-) must NOT be given at the beginning of the prefix name.
 60:    The first character of all runtime options is AUTOMATICALLY the
 61:    hyphen.

 63:    For example, to distinguish between the runtime options for two
 64:    different KSP contexts, one could call
 65: .vb
 66:       KSPSetOptionsPrefix(ksp1,"sys1_")
 67:       KSPSetOptionsPrefix(ksp2,"sys2_")
 68: .ve

 70:    This would enable use of different options for each system, such as
 71: .vb
 72:       -sys1_ksp_type gmres -sys1_ksp_rtol 1.e-3
 73:       -sys2_ksp_type bcgs  -sys2_ksp_rtol 1.e-4
 74: .ve

 76:    Level: advanced

 78: .keywords: KSP, set, options, prefix, database

 80: .seealso: KSPAppendOptionsPrefix(), KSPGetOptionsPrefix()
 81: @*/
 82: PetscErrorCode  KSPSetOptionsPrefix(KSP ksp,const char prefix[])
 83: {
 87:   if (!ksp->pc) {KSPGetPC(ksp,&ksp->pc);}
 88:   PCSetOptionsPrefix(ksp->pc,prefix);
 89:   PetscObjectSetOptionsPrefix((PetscObject)ksp,prefix);
 90:   return(0);
 91: }
 92: 
 95: /*@C
 96:    KSPAppendOptionsPrefix - Appends to the prefix used for searching for all 
 97:    KSP options in the database.

 99:    Collective on KSP

101:    Input Parameters:
102: +  ksp - the Krylov context
103: -  prefix - the prefix string to prepend to all KSP option requests

105:    Notes:
106:    A hyphen (-) must NOT be given at the beginning of the prefix name.
107:    The first character of all runtime options is AUTOMATICALLY the hyphen.

109:    Level: advanced

111: .keywords: KSP, append, options, prefix, database

113: .seealso: KSPSetOptionsPrefix(), KSPGetOptionsPrefix()
114: @*/
115: PetscErrorCode  KSPAppendOptionsPrefix(KSP ksp,const char prefix[])
116: {
120:   if (!ksp->pc) {KSPGetPC(ksp,&ksp->pc);}
121:   PCAppendOptionsPrefix(ksp->pc,prefix);
122:   PetscObjectAppendOptionsPrefix((PetscObject)ksp,prefix);
123:   return(0);
124: }

128: /*@C
129:    KSPSetUseFischerGuess - Use the Paul Fischer algorithm, see KSPFischerGuessCreate()

131:    Collective on KSP

133:    Input Parameters:
134: +  ksp - the Krylov context
135: .  model - use model 1, model 2 or 0 to turn it off
136: -  size - size of subspace used to generate initial guess

138:     Options Database:
139: .   -ksp_fischer_guess <model,size> - uses the Fischer initial guess generator for repeated linear solves

141:    Level: advanced

143: .keywords: KSP, set, options, prefix, database

145: .seealso: KSPSetOptionsPrefix(), KSPAppendOptionsPrefix(), KSPSetUseFischerGuess(), KSPSetFischerGuess(), KSPGetFischerInitialGuess()
146: @*/
147: PetscErrorCode  KSPSetUseFischerGuess(KSP ksp,PetscInt model,PetscInt size)
148: {
152:   if (ksp->guess) {
153:     KSPFischerGuessDestroy(ksp->guess);
154:     ksp->guess = PETSC_NULL;
155:   }
156:   if (model == 1 || model == 2) {
157:     KSPFischerGuessCreate(ksp,model,size,&ksp->guess);
158:     KSPFischerGuessSetFromOptions(ksp->guess);
159:   } else if (model != 0) {
160:     SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Model must be 1 or 2 (or 0 to turn off guess generation)");
161:   }
162:   return(0);
163: }

167: /*@C
168:    KSPSetFischerGuess - Use the Paul Fischer algorithm created by KSPFischerGuessCreate()

170:    Collective on KSP

172:    Input Parameters:
173: +  ksp - the Krylov context
174: -  guess - the object created with KSPFischerGuessCreate()

176:    Level: advanced

178:    Notes: this allows a single KSP to be used with several different initial guess generators (likely for different linear
179:           solvers, see KSPSetPC()).

181:           This increases the reference count of the guess object, you must destroy the object with KSPFischerGuessDestroy()
182:           before the end of the program.

184: .keywords: KSP, set, options, prefix, database

186: .seealso: KSPSetOptionsPrefix(), KSPAppendOptionsPrefix(), KSPSetUseFischerGuess(), KSPSetFischerGuess(), KSPGetFischerGuess()
187: @*/
188: PetscErrorCode  KSPSetFischerGuess(KSP ksp,KSPFischerGuess guess)
189: {
193:   if (ksp->guess) {
194:     KSPFischerGuessDestroy(ksp->guess);
195:   }
196:   ksp->guess = guess;
197:   if (guess) guess->refcnt++;
198:   return(0);
199: }

203: /*@C
204:    KSPGetFischerGuess - Gets the initial guess generator set with either KSPSetFischerGuess() or KSPCreateFischerGuess()/KSPSetFischerGuess()

206:    Collective on KSP

208:    Input Parameters:
209: .  ksp - the Krylov context

211:    Output Parameters:
212: .   guess - the object

214:    Level: developer

216: .keywords: KSP, set, options, prefix, database

218: .seealso: KSPSetOptionsPrefix(), KSPAppendOptionsPrefix(), KSPSetUseFischerGuess(), KSPSetFischerGuess()
219: @*/
220: PetscErrorCode  KSPGetFischerGuess(KSP ksp,KSPFischerGuess *guess)
221: {
223:   *guess = ksp->guess;
224:   return(0);
225: }

229: /*@C
230:    KSPGetOptionsPrefix - Gets the prefix used for searching for all 
231:    KSP options in the database.

233:    Not Collective

235:    Input Parameters:
236: .  ksp - the Krylov context

238:    Output Parameters:
239: .  prefix - pointer to the prefix string used is returned

241:    Notes: On the fortran side, the user should pass in a string 'prifix' of
242:    sufficient length to hold the prefix.

244:    Level: advanced

246: .keywords: KSP, set, options, prefix, database

248: .seealso: KSPSetOptionsPrefix(), KSPAppendOptionsPrefix()
249: @*/
250: PetscErrorCode  KSPGetOptionsPrefix(KSP ksp,const char *prefix[])
251: {
255:   PetscObjectGetOptionsPrefix((PetscObject)ksp,prefix);
256:   return(0);
257: }

261: /*@
262:    KSPSetFromOptions - Sets KSP options from the options database.
263:    This routine must be called before KSPSetUp() if the user is to be 
264:    allowed to set the Krylov type. 

266:    Collective on KSP

268:    Input Parameters:
269: .  ksp - the Krylov space context

271:    Options Database Keys:
272: +   -ksp_max_it - maximum number of linear iterations
273: .   -ksp_rtol rtol - relative tolerance used in default determination of convergence, i.e.
274:                 if residual norm decreases by this factor than convergence is declared
275: .   -ksp_atol abstol - absolute tolerance used in default convergence test, i.e. if residual 
276:                 norm is less than this then convergence is declared
277: .   -ksp_divtol tol - if residual norm increases by this factor than divergence is declared
278: .   -ksp_converged_use_initial_residual_norm - see KSPDefaultConvergedSetUIRNorm()
279: .   -ksp_converged_use_min_initial_residual_norm - see KSPDefaultConvergedSetUMIRNorm()
280: .   -ksp_norm_type - none - skip norms used in convergence tests (useful only when not using 
281: $                       convergence test (say you always want to run with 5 iterations) to 
282: $                       save on communication overhead
283: $                    preconditioned - default for left preconditioning 
284: $                    unpreconditioned - see KSPSetNormType()
285: $                    natural - see KSPSetNormType()
286: .   -ksp_check_norm_iteration it - do not compute residual norm until iteration number it (does compute at 0th iteration)
287: $       works only for PCBCGS, PCIBCGS and and PCCG
288: .   -ksp_fischer_guess <model,size> - uses the Fischer initial guess generator for repeated linear solves
289: .   -ksp_constant_null_space - assume the operator (matrix) has the constant vector in its null space
290: .   -ksp_test_null_space - tests the null space set with KSPSetNullSpace() to see if it truly is a null space
291: .   -ksp_knoll - compute initial guess by applying the preconditioner to the right hand side
292: .   -ksp_monitor_cancel - cancel all previous convergene monitor routines set
293: .   -ksp_monitor <optional filename> - print residual norm at each iteration
294: .   -ksp_monitor_draw - plot residual norm at each iteration
295: .   -ksp_monitor_solution - plot solution at each iteration
296: -   -ksp_monitor_singular_value - monitor extremem singular values at each iteration

298:    Notes:  
299:    To see all options, run your program with the -help option
300:    or consult the users manual.

302:    Level: beginner

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

306: .seealso: KSPSetUseFischerInitialGuess()

308: @*/
309: PetscErrorCode  KSPSetFromOptions(KSP ksp)
310: {
311:   PetscErrorCode          ierr;
312:   PetscInt                indx;
313:   const char             *convtests[] = {"default","skip"};
314:   char                    type[256], monfilename[PETSC_MAX_PATH_LEN];
315:   PetscViewerASCIIMonitor monviewer;
316:   PetscTruth              flg,flag;
317:   PetscInt                i,model[2],nmax = 2;
318:   void                    *ctx;

322:   if (!ksp->pc) {KSPGetPC(ksp,&ksp->pc);}
323:   PCSetFromOptions(ksp->pc);

325:   if (!KSPRegisterAllCalled) {KSPRegisterAll(PETSC_NULL);}
326:   PetscOptionsBegin(((PetscObject)ksp)->comm,((PetscObject)ksp)->prefix,"Krylov Method (KSP) Options","KSP");
327:     PetscOptionsList("-ksp_type","Krylov method","KSPSetType",KSPList,(char*)(((PetscObject)ksp)->type_name?((PetscObject)ksp)->type_name:KSPGMRES),type,256,&flg);
328:     if (flg) {
329:       KSPSetType(ksp,type);
330:     }
331:     /*
332:       Set the type if it was never set.
333:     */
334:     if (!((PetscObject)ksp)->type_name) {
335:       KSPSetType(ksp,KSPGMRES);
336:     }

338:     PetscOptionsInt("-ksp_max_it","Maximum number of iterations","KSPSetTolerances",ksp->max_it,&ksp->max_it,PETSC_NULL);
339:     PetscOptionsReal("-ksp_rtol","Relative decrease in residual norm","KSPSetTolerances",ksp->rtol,&ksp->rtol,PETSC_NULL);
340:     PetscOptionsReal("-ksp_atol","Absolute value of residual norm","KSPSetTolerances",ksp->abstol,&ksp->abstol,PETSC_NULL);
341:     PetscOptionsReal("-ksp_divtol","Residual norm increase cause divergence","KSPSetTolerances",ksp->divtol,&ksp->divtol,PETSC_NULL);

343:     flag = PETSC_FALSE;
344:     PetscOptionsTruth("-ksp_converged_use_initial_residual_norm","Use initial residual residual norm for computing relative convergence","KSPDefaultConvergedSetUIRNorm",flag,&flag,PETSC_NULL);
345:     if (flag) {KSPDefaultConvergedSetUIRNorm(ksp);}
346:     flag = PETSC_FALSE;
347:     PetscOptionsTruth("-ksp_converged_use_min_initial_residual_norm","Use minimum of initial residual norm and b for computing relative convergence","KSPDefaultConvergedSetUMIRNorm",flag,&flag,PETSC_NULL);
348:     if (flag) {KSPDefaultConvergedSetUMIRNorm(ksp);}
349:     KSPGetInitialGuessNonzero(ksp,&flag);
350:     PetscOptionsTruth("-ksp_initial_guess_nonzero","Use the contents of the solution vector for initial guess","KSPSetInitialNonzero",flag,&flag,&flg);
351:     if (flg) {
352:       KSPSetInitialGuessNonzero(ksp,flag);
353:     }

355:     PetscOptionsTruth("-ksp_knoll","Use preconditioner applied to b for initial guess","KSPSetInitialGuessKnoll",ksp->guess_knoll,&ksp->guess_knoll,PETSC_NULL);
356:     PetscOptionsIntArray("-ksp_fischer_guess","Use Paul Fischer's algorihtm for initial guess","KSPSetUseFischerGuess",model,&nmax,&flag);
357:     if (flag) {
358:       if (nmax != 2) SETERRQ(PETSC_ERR_ARG_OUTOFRANGE,"Must pass in model,size as arguments");
359:       KSPSetUseFischerGuess(ksp,model[0],model[1]);
360:     }

362:     PetscOptionsEList("-ksp_convergence_test","Convergence test","KSPSetConvergenceTest",convtests,2,"default",&indx,&flg);
363:     if (flg) {
364:       switch (indx) {
365:       case 0:
366:         KSPDefaultConvergedCreate(&ctx);
367:         KSPSetConvergenceTest(ksp,KSPDefaultConverged,ctx,KSPDefaultConvergedDestroy);
368:         break;
369:       case 1: KSPSetConvergenceTest(ksp,KSPSkipConverged,PETSC_NULL,PETSC_NULL);    break;
370:       }
371:     }

373:     PetscOptionsEList("-ksp_norm_type","KSP Norm type","KSPSetNormType",KSPNormTypes,4,"preconditioned",&indx,&flg);
374:     if (flg) { KSPSetNormType(ksp,(KSPNormType)indx); }

376:     PetscOptionsInt("-ksp_check_norm_iteration","First iteration to compute residual norm","KSPSetCheckNormIteration",ksp->chknorm,&ksp->chknorm,PETSC_NULL);

378:     flag  = ksp->lagnorm;
379:     PetscOptionsTruth("-ksp_lag_norm","Lag the calculation of the residual norm","KSPSetLagNorm",flag,&flag,&flg);
380:     if (flg) {
381:       KSPSetLagNorm(ksp,flag);
382:     }

384:     KSPGetDiagonalScale(ksp,&flag);
385:     PetscOptionsTruth("-ksp_diagonal_scale","Diagonal scale matrix before building preconditioner","KSPSetDiagonalScale",flag,&flag,&flg);
386:     if (flg) {
387:       KSPSetDiagonalScale(ksp,flag);
388:     }
389:     KSPGetDiagonalScaleFix(ksp,&flag);
390:     PetscOptionsTruth("-ksp_diagonal_scale_fix","Fix diagonally scaled matrix after solve","KSPSetDiagonalScaleFix",flag,&flag,&flg);
391:     if (flg) {
392:       KSPSetDiagonalScaleFix(ksp,flag);
393:     }

395:     flg  = PETSC_FALSE;
396:     PetscOptionsTruth("-ksp_constant_null_space","Add constant null space to Krylov solver","KSPSetNullSpace",flg,&flg,PETSC_NULL);
397:     if (flg) {
398:       MatNullSpace nsp;

400:       MatNullSpaceCreate(((PetscObject)ksp)->comm,PETSC_TRUE,0,0,&nsp);
401:       KSPSetNullSpace(ksp,nsp);
402:       MatNullSpaceDestroy(nsp);
403:     }

405:     /* option is actually checked in KSPSetUp(), just here so goes into help message */
406:     if (ksp->nullsp) {
407:       PetscOptionsName("-ksp_test_null_space","Is provided null space correct","None",&flg);
408:     }

410:     /*
411:       Prints reason for convergence or divergence of each linear solve
412:     */
413:     flg = PETSC_FALSE;
414:     PetscOptionsTruth("-ksp_converged_reason","Print reason for converged or diverged","KSPSolve",flg,&flg,PETSC_NULL);
415:     if (flg) {
416:       ksp->printreason = PETSC_TRUE;
417:     }

419:     flg  = PETSC_FALSE;
420:     PetscOptionsTruth("-ksp_monitor_cancel","Remove any hardwired monitor routines","KSPMonitorCancel",flg,&flg,PETSC_NULL);
421:     /* -----------------------------------------------------------------------*/
422:     /*
423:       Cancels all monitors hardwired into code before call to KSPSetFromOptions()
424:     */
425:     if (flg) {
426:       KSPMonitorCancel(ksp);
427:     }
428:     /*
429:       Prints preconditioned residual norm at each iteration
430:     */
431:     PetscOptionsString("-ksp_monitor","Monitor preconditioned residual norm","KSPMonitorSet","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);
432:     if (flg) {
433:       PetscViewerASCIIMonitorCreate(((PetscObject)ksp)->comm,monfilename,((PetscObject)ksp)->tablevel,&monviewer);
434:       KSPMonitorSet(ksp,KSPMonitorDefault,monviewer,(PetscErrorCode (*)(void*))PetscViewerASCIIMonitorDestroy);
435:     }
436:     /*
437:       Prints preconditioned residual norm at each iteration
438:     */
439:     PetscOptionsString("-ksp_monitor_range","Monitor percent of residual entries more than 10 percent of max","KSPMonitorRange","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);
440:     if (flg) {
441:       PetscViewerASCIIMonitorCreate(((PetscObject)ksp)->comm,monfilename,((PetscObject)ksp)->tablevel,&monviewer);
442:       KSPMonitorSet(ksp,KSPMonitorRange,monviewer,(PetscErrorCode (*)(void*))PetscViewerASCIIMonitorDestroy);
443:     }
444:     /*
445:       Plots the vector solution 
446:     */
447:     flg  = PETSC_FALSE;
448:     PetscOptionsTruth("-ksp_monitor_solution","Monitor solution graphically","KSPMonitorSet",flg,&flg,PETSC_NULL);
449:     if (flg) {
450:       KSPMonitorSet(ksp,KSPMonitorSolution,PETSC_NULL,PETSC_NULL);
451:     }
452:     /*
453:       Prints preconditioned and true residual norm at each iteration
454:     */
455:     PetscOptionsString("-ksp_monitor_true_residual","Monitor true residual norm","KSPMonitorSet","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);
456:     if (flg) {
457:       PetscViewerASCIIMonitorCreate(((PetscObject)ksp)->comm,monfilename,((PetscObject)ksp)->tablevel,&monviewer);
458:       KSPMonitorSet(ksp,KSPMonitorTrueResidualNorm,monviewer,(PetscErrorCode (*)(void*))PetscViewerASCIIMonitorDestroy);
459:     }
460:     /*
461:       Prints extreme eigenvalue estimates at each iteration
462:     */
463:     PetscOptionsString("-ksp_monitor_singular_value","Monitor singular values","KSPMonitorSet","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);
464:     if (flg) {
465:       KSPSetComputeSingularValues(ksp,PETSC_TRUE);
466:       PetscViewerASCIIMonitorCreate(((PetscObject)ksp)->comm,monfilename,((PetscObject)ksp)->tablevel,&monviewer);
467:       KSPMonitorSet(ksp,KSPMonitorSingularValue,monviewer,(PetscErrorCode (*)(void*))PetscViewerASCIIMonitorDestroy);
468:     }
469:     /*
470:       Prints preconditioned residual norm with fewer digits
471:     */
472:     PetscOptionsString("-ksp_monitor_short","Monitor preconditioned residual norm with fewer digits","KSPMonitorSet","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);
473:     if (flg) {
474:       PetscViewerASCIIMonitorCreate(((PetscObject)ksp)->comm,monfilename,((PetscObject)ksp)->tablevel,&monviewer);
475:       KSPMonitorSet(ksp,KSPMonitorDefaultShort,monviewer,(PetscErrorCode (*)(void*))PetscViewerASCIIMonitorDestroy);
476:     }
477:     /*
478:       Graphically plots preconditioned residual norm
479:     */
480:     flg  = PETSC_FALSE;
481:     PetscOptionsTruth("-ksp_monitor_draw","Monitor graphically preconditioned residual norm","KSPMonitorSet",flg,&flg,PETSC_NULL);
482:     if (flg) {
483:       KSPMonitorSet(ksp,KSPMonitorLG,PETSC_NULL,PETSC_NULL);
484:     }
485:     /*
486:       Graphically plots preconditioned and true residual norm
487:     */
488:     flg  = PETSC_FALSE;
489:     PetscOptionsTruth("-ksp_monitor_draw_true_residual","Monitor graphically true residual norm","KSPMonitorSet",flg,&flg,PETSC_NULL);
490:     if (flg){
491:       KSPMonitorSet(ksp,KSPMonitorLGTrueResidualNorm,PETSC_NULL,PETSC_NULL);
492:     }
493:     /*
494:       Graphically plots preconditioned residual norm and range of residual element values
495:     */
496:     flg  = PETSC_FALSE;
497:     PetscOptionsTruth("-ksp_monitor_range_draw","Monitor graphically preconditioned residual norm","KSPMonitorSet",flg,&flg,PETSC_NULL);
498:     if (flg) {
499:       KSPMonitorSet(ksp,KSPMonitorLGRange,PETSC_NULL,PETSC_NULL);
500:     }

502:     /* -----------------------------------------------------------------------*/

504:     PetscOptionsTruthGroupBegin("-ksp_left_pc","Use left preconditioning","KSPSetPreconditionerSide",&flg);
505:     if (flg) { KSPSetPreconditionerSide(ksp,PC_LEFT); }
506:     PetscOptionsTruthGroup("-ksp_right_pc","Use right preconditioning","KSPSetPreconditionerSide",&flg);
507:     if (flg) { KSPSetPreconditionerSide(ksp,PC_RIGHT);}
508:     PetscOptionsTruthGroupEnd("-ksp_symmetric_pc","Use symmetric (factorized) preconditioning","KSPSetPreconditionerSide",&flg);
509:     if (flg) { KSPSetPreconditionerSide(ksp,PC_SYMMETRIC);}

511:     flg  = PETSC_FALSE;
512:     PetscOptionsTruth("-ksp_compute_singularvalues","Compute singular values of preconditioned operator","KSPSetComputeSingularValues",flg,&flg,PETSC_NULL);
513:     if (flg) { KSPSetComputeSingularValues(ksp,PETSC_TRUE); }
514:     flg  = PETSC_FALSE;
515:     PetscOptionsTruth("-ksp_compute_eigenvalues","Compute eigenvalues of preconditioned operator","KSPSetComputeSingularValues",flg,&flg,PETSC_NULL);
516:     if (flg) { KSPSetComputeSingularValues(ksp,PETSC_TRUE); }
517:     flg  = PETSC_FALSE;
518:     PetscOptionsTruth("-ksp_plot_eigenvalues","Scatter plot extreme eigenvalues","KSPSetComputeSingularValues",flg,&flg,PETSC_NULL);
519:     if (flg) { KSPSetComputeSingularValues(ksp,PETSC_TRUE); }

521:     for(i = 0; i < numberofsetfromoptions; i++) {
522:       (*othersetfromoptions[i])(ksp);
523:     }

525:     if (ksp->ops->setfromoptions) {
526:       (*ksp->ops->setfromoptions)(ksp);
527:     }
528:     /* actually check in setup this is just here so goes into help message */
529:     PetscOptionsName("-ksp_view","View linear solver parameters","KSPView",&flg);
530:   PetscOptionsEnd();
531:   return(0);
532: }