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