1: /*
2: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3: SLEPc - Scalable Library for Eigenvalue Problem Computations
4: Copyright (c) 2002-2021, Universitat Politecnica de Valencia, Spain
6: This file is part of SLEPc.
7: SLEPc is distributed under a 2-clause BSD license (see LICENSE).
8: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
9: */
10: /*
11: LME routines related to options that can be set via the command-line
12: or procedurally
13: */
15: #include <slepc/private/lmeimpl.h> 16: #include <petscdraw.h>
18: /*@C
19: LMEMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type
20: indicated by the user.
22: Collective on lme
24: Input Parameters:
25: + lme - the linear matrix equation context
26: . opt - the command line option for this monitor
27: . name - the monitor type one is seeking
28: - ctx - an optional user context for the monitor, or NULL
30: Level: developer
32: .seealso: LMEMonitorSet()
33: @*/
34: PetscErrorCode LMEMonitorSetFromOptions(LME lme,const char opt[],const char name[],void *ctx) 35: {
36: PetscErrorCode (*mfunc)(LME,PetscInt,PetscReal,void*);
37: PetscErrorCode (*cfunc)(PetscViewer,PetscViewerFormat,void*,PetscViewerAndFormat**);
38: PetscErrorCode (*dfunc)(PetscViewerAndFormat**);
39: PetscViewerAndFormat *vf;
40: PetscViewer viewer;
41: PetscViewerFormat format;
42: PetscViewerType vtype;
43: char key[PETSC_MAX_PATH_LEN];
44: PetscBool flg;
45: PetscErrorCode ierr;
48: PetscOptionsGetViewer(PetscObjectComm((PetscObject)lme),((PetscObject)lme)->options,((PetscObject)lme)->prefix,opt,&viewer,&format,&flg);
49: if (!flg) return(0);
51: PetscViewerGetType(viewer,&vtype);
52: SlepcMonitorMakeKey_Internal(name,vtype,format,key);
53: PetscFunctionListFind(LMEMonitorList,key,&mfunc);
54: PetscFunctionListFind(LMEMonitorCreateList,key,&cfunc);
55: PetscFunctionListFind(LMEMonitorDestroyList,key,&dfunc);
56: if (!cfunc) cfunc = PetscViewerAndFormatCreate_Internal;
57: if (!dfunc) dfunc = PetscViewerAndFormatDestroy;
59: (*cfunc)(viewer,format,ctx,&vf);
60: PetscObjectDereference((PetscObject)viewer);
61: LMEMonitorSet(lme,mfunc,vf,(PetscErrorCode(*)(void **))dfunc);
62: return(0);
63: }
65: /*@
66: LMESetFromOptions - Sets LME options from the options database.
67: This routine must be called before LMESetUp() if the user is to be
68: allowed to set the solver type.
70: Collective on lme
72: Input Parameters:
73: . lme - the linear matrix equation solver context
75: Notes:
76: To see all options, run your program with the -help option.
78: Level: beginner
79: @*/
80: PetscErrorCode LMESetFromOptions(LME lme) 81: {
83: char type[256];
84: PetscBool set,flg,flg1,flg2;
85: PetscReal r;
86: PetscInt i;
90: LMERegisterAll();
91: PetscObjectOptionsBegin((PetscObject)lme);
92: PetscOptionsFList("-lme_type","Linear matrix equation","LMESetType",LMEList,(char*)(((PetscObject)lme)->type_name?((PetscObject)lme)->type_name:LMEKRYLOV),type,sizeof(type),&flg);
93: if (flg) {
94: LMESetType(lme,type);
95: } else if (!((PetscObject)lme)->type_name) {
96: LMESetType(lme,LMEKRYLOV);
97: }
99: PetscOptionsBoolGroupBegin("-lme_lyapunov","Continuous-time Lyapunov equation","LMESetProblemType",&flg);
100: if (flg) { LMESetProblemType(lme,LME_LYAPUNOV); }
101: PetscOptionsBoolGroup("-lme_sylvester","Continuous-time Sylvester equation","LMESetProblemType",&flg);
102: if (flg) { LMESetProblemType(lme,LME_SYLVESTER); }
103: PetscOptionsBoolGroup("-lme_gen_lyapunov","Generalized Lyapunov equation","LMESetProblemType",&flg);
104: if (flg) { LMESetProblemType(lme,LME_GEN_LYAPUNOV); }
105: PetscOptionsBoolGroup("-lme_gen_sylvester","Generalized Sylvester equation","LMESetProblemType",&flg);
106: if (flg) { LMESetProblemType(lme,LME_GEN_SYLVESTER); }
107: PetscOptionsBoolGroup("-lme_dt_lyapunov","Discrete-time Lyapunov equation","LMESetProblemType",&flg);
108: if (flg) { LMESetProblemType(lme,LME_DT_LYAPUNOV); }
109: PetscOptionsBoolGroupEnd("-lme_stein","Stein equation","LMESetProblemType",&flg);
110: if (flg) { LMESetProblemType(lme,LME_STEIN); }
112: i = lme->max_it;
113: PetscOptionsInt("-lme_max_it","Maximum number of iterations","LMESetTolerances",lme->max_it,&i,&flg1);
114: if (!flg1) i = PETSC_DEFAULT;
115: r = lme->tol;
116: PetscOptionsReal("-lme_tol","Tolerance","LMESetTolerances",lme->tol==PETSC_DEFAULT?SLEPC_DEFAULT_TOL:lme->tol,&r,&flg2);
117: if (flg1 || flg2) { LMESetTolerances(lme,r,i); }
119: PetscOptionsInt("-lme_ncv","Number of basis vectors","LMESetDimensions",lme->ncv,&i,&flg);
120: if (flg) { LMESetDimensions(lme,i); }
122: PetscOptionsBool("-lme_error_if_not_converged","Generate error if solver does not converge","LMESetErrorIfNotConverged",lme->errorifnotconverged,&lme->errorifnotconverged,NULL);
124: /* -----------------------------------------------------------------------*/
125: /*
126: Cancels all monitors hardwired into code before call to LMESetFromOptions()
127: */
128: PetscOptionsBool("-lme_monitor_cancel","Remove any hardwired monitor routines","LMEMonitorCancel",PETSC_FALSE,&flg,&set);
129: if (set && flg) { LMEMonitorCancel(lme); }
130: LMEMonitorSetFromOptions(lme,"-lme_monitor","error_estimate",NULL);
132: /* -----------------------------------------------------------------------*/
133: PetscOptionsName("-lme_view","Print detailed information on solver used","LMEView",NULL);
135: if (lme->ops->setfromoptions) {
136: (*lme->ops->setfromoptions)(PetscOptionsObject,lme);
137: }
138: PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)lme);
139: PetscOptionsEnd();
141: if (!lme->V) { LMEGetBV(lme,&lme->V); }
142: BVSetFromOptions(lme->V);
143: return(0);
144: }
146: /*@
147: LMESetProblemType - Specifies the type of matrix equation to be solved.
149: Logically Collective on lme
151: Input Parameters:
152: + lme - the linear matrix equation solver context
153: - type - a known type of matrix equation
155: Options Database Keys:
156: + -lme_lyapunov - continuous-time Lyapunov equation A*X+X*A'=-C
157: . -lme_sylvester - continuous-time Sylvester equation A*X+X*B=C
158: . -lme_gen_lyapunov - generalized Lyapunov equation A*X*D'+D*X*A'=-C
159: . -lme_gen_sylvester - generalized Sylvester equation A*X*E+D*X*B=C
160: . -lme_dt_lyapunov - discrete-time Lyapunov equation A*X*A'-X=-C
161: - -lme_stein - Stein equation A*X*E+X=C
163: Notes:
164: The coefficient matrices A, B, D, E must be provided via LMESetCoefficients(),
165: but some of them are optional depending on the matrix equation.
167: .vb
168: equation A B D E
169: ----------------- --- --- --- ---
170: LME_LYAPUNOV A*X+X*A'=-C yes (A-t) - -
171: LME_SYLVESTER A*X+X*B=C yes yes - -
172: LME_GEN_LYAPUNOV A*X*D'+D*X*A'=-C yes (A-t) yes (D-t)
173: LME_GEN_SYLVESTER A*X*E+D*X*B=C yes yes yes yes
174: LME_DT_LYAPUNOV A*X*A'-X=-C yes - - (A-t)
175: LME_STEIN A*X*E+X=C yes - - yes
176: .ve
178: In the above table, the notation (A-t) means that this matrix need
179: not be passed, but the user may choose to pass an explicit transpose
180: of matrix A (for improved efficiency).
182: Also note that some of the equation types impose restrictions on the
183: properties of the coefficient matrices and possibly on the right-hand
184: side C.
186: Level: beginner
188: .seealso: LMESetCoefficients(), LMESetType(), LMEGetProblemType(), LMEProblemType189: @*/
190: PetscErrorCode LMESetProblemType(LME lme,LMEProblemType type)191: {
195: if (type == lme->problem_type) return(0);
196: switch (type) {
197: case LME_LYAPUNOV:
198: case LME_SYLVESTER:
199: case LME_GEN_LYAPUNOV:
200: case LME_GEN_SYLVESTER:
201: case LME_DT_LYAPUNOV:
202: case LME_STEIN:
203: break;
204: default:205: SETERRQ(PetscObjectComm((PetscObject)lme),PETSC_ERR_ARG_WRONG,"Unknown matrix equation type");
206: }
207: lme->problem_type = type;
208: lme->setupcalled = PETSC_FALSE;
209: return(0);
210: }
212: /*@
213: LMEGetProblemType - Gets the matrix equation type from the LME object.
215: Not Collective
217: Input Parameter:
218: . lme - the linear matrix equation solver context
220: Output Parameter:
221: . type - name of LME problem type
223: Level: intermediate
225: .seealso: LMESetProblemType(), LMEProblemType226: @*/
227: PetscErrorCode LMEGetProblemType(LME lme,LMEProblemType *type)228: {
232: *type = lme->problem_type;
233: return(0);
234: }
236: /*@C
237: LMEGetTolerances - Gets the tolerance and maximum iteration count used
238: by the LME convergence tests.
240: Not Collective
242: Input Parameter:
243: . lme - the linear matrix equation solver context
245: Output Parameters:
246: + tol - the convergence tolerance
247: - maxits - maximum number of iterations
249: Notes:
250: The user can specify NULL for any parameter that is not needed.
252: Level: intermediate
254: .seealso: LMESetTolerances()
255: @*/
256: PetscErrorCode LMEGetTolerances(LME lme,PetscReal *tol,PetscInt *maxits)257: {
260: if (tol) *tol = lme->tol;
261: if (maxits) *maxits = lme->max_it;
262: return(0);
263: }
265: /*@
266: LMESetTolerances - Sets the tolerance and maximum iteration count used
267: by the LME convergence tests.
269: Logically Collective on lme
271: Input Parameters:
272: + lme - the linear matrix equation solver context
273: . tol - the convergence tolerance
274: - maxits - maximum number of iterations to use
276: Options Database Keys:
277: + -lme_tol <tol> - Sets the convergence tolerance
278: - -lme_max_it <maxits> - Sets the maximum number of iterations allowed
280: Notes:
281: Use PETSC_DEFAULT for either argument to assign a reasonably good value.
283: Level: intermediate
285: .seealso: LMEGetTolerances()
286: @*/
287: PetscErrorCode LMESetTolerances(LME lme,PetscReal tol,PetscInt maxits)288: {
293: if (tol == PETSC_DEFAULT) {
294: lme->tol = PETSC_DEFAULT;
295: lme->setupcalled = 0;
296: } else {
297: if (tol <= 0.0) SETERRQ(PetscObjectComm((PetscObject)lme),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of tol. Must be > 0");
298: lme->tol = tol;
299: }
300: if (maxits == PETSC_DEFAULT || maxits == PETSC_DECIDE) {
301: lme->max_it = PETSC_DEFAULT;
302: lme->setupcalled = 0;
303: } else {
304: if (maxits <= 0) SETERRQ(PetscObjectComm((PetscObject)lme),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of maxits. Must be > 0");
305: lme->max_it = maxits;
306: }
307: return(0);
308: }
310: /*@
311: LMEGetDimensions - Gets the dimension of the subspace used by the solver.
313: Not Collective
315: Input Parameter:
316: . lme - the linear matrix equation solver context
318: Output Parameter:
319: . ncv - the maximum dimension of the subspace to be used by the solver
321: Level: intermediate
323: .seealso: LMESetDimensions()
324: @*/
325: PetscErrorCode LMEGetDimensions(LME lme,PetscInt *ncv)326: {
330: *ncv = lme->ncv;
331: return(0);
332: }
334: /*@
335: LMESetDimensions - Sets the dimension of the subspace to be used by the solver.
337: Logically Collective on lme
339: Input Parameters:
340: + lme - the linear matrix equation solver context
341: - ncv - the maximum dimension of the subspace to be used by the solver
343: Options Database Keys:
344: . -lme_ncv <ncv> - Sets the dimension of the subspace
346: Notes:
347: Use PETSC_DEFAULT for ncv to assign a reasonably good value, which is
348: dependent on the solution method.
350: Level: intermediate
352: .seealso: LMEGetDimensions()
353: @*/
354: PetscErrorCode LMESetDimensions(LME lme,PetscInt ncv)355: {
359: if (ncv == PETSC_DECIDE || ncv == PETSC_DEFAULT) {
360: lme->ncv = PETSC_DEFAULT;
361: } else {
362: if (ncv<1) SETERRQ(PetscObjectComm((PetscObject)lme),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of ncv. Must be > 0");
363: lme->ncv = ncv;
364: }
365: lme->setupcalled = 0;
366: return(0);
367: }
369: /*@
370: LMESetErrorIfNotConverged - Causes LMESolve() to generate an error if the
371: solver has not converged.
373: Logically Collective on lme
375: Input Parameters:
376: + lme - the linear matrix equation solver context
377: - flg - PETSC_TRUE indicates you want the error generated
379: Options Database Keys:
380: . -lme_error_if_not_converged - this takes an optional truth value (0/1/no/yes/true/false)
382: Level: intermediate
384: Note:
385: Normally SLEPc continues if the solver fails to converge, you can call
386: LMEGetConvergedReason() after a LMESolve() to determine if it has converged.
388: .seealso: LMEGetErrorIfNotConverged()
389: @*/
390: PetscErrorCode LMESetErrorIfNotConverged(LME lme,PetscBool flg)391: {
395: lme->errorifnotconverged = flg;
396: return(0);
397: }
399: /*@
400: LMEGetErrorIfNotConverged - Return a flag indicating whether LMESolve() will
401: generate an error if the solver does not converge.
403: Not Collective
405: Input Parameter:
406: . lme - the linear matrix equation solver context
408: Output Parameter:
409: . flag - PETSC_TRUE if it will generate an error, else PETSC_FALSE
411: Level: intermediate
413: .seealso: LMESetErrorIfNotConverged()
414: @*/
415: PetscErrorCode LMEGetErrorIfNotConverged(LME lme,PetscBool *flag)416: {
420: *flag = lme->errorifnotconverged;
421: return(0);
422: }
424: /*@C
425: LMESetOptionsPrefix - Sets the prefix used for searching for all
426: LME options in the database.
428: Logically Collective on lme
430: Input Parameters:
431: + lme - the linear matrix equation solver context
432: - prefix - the prefix string to prepend to all LME option requests
434: Notes:
435: A hyphen (-) must NOT be given at the beginning of the prefix name.
436: The first character of all runtime options is AUTOMATICALLY the
437: hyphen.
439: For example, to distinguish between the runtime options for two
440: different LME contexts, one could call
441: .vb
442: LMESetOptionsPrefix(lme1,"fun1_")
443: LMESetOptionsPrefix(lme2,"fun2_")
444: .ve
446: Level: advanced
448: .seealso: LMEAppendOptionsPrefix(), LMEGetOptionsPrefix()
449: @*/
450: PetscErrorCode LMESetOptionsPrefix(LME lme,const char *prefix)451: {
456: if (!lme->V) { LMEGetBV(lme,&lme->V); }
457: BVSetOptionsPrefix(lme->V,prefix);
458: PetscObjectSetOptionsPrefix((PetscObject)lme,prefix);
459: return(0);
460: }
462: /*@C
463: LMEAppendOptionsPrefix - Appends to the prefix used for searching for all
464: LME options in the database.
466: Logically Collective on lme
468: Input Parameters:
469: + lme - the linear matrix equation solver context
470: - prefix - the prefix string to prepend to all LME option requests
472: Notes:
473: A hyphen (-) must NOT be given at the beginning of the prefix name.
474: The first character of all runtime options is AUTOMATICALLY the hyphen.
476: Level: advanced
478: .seealso: LMESetOptionsPrefix(), LMEGetOptionsPrefix()
479: @*/
480: PetscErrorCode LMEAppendOptionsPrefix(LME lme,const char *prefix)481: {
486: if (!lme->V) { LMEGetBV(lme,&lme->V); }
487: BVAppendOptionsPrefix(lme->V,prefix);
488: PetscObjectAppendOptionsPrefix((PetscObject)lme,prefix);
489: return(0);
490: }
492: /*@C
493: LMEGetOptionsPrefix - Gets the prefix used for searching for all
494: LME options in the database.
496: Not Collective
498: Input Parameters:
499: . lme - the linear matrix equation solver context
501: Output Parameters:
502: . prefix - pointer to the prefix string used is returned
504: Note:
505: On the Fortran side, the user should pass in a string 'prefix' of
506: sufficient length to hold the prefix.
508: Level: advanced
510: .seealso: LMESetOptionsPrefix(), LMEAppendOptionsPrefix()
511: @*/
512: PetscErrorCode LMEGetOptionsPrefix(LME lme,const char *prefix[])513: {
519: PetscObjectGetOptionsPrefix((PetscObject)lme,prefix);
520: return(0);
521: }