Actual source code: itcl.c
1: /*
2: Code for setting KSP options from the options database.
3: */
5: #include <petsc/private/kspimpl.h>
6: #include <petscdraw.h>
8: /*@
9: KSPSetOptionsPrefix - Sets the prefix used for searching for all
10: `KSP` options in the database.
12: Logically Collective
14: Input Parameters:
15: + ksp - the Krylov context
16: - prefix - the prefix string to prepend to all `KSP` option requests
18: Level: intermediate
20: Notes:
21: A hyphen (-) must NOT be given at the beginning of the prefix name.
22: The first character of all runtime options is AUTOMATICALLY the
23: hyphen.
25: For example, to distinguish between the runtime options for two
26: different `KSP` contexts, one could call
27: .vb
28: KSPSetOptionsPrefix(ksp1,"sys1_")
29: KSPSetOptionsPrefix(ksp2,"sys2_")
30: .ve
32: This would enable use of different options for each system, such as
33: .vb
34: -sys1_ksp_type gmres -sys1_ksp_rtol 1.e-3
35: -sys2_ksp_type bcgs -sys2_ksp_rtol 1.e-4
36: .ve
38: .seealso: [](ch_ksp), `KSP`, `KSPAppendOptionsPrefix()`, `KSPGetOptionsPrefix()`, `KSPSetFromOptions()`
39: @*/
40: PetscErrorCode KSPSetOptionsPrefix(KSP ksp, const char prefix[])
41: {
42: PetscBool ispcmpi;
44: PetscFunctionBegin;
46: if (!ksp->pc) PetscCall(KSPGetPC(ksp, &ksp->pc));
47: PetscCall(PetscObjectTypeCompare((PetscObject)ksp->pc, PCMPI, &ispcmpi));
48: if (ispcmpi) {
49: size_t len;
50: const char suffix[] = "mpi_linear_solver_server_";
51: char *newprefix;
53: PetscCall(PetscStrlen(prefix, &len));
54: PetscCall(PetscMalloc1(len + sizeof(suffix) + 1, &newprefix));
55: PetscCall(PetscStrncpy(newprefix, prefix, len + sizeof(suffix)));
56: PetscCall(PetscStrlcat(newprefix, suffix, len + sizeof(suffix)));
57: PetscCall(PCSetOptionsPrefix(ksp->pc, newprefix));
58: PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ksp, newprefix));
59: PetscCall(PetscFree(newprefix));
60: } else {
61: PetscCall(PCSetOptionsPrefix(ksp->pc, prefix));
62: PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ksp, prefix));
63: }
64: PetscFunctionReturn(PETSC_SUCCESS);
65: }
67: /*@
68: KSPAppendOptionsPrefix - Appends to the prefix used for searching for all
69: `KSP` options in the database.
71: Logically Collective
73: Input Parameters:
74: + ksp - the Krylov context
75: - prefix - the prefix string to prepend to all `KSP` option requests
77: Level: intermediate
79: Note:
80: A hyphen (-) must NOT be given at the beginning of the prefix name.
81: The first character of all runtime options is AUTOMATICALLY the hyphen.
83: .seealso: [](ch_ksp), `KSP`, `KSPSetOptionsPrefix()`, `KSPGetOptionsPrefix()`, `KSPSetFromOptions()`
84: @*/
85: PetscErrorCode KSPAppendOptionsPrefix(KSP ksp, const char prefix[])
86: {
87: PetscFunctionBegin;
89: if (!ksp->pc) PetscCall(KSPGetPC(ksp, &ksp->pc));
90: PetscCall(PCAppendOptionsPrefix(ksp->pc, prefix));
91: PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)ksp, prefix));
92: PetscFunctionReturn(PETSC_SUCCESS);
93: }
95: /*@
96: KSPSetUseFischerGuess - Use the Paul Fischer algorithm or its variants to compute initial guesses for a set of solves with related right-hand sides
98: Logically Collective
100: Input Parameters:
101: + ksp - the Krylov context
102: . model - use model 1, model 2, model 3, or any other number to turn it off
103: - size - size of subspace used to generate initial guess
105: Options Database Key:
106: . -ksp_fischer_guess <model,size> - uses the Fischer initial guess generator for repeated linear solves
108: Level: advanced
110: .seealso: [](ch_ksp), `KSP`, `KSPSetOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `KSPSetGuess()`, `KSPGetGuess()`, `KSPGuess`
111: @*/
112: PetscErrorCode KSPSetUseFischerGuess(KSP ksp, PetscInt model, PetscInt size)
113: {
114: KSPGuess guess;
116: PetscFunctionBegin;
120: PetscCall(KSPGetGuess(ksp, &guess));
121: PetscCall(KSPGuessSetType(guess, KSPGUESSFISCHER));
122: PetscCall(KSPGuessFischerSetModel(guess, model, size));
123: PetscFunctionReturn(PETSC_SUCCESS);
124: }
126: /*@
127: KSPSetGuess - Set the initial guess object
129: Logically Collective
131: Input Parameters:
132: + ksp - the Krylov context
133: - guess - the object created with `KSPGuessCreate()`
135: Level: advanced
137: Notes:
138: this allows a single `KSP` to be used with several different initial guess generators (likely for different linear
139: solvers, see `KSPSetPC()`).
141: This increases the reference count of the guess object, you must destroy the object with `KSPGuessDestroy()`
142: before the end of the program.
144: .seealso: [](ch_ksp), `KSP`, `KSPGuess`, `KSPSetOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `KSPSetUseFischerGuess()`, `KSPGetGuess()`
145: @*/
146: PetscErrorCode KSPSetGuess(KSP ksp, KSPGuess guess)
147: {
148: PetscFunctionBegin;
151: PetscCall(PetscObjectReference((PetscObject)guess));
152: PetscCall(KSPGuessDestroy(&ksp->guess));
153: ksp->guess = guess;
154: ksp->guess->ksp = ksp;
155: PetscFunctionReturn(PETSC_SUCCESS);
156: }
158: /*@
159: KSPGetGuess - Gets the initial guess generator for the `KSP`.
161: Not Collective
163: Input Parameter:
164: . ksp - the Krylov context
166: Output Parameter:
167: . guess - the object
169: Level: developer
171: .seealso: [](ch_ksp), `KSPGuess`, `KSP`, `KSPSetOptionsPrefix()`, `KSPAppendOptionsPrefix()`, `KSPSetUseFischerGuess()`, `KSPSetGuess()`
172: @*/
173: PetscErrorCode KSPGetGuess(KSP ksp, KSPGuess *guess)
174: {
175: PetscFunctionBegin;
177: PetscAssertPointer(guess, 2);
178: if (!ksp->guess) {
179: const char *prefix;
181: PetscCall(KSPGuessCreate(PetscObjectComm((PetscObject)ksp), &ksp->guess));
182: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ksp, &prefix));
183: if (prefix) PetscCall(PetscObjectSetOptionsPrefix((PetscObject)ksp->guess, prefix));
184: ksp->guess->ksp = ksp;
185: }
186: *guess = ksp->guess;
187: PetscFunctionReturn(PETSC_SUCCESS);
188: }
190: /*@
191: KSPGetOptionsPrefix - Gets the prefix used for searching for all
192: `KSP` options in the database.
194: Not Collective
196: Input Parameter:
197: . ksp - the Krylov context
199: Output Parameter:
200: . prefix - pointer to the prefix string used is returned
202: Level: advanced
204: Fortran Note:
205: Pass in a string 'prefix' of
206: sufficient length to hold the prefix.
208: .seealso: [](ch_ksp), `KSP`, `KSPSetFromOptions()`, `KSPSetOptionsPrefix()`, `KSPAppendOptionsPrefix()`
209: @*/
210: PetscErrorCode KSPGetOptionsPrefix(KSP ksp, const char *prefix[])
211: {
212: PetscFunctionBegin;
214: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ksp, prefix));
215: PetscFunctionReturn(PETSC_SUCCESS);
216: }
218: static PetscErrorCode PetscViewerAndFormatCreate_Internal(PetscViewer viewer, PetscViewerFormat format, void *ctx, PetscViewerAndFormat **vf)
219: {
220: PetscFunctionBegin;
221: PetscCall(PetscViewerAndFormatCreate(viewer, format, vf));
222: (*vf)->data = ctx;
223: PetscFunctionReturn(PETSC_SUCCESS);
224: }
226: /*@C
227: KSPMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user in the options database
229: Collective
231: Input Parameters:
232: + ksp - `KSP` object you wish to monitor
233: . opt - the command line option for this monitor
234: . name - the monitor type one is seeking
235: - ctx - An optional user context for the monitor, or `NULL`
237: Level: developer
239: .seealso: [](ch_ksp), `KSPMonitorRegister()`, `KSPMonitorSet()`, `PetscOptionsCreateViewer()`, `PetscOptionsGetReal()`, `PetscOptionsHasName()`, `PetscOptionsGetString()`,
240: `PetscOptionsGetIntArray()`, `PetscOptionsGetRealArray()`, `PetscOptionsBool()`
241: `PetscOptionsInt()`, `PetscOptionsString()`, `PetscOptionsReal()`,
242: `PetscOptionsName()`, `PetscOptionsBegin()`, `PetscOptionsEnd()`, `PetscOptionsHeadBegin()`,
243: `PetscOptionsStringArray()`, `PetscOptionsRealArray()`, `PetscOptionsScalar()`,
244: `PetscOptionsBoolGroupBegin()`, `PetscOptionsBoolGroup()`, `PetscOptionsBoolGroupEnd()`,
245: `PetscOptionsFList()`, `PetscOptionsEList()`
246: @*/
247: PetscErrorCode KSPMonitorSetFromOptions(KSP ksp, const char opt[], const char name[], void *ctx)
248: {
249: PetscErrorCode (*mfunc)(KSP, PetscInt, PetscReal, void *);
250: PetscErrorCode (*cfunc)(PetscViewer, PetscViewerFormat, void *, PetscViewerAndFormat **);
251: PetscErrorCode (*dfunc)(PetscViewerAndFormat **);
252: PetscViewerAndFormat *vf;
253: PetscViewer viewer;
254: PetscViewerFormat format;
255: PetscViewerType vtype;
256: char key[PETSC_MAX_PATH_LEN];
257: PetscBool all, flg;
258: const char *prefix = NULL;
260: PetscFunctionBegin;
261: PetscCall(PetscStrcmp(opt, "-all_ksp_monitor", &all));
262: if (!all) PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ksp, &prefix));
263: PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)ksp), ((PetscObject)ksp)->options, prefix, opt, &viewer, &format, &flg));
264: if (!flg) PetscFunctionReturn(PETSC_SUCCESS);
266: PetscCall(PetscViewerGetType(viewer, &vtype));
267: PetscCall(KSPMonitorMakeKey_Internal(name, vtype, format, key));
268: PetscCall(PetscFunctionListFind(KSPMonitorList, key, &mfunc));
269: PetscCall(PetscFunctionListFind(KSPMonitorCreateList, key, &cfunc));
270: PetscCall(PetscFunctionListFind(KSPMonitorDestroyList, key, &dfunc));
271: if (!cfunc) cfunc = PetscViewerAndFormatCreate_Internal;
272: if (!dfunc) dfunc = PetscViewerAndFormatDestroy;
274: PetscCall((*cfunc)(viewer, format, ctx, &vf));
275: PetscCall(PetscViewerDestroy(&viewer));
276: PetscCall(KSPMonitorSet(ksp, mfunc, vf, (PetscErrorCode (*)(void **))dfunc));
277: PetscFunctionReturn(PETSC_SUCCESS);
278: }
280: PETSC_INTERN PetscErrorCode KSPCheckPCMPI(KSP);
282: /*@
283: KSPSetFromOptions - Sets `KSP` options from the options database.
284: This routine must be called before `KSPSetUp()` if the user is to be
285: allowed to set the Krylov type.
287: Collective
289: Input Parameter:
290: . ksp - the Krylov space context
292: Options Database Keys:
293: + -ksp_rtol rtol - relative tolerance used in default determination of convergence, i.e.
294: if residual norm decreases by this factor than convergence is declared
295: . -ksp_atol abstol - absolute tolerance used in default convergence test, i.e. if residual
296: norm is less than this then convergence is declared
297: . -ksp_divtol tol - if residual norm increases by this factor than divergence is declared
298: . -ksp_max_it - maximum number of linear iterations
299: . -ksp_min_it - minimum number of linear iterations to use, defaults to zero
301: . -ksp_converged_use_initial_residual_norm - see `KSPConvergedDefaultSetUIRNorm()`
302: . -ksp_converged_use_min_initial_residual_norm - see `KSPConvergedDefaultSetUMIRNorm()`
303: . -ksp_converged_maxits - see `KSPConvergedDefaultSetConvergedMaxits()`
304: . -ksp_norm_type <none,preconditioned,unpreconditioned,natural> - see `KSPSetNormType()`
305: . -ksp_check_norm_iteration it - do not compute residual norm until iteration number it (does compute at 0th iteration)
306: works only for `KSPBCGS`, `KSPIBCGS`, and `KSPCG`
307: . -ksp_lag_norm - compute the norm of the residual for the ith iteration on the i+1 iteration;
308: this means that one can use the norm of the residual for convergence test WITHOUT
309: an extra `MPI_Allreduce()` limiting global synchronizations.
310: This will require 1 more iteration of the solver than usual.
311: . -ksp_guess_type - Type of initial guess generator for repeated linear solves
312: . -ksp_fischer_guess <model,size> - uses the Fischer initial guess generator for repeated linear solves
313: . -ksp_constant_null_space - assume the operator (matrix) has the constant vector in its null space
314: . -ksp_test_null_space - tests the null space set with `MatSetNullSpace()` to see if it truly is a null space
315: . -ksp_knoll - compute initial guess by applying the preconditioner to the right-hand side
316: . -ksp_monitor_cancel - cancel all previous convergene monitor routines set
317: . -ksp_monitor - print residual norm at each iteration
318: . -ksp_monitor draw::draw_lg - plot residual norm at each iteration
319: . -ksp_monitor_true_residual - print true residual norm at each iteration
320: . -all_ksp_monitor <optional filename> - print residual norm at each iteration for ALL KSP solves, regardless of their prefix. This is
321: useful for `PCFIELDSPLIT`, `PCMG`, etc that have inner solvers and
322: you wish to track the convergence of all the solvers
323: . -ksp_monitor_solution [ascii binary or draw][:filename][:format option] - plot solution at each iteration
324: . -ksp_monitor_singular_value - monitor extreme singular values at each iteration
325: . -ksp_converged_reason - view the convergence state at the end of the solve
326: . -ksp_use_explicittranspose - transpose the system explicitly in KSPSolveTranspose
327: . -ksp_error_if_not_converged - stop the program as soon as an error is detected in a `KSPSolve()`, `KSP_DIVERGED_ITS`
328: is not treated as an error on inner solves
329: - -ksp_converged_rate - view the convergence rate at the end of the solve
331: Level: beginner
333: Note:
334: To see all options, run your program with the `-help` option or consult [](ch_ksp)
336: .seealso: [](ch_ksp), `KSP`, `KSPSetOptionsPrefix()`, `KSPResetFromOptions()`, `KSPSetUseFischerGuess()`
337: @*/
338: PetscErrorCode KSPSetFromOptions(KSP ksp)
339: {
340: const char *convtests[] = {"default", "skip", "lsqr"}, *prefix;
341: char type[256], guesstype[256], monfilename[PETSC_MAX_PATH_LEN];
342: PetscBool flg, flag, reuse, set;
343: PetscInt indx, model[2] = {0, 0}, nmax, max_it;
344: KSPNormType normtype;
345: PCSide pcside;
346: void *ctx;
347: MPI_Comm comm;
348: PetscReal rtol, abstol, divtol;
350: PetscFunctionBegin;
353: PetscCall(PetscObjectGetComm((PetscObject)ksp, &comm));
354: if (!ksp->pc) PetscCall(KSPGetPC(ksp, &ksp->pc));
355: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)ksp, &prefix));
356: if (!ksp->skippcsetfromoptions) PetscCall(PCSetFromOptions(ksp->pc));
358: PetscCall(KSPRegisterAll());
359: PetscObjectOptionsBegin((PetscObject)ksp);
360: PetscCall(PetscOptionsFList("-ksp_type", "Krylov method", "KSPSetType", KSPList, (char *)(((PetscObject)ksp)->type_name ? ((PetscObject)ksp)->type_name : KSPGMRES), type, 256, &flg));
361: if (flg) PetscCall(KSPSetType(ksp, type));
362: /*
363: Set the type if it was never set.
364: */
365: if (!((PetscObject)ksp)->type_name) PetscCall(KSPSetType(ksp, KSPGMRES));
367: PetscCall(KSPResetViewers(ksp));
369: /* Cancels all monitors hardwired into code before call to KSPSetFromOptions() */
370: PetscCall(PetscOptionsBool("-ksp_monitor_cancel", "Remove any hardwired monitor routines", "KSPMonitorCancel", PETSC_FALSE, &flg, &set));
371: if (set && flg) PetscCall(KSPMonitorCancel(ksp));
372: PetscCall(KSPMonitorSetFromOptions(ksp, "-ksp_monitor", "preconditioned_residual", NULL));
373: PetscCall(KSPMonitorSetFromOptions(ksp, "-ksp_monitor_short", "preconditioned_residual_short", NULL));
374: PetscCall(KSPMonitorSetFromOptions(ksp, "-all_ksp_monitor", "preconditioned_residual", NULL));
375: PetscCall(KSPMonitorSetFromOptions(ksp, "-ksp_monitor_range", "preconditioned_residual_range", NULL));
376: PetscCall(KSPMonitorSetFromOptions(ksp, "-ksp_monitor_true_residual", "true_residual", NULL));
377: PetscCall(KSPMonitorSetFromOptions(ksp, "-ksp_monitor_max", "true_residual_max", NULL));
378: PetscCall(KSPMonitorSetFromOptions(ksp, "-ksp_monitor_solution", "solution", NULL));
379: PetscCall(KSPMonitorSetFromOptions(ksp, "-ksp_monitor_singular_value", "singular_value", ksp));
380: PetscCall(KSPMonitorSetFromOptions(ksp, "-ksp_monitor_error", "error", ksp));
381: PetscCall(PetscOptionsBool("-ksp_monitor_pause_final", "Pauses all draw monitors at the final iterate", "KSPMonitorPauseFinal_Internal", PETSC_FALSE, &ksp->pauseFinal, NULL));
382: PetscCall(PetscOptionsBool("-ksp_initial_guess_nonzero", "Use the contents of the solution vector for initial guess", "KSPSetInitialNonzero", ksp->guess_zero ? PETSC_FALSE : PETSC_TRUE, &flag, &flg));
383: if (flg) PetscCall(KSPSetInitialGuessNonzero(ksp, flag));
385: PetscCall(PetscObjectTypeCompare((PetscObject)ksp, KSPPREONLY, &flg));
386: if (flg) {
387: PetscCall(KSPGetReusePreconditioner(ksp, &reuse));
388: PetscCall(PetscOptionsBool("-ksp_reuse_preconditioner", "Use initial preconditioner and don't ever compute a new one", "KSPReusePreconditioner", reuse, &reuse, NULL));
389: PetscCall(KSPSetReusePreconditioner(ksp, reuse));
390: PetscCall(PetscOptionsBool("-ksp_error_if_not_converged", "Generate error if solver does not converge", "KSPSetErrorIfNotConverged", ksp->errorifnotconverged, &ksp->errorifnotconverged, NULL));
391: PetscCall(PetscOptionsCreateViewer(comm, ((PetscObject)ksp)->options, prefix, "-ksp_view", &ksp->viewer, &ksp->format, &ksp->view));
392: PetscCall(PetscViewerDestroy(&ksp->convergedreasonviewer));
393: PetscCall(PetscOptionsCreateViewer(comm, ((PetscObject)ksp)->options, ((PetscObject)ksp)->prefix, "-ksp_converged_reason", &ksp->convergedreasonviewer, &ksp->convergedreasonformat, NULL));
394: flg = PETSC_FALSE;
395: PetscCall(PetscOptionsBool("-ksp_converged_reason_view_cancel", "Cancel all the converged reason view functions set using KSPConvergedReasonViewSet", "KSPConvergedReasonViewCancel", PETSC_FALSE, &flg, &set));
396: if (set && flg) PetscCall(KSPConvergedReasonViewCancel(ksp));
397: PetscCall(PetscOptionsCreateViewer(comm, ((PetscObject)ksp)->options, prefix, "-ksp_view_mat", &ksp->viewerMat, &ksp->formatMat, &ksp->viewMat));
398: PetscCall(PetscOptionsCreateViewer(comm, ((PetscObject)ksp)->options, prefix, "-ksp_view_pmat", &ksp->viewerPMat, &ksp->formatPMat, &ksp->viewPMat));
399: PetscCall(PetscOptionsCreateViewer(comm, ((PetscObject)ksp)->options, prefix, "-ksp_view_rhs", &ksp->viewerRhs, &ksp->formatRhs, &ksp->viewRhs));
400: PetscCall(PetscOptionsCreateViewer(comm, ((PetscObject)ksp)->options, prefix, "-ksp_view_solution", &ksp->viewerSol, &ksp->formatSol, &ksp->viewSol));
401: PetscCall(PetscOptionsCreateViewer(comm, ((PetscObject)ksp)->options, prefix, "-ksp_view_mat_explicit", &ksp->viewerMatExp, &ksp->formatMatExp, &ksp->viewMatExp));
402: PetscCall(PetscOptionsCreateViewer(comm, ((PetscObject)ksp)->options, prefix, "-ksp_view_final_residual", &ksp->viewerFinalRes, &ksp->formatFinalRes, &ksp->viewFinalRes));
403: PetscCall(PetscOptionsCreateViewer(comm, ((PetscObject)ksp)->options, prefix, "-ksp_view_preconditioned_operator_explicit", &ksp->viewerPOpExp, &ksp->formatPOpExp, &ksp->viewPOpExp));
404: PetscCall(PetscOptionsCreateViewer(comm, ((PetscObject)ksp)->options, prefix, "-ksp_view_diagonal_scale", &ksp->viewerDScale, &ksp->formatDScale, &ksp->viewDScale));
406: PetscCall(KSPGetDiagonalScale(ksp, &flag));
407: PetscCall(PetscOptionsBool("-ksp_diagonal_scale", "Diagonal scale matrix before building preconditioner", "KSPSetDiagonalScale", flag, &flag, &flg));
408: if (flg) PetscCall(KSPSetDiagonalScale(ksp, flag));
409: PetscCall(KSPGetDiagonalScaleFix(ksp, &flag));
410: PetscCall(PetscOptionsBool("-ksp_diagonal_scale_fix", "Fix diagonally scaled matrix after solve", "KSPSetDiagonalScaleFix", flag, &flag, &flg));
411: if (flg) PetscCall(KSPSetDiagonalScaleFix(ksp, flag));
412: nmax = ksp->nmax;
413: PetscCall(PetscOptionsDeprecated("-ksp_matsolve_block_size", "-ksp_matsolve_batch_size", "3.15", NULL));
414: PetscCall(PetscOptionsInt("-ksp_matsolve_batch_size", "Maximum number of columns treated simultaneously", "KSPSetMatSolveBatchSize", nmax, &nmax, &flg));
415: if (flg) PetscCall(KSPSetMatSolveBatchSize(ksp, nmax));
416: goto skipoptions;
417: }
419: rtol = ksp->rtol;
420: abstol = ksp->abstol;
421: divtol = ksp->divtol;
422: max_it = ksp->max_it;
423: PetscCall(PetscOptionsReal("-ksp_rtol", "Relative decrease in residual norm", "KSPSetTolerances", ksp->rtol, &rtol, NULL));
424: PetscCall(PetscOptionsReal("-ksp_atol", "Absolute value of residual norm", "KSPSetTolerances", ksp->abstol, &abstol, NULL));
425: PetscCall(PetscOptionsReal("-ksp_divtol", "Residual norm increase cause divergence", "KSPSetTolerances", ksp->divtol, &divtol, NULL));
426: PetscCall(PetscOptionsInt("-ksp_max_it", "Maximum number of iterations", "KSPSetTolerances", ksp->max_it, &max_it, &flg));
427: PetscCall(KSPSetTolerances(ksp, rtol, abstol, divtol, max_it));
428: PetscCall(PetscOptionsRangeInt("-ksp_min_it", "Minimum number of iterations", "KSPSetMinimumIterations", ksp->min_it, &ksp->min_it, NULL, 0, ksp->max_it));
430: PetscCall(PetscOptionsBool("-ksp_converged_use_initial_residual_norm", "Use initial residual norm for computing relative convergence", "KSPConvergedDefaultSetUIRNorm", PETSC_FALSE, &flag, &set));
431: if (set && flag) PetscCall(KSPConvergedDefaultSetUIRNorm(ksp));
432: PetscCall(PetscOptionsBool("-ksp_converged_use_min_initial_residual_norm", "Use minimum of initial residual norm and b for computing relative convergence", "KSPConvergedDefaultSetUMIRNorm", PETSC_FALSE, &flag, &set));
433: if (set && flag) PetscCall(KSPConvergedDefaultSetUMIRNorm(ksp));
434: PetscCall(PetscOptionsBool("-ksp_converged_maxits", "Declare convergence if the maximum number of iterations is reached", "KSPConvergedDefaultSetConvergedMaxits", PETSC_FALSE, &flag, &set));
435: if (set) PetscCall(KSPConvergedDefaultSetConvergedMaxits(ksp, flag));
436: PetscCall(KSPGetConvergedNegativeCurvature(ksp, &flag));
437: PetscCall(PetscOptionsBool("-ksp_converged_neg_curve", "Declare convergence if negative curvature is detected", "KSPConvergedNegativeCurvature", flag, &flag, &set));
438: if (set) PetscCall(KSPSetConvergedNegativeCurvature(ksp, flag));
439: PetscCall(KSPGetReusePreconditioner(ksp, &reuse));
440: PetscCall(PetscOptionsBool("-ksp_reuse_preconditioner", "Use initial preconditioner and don't ever compute a new one", "KSPReusePreconditioner", reuse, &reuse, NULL));
441: PetscCall(KSPSetReusePreconditioner(ksp, reuse));
443: PetscCall(PetscOptionsBool("-ksp_knoll", "Use preconditioner applied to b for initial guess", "KSPSetInitialGuessKnoll", ksp->guess_knoll, &ksp->guess_knoll, NULL));
444: PetscCall(PetscOptionsBool("-ksp_error_if_not_converged", "Generate error if solver does not converge", "KSPSetErrorIfNotConverged", ksp->errorifnotconverged, &ksp->errorifnotconverged, NULL));
445: PetscCall(PetscOptionsFList("-ksp_guess_type", "Initial guess in Krylov method", NULL, KSPGuessList, NULL, guesstype, 256, &flg));
446: if (flg) {
447: PetscCall(KSPGetGuess(ksp, &ksp->guess));
448: PetscCall(KSPGuessSetType(ksp->guess, guesstype));
449: PetscCall(KSPGuessSetFromOptions(ksp->guess));
450: } else { /* old option for KSP */
451: nmax = 2;
452: PetscCall(PetscOptionsIntArray("-ksp_fischer_guess", "Use Paul Fischer's algorithm or its variants for initial guess", "KSPSetUseFischerGuess", model, &nmax, &flag));
453: if (flag) {
454: PetscCheck(nmax == 2, comm, PETSC_ERR_ARG_OUTOFRANGE, "Must pass in model,size as arguments");
455: PetscCall(KSPSetUseFischerGuess(ksp, model[0], model[1]));
456: }
457: }
459: PetscCall(PetscOptionsEList("-ksp_convergence_test", "Convergence test", "KSPSetConvergenceTest", convtests, 3, "default", &indx, &flg));
460: if (flg) {
461: switch (indx) {
462: case 0:
463: PetscCall(KSPConvergedDefaultCreate(&ctx));
464: PetscCall(KSPSetConvergenceTest(ksp, KSPConvergedDefault, ctx, KSPConvergedDefaultDestroy));
465: break;
466: case 1:
467: PetscCall(KSPSetConvergenceTest(ksp, KSPConvergedSkip, NULL, NULL));
468: break;
469: case 2:
470: PetscCall(KSPConvergedDefaultCreate(&ctx));
471: PetscCall(KSPSetConvergenceTest(ksp, KSPLSQRConvergedDefault, ctx, KSPConvergedDefaultDestroy));
472: break;
473: }
474: }
476: PetscCall(KSPSetUpNorms_Private(ksp, PETSC_FALSE, &normtype, NULL));
477: PetscCall(PetscOptionsEnum("-ksp_norm_type", "KSP Norm type", "KSPSetNormType", KSPNormTypes, (PetscEnum)normtype, (PetscEnum *)&normtype, &flg));
478: if (flg) PetscCall(KSPSetNormType(ksp, normtype));
480: PetscCall(PetscOptionsInt("-ksp_check_norm_iteration", "First iteration to compute residual norm", "KSPSetCheckNormIteration", ksp->chknorm, &ksp->chknorm, NULL));
482: PetscCall(PetscOptionsBool("-ksp_lag_norm", "Lag the calculation of the residual norm", "KSPSetLagNorm", ksp->lagnorm, &flag, &flg));
483: if (flg) PetscCall(KSPSetLagNorm(ksp, flag));
485: PetscCall(KSPGetDiagonalScale(ksp, &flag));
486: PetscCall(PetscOptionsBool("-ksp_diagonal_scale", "Diagonal scale matrix before building preconditioner", "KSPSetDiagonalScale", flag, &flag, &flg));
487: if (flg) PetscCall(KSPSetDiagonalScale(ksp, flag));
488: PetscCall(KSPGetDiagonalScaleFix(ksp, &flag));
489: PetscCall(PetscOptionsBool("-ksp_diagonal_scale_fix", "Fix diagonally scaled matrix after solve", "KSPSetDiagonalScaleFix", flag, &flag, &flg));
490: if (flg) PetscCall(KSPSetDiagonalScaleFix(ksp, flag));
492: PetscCall(PetscOptionsBool("-ksp_constant_null_space", "Add constant null space to Krylov solver matrix", "MatSetNullSpace", PETSC_FALSE, &flg, &set));
493: if (set && flg) {
494: MatNullSpace nsp;
495: Mat Amat = NULL;
497: PetscCall(MatNullSpaceCreate(comm, PETSC_TRUE, 0, NULL, &nsp));
498: if (ksp->pc) PetscCall(PCGetOperators(ksp->pc, &Amat, NULL));
499: PetscCheck(Amat, comm, PETSC_ERR_ARG_WRONGSTATE, "Cannot set nullspace, matrix has not yet been provided");
500: PetscCall(MatSetNullSpace(Amat, nsp));
501: PetscCall(MatNullSpaceDestroy(&nsp));
502: }
504: flg = PETSC_FALSE;
505: if (ksp->pc) {
506: PetscCall(PetscObjectTypeCompare((PetscObject)ksp->pc, PCKSP, &flg));
507: if (!flg) PetscCall(PetscObjectTypeCompare((PetscObject)ksp->pc, PCBJACOBI, &flg));
508: if (!flg) PetscCall(PetscObjectTypeCompare((PetscObject)ksp->pc, PCDEFLATION, &flg));
509: }
511: if (flg) {
512: /* Using dynamic tolerance in preconditioner */
513: PetscCall(PetscOptionsString("-sub_ksp_dynamic_tolerance", "Use dynamic tolerance for inner PC", "KSPMonitorDynamicTolerance", "stdout", monfilename, sizeof(monfilename), &flg));
514: if (flg) {
515: void *scale;
516: PetscReal coeff = 1.0;
518: PetscCall(KSPMonitorDynamicToleranceCreate(&scale));
519: PetscCall(PetscOptionsReal("-sub_ksp_dynamic_tolerance", "Coefficient of dynamic tolerance for inner PC", "KSPMonitorDynamicTolerance", coeff, &coeff, &flg));
520: if (flg) PetscCall(KSPMonitorDynamicToleranceSetCoefficient(scale, coeff));
521: PetscCall(KSPMonitorSet(ksp, KSPMonitorDynamicTolerance, scale, KSPMonitorDynamicToleranceDestroy));
522: }
523: }
525: /*
526: Calls Python function
527: */
528: PetscCall(PetscOptionsString("-ksp_monitor_python", "Use Python function", "KSPMonitorSet", NULL, monfilename, sizeof(monfilename), &flg));
529: if (flg) PetscCall(PetscPythonMonitorSet((PetscObject)ksp, monfilename));
530: /*
531: Graphically plots preconditioned residual norm and range of residual element values
532: */
533: PetscCall(PetscOptionsBool("-ksp_monitor_lg_range", "Monitor graphically range of preconditioned residual norm", "KSPMonitorSet", PETSC_FALSE, &flg, &set));
534: if (set && flg) {
535: PetscViewer ctx;
537: PetscCall(PetscViewerDrawOpen(comm, NULL, NULL, PETSC_DECIDE, PETSC_DECIDE, 400, 300, &ctx));
538: PetscCall(KSPMonitorSet(ksp, KSPMonitorLGRange, ctx, (PetscErrorCode (*)(void **))PetscViewerDestroy));
539: }
540: /* TODO Do these show up in help? */
541: PetscCall(PetscOptionsHasName(((PetscObject)ksp)->options, prefix, "-ksp_converged_rate", &flg));
542: if (flg) {
543: const char *RateTypes[] = {"default", "residual", "error", "PetscRateType", "RATE_", NULL};
544: PetscEnum rtype = (PetscEnum)1;
546: PetscCall(PetscOptionsGetEnum(((PetscObject)ksp)->options, prefix, "-ksp_converged_rate_type", RateTypes, &rtype, &flg));
547: if (rtype == (PetscEnum)0 || rtype == (PetscEnum)1) PetscCall(KSPSetResidualHistory(ksp, NULL, PETSC_DETERMINE, PETSC_TRUE));
548: if (rtype == (PetscEnum)0 || rtype == (PetscEnum)2) PetscCall(KSPSetErrorHistory(ksp, NULL, PETSC_DETERMINE, PETSC_TRUE));
549: }
550: PetscCall(PetscOptionsCreateViewer(comm, ((PetscObject)ksp)->options, prefix, "-ksp_view", &ksp->viewer, &ksp->format, &ksp->view));
551: PetscCall(PetscOptionsCreateViewer(comm, ((PetscObject)ksp)->options, prefix, "-ksp_view_pre", &ksp->viewerPre, &ksp->formatPre, &ksp->viewPre));
553: PetscCall(PetscViewerDestroy(&ksp->convergedreasonviewer));
554: PetscCall(PetscOptionsCreateViewer(comm, ((PetscObject)ksp)->options, ((PetscObject)ksp)->prefix, "-ksp_converged_reason", &ksp->convergedreasonviewer, &ksp->convergedreasonformat, NULL));
555: flg = PETSC_FALSE;
556: PetscCall(PetscOptionsBool("-ksp_converged_reason_view_cancel", "Cancel all the converged reason view functions set using KSPConvergedReasonViewSet", "KSPConvergedReasonViewCancel", PETSC_FALSE, &flg, &set));
557: if (set && flg) PetscCall(KSPConvergedReasonViewCancel(ksp));
558: PetscCall(PetscOptionsCreateViewer(comm, ((PetscObject)ksp)->options, prefix, "-ksp_converged_rate", &ksp->viewerRate, &ksp->formatRate, &ksp->viewRate));
559: PetscCall(PetscOptionsCreateViewer(comm, ((PetscObject)ksp)->options, prefix, "-ksp_view_mat", &ksp->viewerMat, &ksp->formatMat, &ksp->viewMat));
560: PetscCall(PetscOptionsCreateViewer(comm, ((PetscObject)ksp)->options, prefix, "-ksp_view_pmat", &ksp->viewerPMat, &ksp->formatPMat, &ksp->viewPMat));
561: PetscCall(PetscOptionsCreateViewer(comm, ((PetscObject)ksp)->options, prefix, "-ksp_view_rhs", &ksp->viewerRhs, &ksp->formatRhs, &ksp->viewRhs));
562: PetscCall(PetscOptionsCreateViewer(comm, ((PetscObject)ksp)->options, prefix, "-ksp_view_solution", &ksp->viewerSol, &ksp->formatSol, &ksp->viewSol));
563: PetscCall(PetscOptionsCreateViewer(comm, ((PetscObject)ksp)->options, prefix, "-ksp_view_mat_explicit", &ksp->viewerMatExp, &ksp->formatMatExp, &ksp->viewMatExp));
564: PetscCall(PetscOptionsDeprecated("-ksp_compute_eigenvalues", "-ksp_view_eigenvalues", "3.9", NULL));
565: PetscCall(PetscOptionsCreateViewer(comm, ((PetscObject)ksp)->options, prefix, "-ksp_view_eigenvalues", &ksp->viewerEV, &ksp->formatEV, &ksp->viewEV));
566: PetscCall(PetscOptionsDeprecated("-ksp_compute_singularvalues", "-ksp_view_singularvalues", "3.9", NULL));
567: PetscCall(PetscOptionsCreateViewer(comm, ((PetscObject)ksp)->options, prefix, "-ksp_view_singularvalues", &ksp->viewerSV, &ksp->formatSV, &ksp->viewSV));
568: PetscCall(PetscOptionsDeprecated("-ksp_compute_eigenvalues_explicitly", "-ksp_view_eigenvalues_explicit", "3.9", NULL));
569: PetscCall(PetscOptionsCreateViewer(comm, ((PetscObject)ksp)->options, prefix, "-ksp_view_eigenvalues_explicit", &ksp->viewerEVExp, &ksp->formatEVExp, &ksp->viewEVExp));
570: PetscCall(PetscOptionsDeprecated("-ksp_final_residual", "-ksp_view_final_residual", "3.9", NULL));
571: PetscCall(PetscOptionsCreateViewer(comm, ((PetscObject)ksp)->options, prefix, "-ksp_view_final_residual", &ksp->viewerFinalRes, &ksp->formatFinalRes, &ksp->viewFinalRes));
572: PetscCall(PetscOptionsCreateViewer(comm, ((PetscObject)ksp)->options, prefix, "-ksp_view_preconditioned_operator_explicit", &ksp->viewerPOpExp, &ksp->formatPOpExp, &ksp->viewPOpExp));
573: PetscCall(PetscOptionsCreateViewer(comm, ((PetscObject)ksp)->options, prefix, "-ksp_view_diagonal_scale", &ksp->viewerDScale, &ksp->formatDScale, &ksp->viewDScale));
575: /* Deprecated options */
576: if (!ksp->viewEV) {
577: /* Cannot remove the what otherwise would be redundant call to PetscOptionsName("-ksp_plot_eigenvalues",...) below because the argument handling is different */
578: PetscCall(PetscOptionsDeprecated("-ksp_plot_eigenvalues", NULL, "3.9", "Use -ksp_view_eigenvalues draw"));
579: PetscCall(PetscOptionsName("-ksp_plot_eigenvalues", "[deprecated since PETSc 3.9; use -ksp_view_eigenvalues draw]", "KSPView", &ksp->viewEV));
580: if (ksp->viewEV) {
581: ksp->formatEV = PETSC_VIEWER_DEFAULT;
582: ksp->viewerEV = PETSC_VIEWER_DRAW_(comm);
583: PetscCall(PetscObjectReference((PetscObject)ksp->viewerEV));
584: }
585: }
586: if (!ksp->viewEV) {
587: PetscCall(PetscOptionsDeprecated("-ksp_plot_eigenvalues_explicitly", NULL, "3.9", "Use -ksp_view_eigenvalues_explicit draw"));
588: /* Cannot remove the what otherwise would be redundant call to PetscOptionsName("-ksp_plot_eigencontours",...) below because the argument handling is different */
589: PetscCall(PetscOptionsName("-ksp_plot_eigencontours", "[deprecated since PETSc 3.9; use -ksp_view_eigenvalues draw::draw_contour]", "KSPView", &ksp->viewEV));
590: if (ksp->viewEV) {
591: ksp->formatEV = PETSC_VIEWER_DRAW_CONTOUR;
592: ksp->viewerEV = PETSC_VIEWER_DRAW_(comm);
593: PetscCall(PetscObjectReference((PetscObject)ksp->viewerEV));
594: }
595: }
596: if (!ksp->viewEVExp) {
597: /* Cannot remove the what otherwise would be redundant call to PetscOptionsName("-ksp_plot_eigencontours_explicitly",...) below because the argument handling is different */
598: PetscCall(PetscOptionsName("-ksp_plot_eigenvalues_explicitly", "[deprecated since PETSc 3.9; use -ksp_view_eigenvalues_explicit draw]", "KSPView", &ksp->viewEVExp));
599: if (ksp->viewEVExp) {
600: ksp->formatEVExp = PETSC_VIEWER_DEFAULT;
601: ksp->viewerEVExp = PETSC_VIEWER_DRAW_(comm);
602: PetscCall(PetscObjectReference((PetscObject)ksp->viewerEVExp));
603: }
604: }
606: #if defined(PETSC_HAVE_SAWS)
607: /*
608: Publish convergence information using AMS
609: */
610: PetscCall(PetscOptionsBool("-ksp_monitor_saws", "Publish KSP progress using SAWs", "KSPMonitorSet", PETSC_FALSE, &flg, &set));
611: if (set && flg) {
612: void *ctx;
613: PetscCall(KSPMonitorSAWsCreate(ksp, &ctx));
614: PetscCall(KSPMonitorSet(ksp, KSPMonitorSAWs, ctx, KSPMonitorSAWsDestroy));
615: PetscCall(KSPSetComputeSingularValues(ksp, PETSC_TRUE));
616: }
617: #endif
619: PetscCall(KSPSetUpNorms_Private(ksp, PETSC_FALSE, NULL, &pcside));
620: PetscCall(PetscOptionsEnum("-ksp_pc_side", "KSP preconditioner side", "KSPSetPCSide", PCSides, (PetscEnum)pcside, (PetscEnum *)&pcside, &flg));
621: if (flg) PetscCall(KSPSetPCSide(ksp, pcside));
623: if (ksp->viewSV || ksp->viewEV) PetscCall(KSPSetComputeSingularValues(ksp, PETSC_TRUE));
625: #if defined(PETSC_HAVE_SAWS)
626: {
627: PetscBool set;
628: flg = PETSC_FALSE;
629: PetscCall(PetscOptionsBool("-ksp_saws_block", "Block for SAWs at end of KSPSolve", "PetscObjectSAWsBlock", ((PetscObject)ksp)->amspublishblock, &flg, &set));
630: if (set) PetscCall(PetscObjectSAWsSetBlock((PetscObject)ksp, flg));
631: }
632: #endif
634: nmax = ksp->nmax;
635: PetscCall(PetscOptionsDeprecated("-ksp_matsolve_block_size", "-ksp_matsolve_batch_size", "3.15", NULL));
636: PetscCall(PetscOptionsInt("-ksp_matsolve_batch_size", "Maximum number of columns treated simultaneously", "KSPSetMatSolveBatchSize", nmax, &nmax, &flg));
637: if (flg) PetscCall(KSPSetMatSolveBatchSize(ksp, nmax));
639: flg = PETSC_FALSE;
640: PetscCall(PetscOptionsBool("-ksp_use_explicittranspose", "Explicitly transpose the system in KSPSolveTranspose", "KSPSetUseExplicitTranspose", ksp->transpose.use_explicittranspose, &flg, &set));
641: if (set) PetscCall(KSPSetUseExplicitTranspose(ksp, flg));
643: PetscTryTypeMethod(ksp, setfromoptions, PetscOptionsObject);
644: skipoptions:
645: /* process any options handlers added with PetscObjectAddOptionsHandler() */
646: PetscCall(PetscObjectProcessOptionsHandlers((PetscObject)ksp, PetscOptionsObject));
647: PetscOptionsEnd();
648: ksp->setfromoptionscalled++;
649: PetscFunctionReturn(PETSC_SUCCESS);
650: }
652: /*@
653: KSPResetFromOptions - Sets `KSP` parameters from user options ONLY if the `KSP` was previously set from options
655: Collective
657: Input Parameter:
658: . ksp - the `KSP` context
660: Level: advanced
662: .seealso: [](ch_ksp), `KSPSetFromOptions()`, `KSPSetOptionsPrefix()`
663: @*/
664: PetscErrorCode KSPResetFromOptions(KSP ksp)
665: {
666: PetscFunctionBegin;
667: if (ksp->setfromoptionscalled) PetscCall(KSPSetFromOptions(ksp));
668: PetscFunctionReturn(PETSC_SUCCESS);
669: }