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: }