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: if (!mfunc) SETERRQ(PetscObjectComm((PetscObject)lme),PETSC_ERR_SUP,"Specified viewer and format not supported");
55: PetscFunctionListFind(LMEMonitorCreateList,key,&cfunc);
56: PetscFunctionListFind(LMEMonitorDestroyList,key,&dfunc);
57: if (!cfunc) cfunc = PetscViewerAndFormatCreate_Internal;
58: if (!dfunc) dfunc = PetscViewerAndFormatDestroy;
60: (*cfunc)(viewer,format,ctx,&vf);
61: PetscObjectDereference((PetscObject)viewer);
62: LMEMonitorSet(lme,mfunc,vf,(PetscErrorCode(*)(void **))dfunc);
63: return(0);
64: }
66: /*@
67: LMESetFromOptions - Sets LME options from the options database.
68: This routine must be called before LMESetUp() if the user is to be
69: allowed to set the solver type.
71: Collective on lme
73: Input Parameters:
74: . lme - the linear matrix equation solver context
76: Notes:
77: To see all options, run your program with the -help option.
79: Level: beginner
80: @*/
81: PetscErrorCode LMESetFromOptions(LME lme) 82: {
84: char type[256];
85: PetscBool set,flg,flg1,flg2;
86: PetscReal r;
87: PetscInt i;
91: LMERegisterAll();
92: PetscObjectOptionsBegin((PetscObject)lme);
93: PetscOptionsFList("-lme_type","Linear matrix equation","LMESetType",LMEList,(char*)(((PetscObject)lme)->type_name?((PetscObject)lme)->type_name:LMEKRYLOV),type,sizeof(type),&flg);
94: if (flg) {
95: LMESetType(lme,type);
96: } else if (!((PetscObject)lme)->type_name) {
97: LMESetType(lme,LMEKRYLOV);
98: }
100: PetscOptionsBoolGroupBegin("-lme_lyapunov","Continuous-time Lyapunov equation","LMESetProblemType",&flg);
101: if (flg) { LMESetProblemType(lme,LME_LYAPUNOV); }
102: PetscOptionsBoolGroup("-lme_sylvester","Continuous-time Sylvester equation","LMESetProblemType",&flg);
103: if (flg) { LMESetProblemType(lme,LME_SYLVESTER); }
104: PetscOptionsBoolGroup("-lme_gen_lyapunov","Generalized Lyapunov equation","LMESetProblemType",&flg);
105: if (flg) { LMESetProblemType(lme,LME_GEN_LYAPUNOV); }
106: PetscOptionsBoolGroup("-lme_gen_sylvester","Generalized Sylvester equation","LMESetProblemType",&flg);
107: if (flg) { LMESetProblemType(lme,LME_GEN_SYLVESTER); }
108: PetscOptionsBoolGroup("-lme_dt_lyapunov","Discrete-time Lyapunov equation","LMESetProblemType",&flg);
109: if (flg) { LMESetProblemType(lme,LME_DT_LYAPUNOV); }
110: PetscOptionsBoolGroupEnd("-lme_stein","Stein equation","LMESetProblemType",&flg);
111: if (flg) { LMESetProblemType(lme,LME_STEIN); }
113: i = lme->max_it;
114: PetscOptionsInt("-lme_max_it","Maximum number of iterations","LMESetTolerances",lme->max_it,&i,&flg1);
115: if (!flg1) i = PETSC_DEFAULT;
116: r = lme->tol;
117: PetscOptionsReal("-lme_tol","Tolerance","LMESetTolerances",SlepcDefaultTol(lme->tol),&r,&flg2);
118: if (flg1 || flg2) { LMESetTolerances(lme,r,i); }
120: PetscOptionsInt("-lme_ncv","Number of basis vectors","LMESetDimensions",lme->ncv,&i,&flg);
121: if (flg) { LMESetDimensions(lme,i); }
123: PetscOptionsBool("-lme_error_if_not_converged","Generate error if solver does not converge","LMESetErrorIfNotConverged",lme->errorifnotconverged,&lme->errorifnotconverged,NULL);
125: /* -----------------------------------------------------------------------*/
126: /*
127: Cancels all monitors hardwired into code before call to LMESetFromOptions()
128: */
129: PetscOptionsBool("-lme_monitor_cancel","Remove any hardwired monitor routines","LMEMonitorCancel",PETSC_FALSE,&flg,&set);
130: if (set && flg) { LMEMonitorCancel(lme); }
131: LMEMonitorSetFromOptions(lme,"-lme_monitor","error_estimate",NULL);
133: /* -----------------------------------------------------------------------*/
134: PetscOptionsName("-lme_view","Print detailed information on solver used","LMEView",NULL);
136: if (lme->ops->setfromoptions) {
137: (*lme->ops->setfromoptions)(PetscOptionsObject,lme);
138: }
139: PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)lme);
140: PetscOptionsEnd();
142: if (!lme->V) { LMEGetBV(lme,&lme->V); }
143: BVSetFromOptions(lme->V);
144: return(0);
145: }
147: /*@
148: LMESetProblemType - Specifies the type of matrix equation to be solved.
150: Logically Collective on lme
152: Input Parameters:
153: + lme - the linear matrix equation solver context
154: - type - a known type of matrix equation
156: Options Database Keys:
157: + -lme_lyapunov - continuous-time Lyapunov equation A*X+X*A'=-C
158: . -lme_sylvester - continuous-time Sylvester equation A*X+X*B=C
159: . -lme_gen_lyapunov - generalized Lyapunov equation A*X*D'+D*X*A'=-C
160: . -lme_gen_sylvester - generalized Sylvester equation A*X*E+D*X*B=C
161: . -lme_dt_lyapunov - discrete-time Lyapunov equation A*X*A'-X=-C
162: - -lme_stein - Stein equation A*X*E+X=C
164: Notes:
165: The coefficient matrices A, B, D, E must be provided via LMESetCoefficients(),
166: but some of them are optional depending on the matrix equation.
168: .vb
169: equation A B D E
170: ----------------- --- --- --- ---
171: LME_LYAPUNOV A*X+X*A'=-C yes (A-t) - -
172: LME_SYLVESTER A*X+X*B=C yes yes - -
173: LME_GEN_LYAPUNOV A*X*D'+D*X*A'=-C yes (A-t) yes (D-t)
174: LME_GEN_SYLVESTER A*X*E+D*X*B=C yes yes yes yes
175: LME_DT_LYAPUNOV A*X*A'-X=-C yes - - (A-t)
176: LME_STEIN A*X*E+X=C yes - - yes
177: .ve
179: In the above table, the notation (A-t) means that this matrix need
180: not be passed, but the user may choose to pass an explicit transpose
181: of matrix A (for improved efficiency).
183: Also note that some of the equation types impose restrictions on the
184: properties of the coefficient matrices and possibly on the right-hand
185: side C.
187: Level: beginner
189: .seealso: LMESetCoefficients(), LMESetType(), LMEGetProblemType(), LMEProblemType190: @*/
191: PetscErrorCode LMESetProblemType(LME lme,LMEProblemType type)192: {
196: if (type == lme->problem_type) return(0);
197: switch (type) {
198: case LME_LYAPUNOV:
199: case LME_SYLVESTER:
200: case LME_GEN_LYAPUNOV:
201: case LME_GEN_SYLVESTER:
202: case LME_DT_LYAPUNOV:
203: case LME_STEIN:
204: break;
205: default:206: SETERRQ(PetscObjectComm((PetscObject)lme),PETSC_ERR_ARG_WRONG,"Unknown matrix equation type");
207: }
208: lme->problem_type = type;
209: lme->setupcalled = PETSC_FALSE;
210: return(0);
211: }
213: /*@
214: LMEGetProblemType - Gets the matrix equation type from the LME object.
216: Not Collective
218: Input Parameter:
219: . lme - the linear matrix equation solver context
221: Output Parameter:
222: . type - name of LME problem type
224: Level: intermediate
226: .seealso: LMESetProblemType(), LMEProblemType227: @*/
228: PetscErrorCode LMEGetProblemType(LME lme,LMEProblemType *type)229: {
233: *type = lme->problem_type;
234: return(0);
235: }
237: /*@C
238: LMEGetTolerances - Gets the tolerance and maximum iteration count used
239: by the LME convergence tests.
241: Not Collective
243: Input Parameter:
244: . lme - the linear matrix equation solver context
246: Output Parameters:
247: + tol - the convergence tolerance
248: - maxits - maximum number of iterations
250: Notes:
251: The user can specify NULL for any parameter that is not needed.
253: Level: intermediate
255: .seealso: LMESetTolerances()
256: @*/
257: PetscErrorCode LMEGetTolerances(LME lme,PetscReal *tol,PetscInt *maxits)258: {
261: if (tol) *tol = lme->tol;
262: if (maxits) *maxits = lme->max_it;
263: return(0);
264: }
266: /*@
267: LMESetTolerances - Sets the tolerance and maximum iteration count used
268: by the LME convergence tests.
270: Logically Collective on lme
272: Input Parameters:
273: + lme - the linear matrix equation solver context
274: . tol - the convergence tolerance
275: - maxits - maximum number of iterations to use
277: Options Database Keys:
278: + -lme_tol <tol> - Sets the convergence tolerance
279: - -lme_max_it <maxits> - Sets the maximum number of iterations allowed
281: Notes:
282: Use PETSC_DEFAULT for either argument to assign a reasonably good value.
284: Level: intermediate
286: .seealso: LMEGetTolerances()
287: @*/
288: PetscErrorCode LMESetTolerances(LME lme,PetscReal tol,PetscInt maxits)289: {
294: if (tol == PETSC_DEFAULT) {
295: lme->tol = PETSC_DEFAULT;
296: lme->setupcalled = 0;
297: } else {
298: if (tol <= 0.0) SETERRQ(PetscObjectComm((PetscObject)lme),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of tol. Must be > 0");
299: lme->tol = tol;
300: }
301: if (maxits == PETSC_DEFAULT || maxits == PETSC_DECIDE) {
302: lme->max_it = PETSC_DEFAULT;
303: lme->setupcalled = 0;
304: } else {
305: if (maxits <= 0) SETERRQ(PetscObjectComm((PetscObject)lme),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of maxits. Must be > 0");
306: lme->max_it = maxits;
307: }
308: return(0);
309: }
311: /*@
312: LMEGetDimensions - Gets the dimension of the subspace used by the solver.
314: Not Collective
316: Input Parameter:
317: . lme - the linear matrix equation solver context
319: Output Parameter:
320: . ncv - the maximum dimension of the subspace to be used by the solver
322: Level: intermediate
324: .seealso: LMESetDimensions()
325: @*/
326: PetscErrorCode LMEGetDimensions(LME lme,PetscInt *ncv)327: {
331: *ncv = lme->ncv;
332: return(0);
333: }
335: /*@
336: LMESetDimensions - Sets the dimension of the subspace to be used by the solver.
338: Logically Collective on lme
340: Input Parameters:
341: + lme - the linear matrix equation solver context
342: - ncv - the maximum dimension of the subspace to be used by the solver
344: Options Database Keys:
345: . -lme_ncv <ncv> - Sets the dimension of the subspace
347: Notes:
348: Use PETSC_DEFAULT for ncv to assign a reasonably good value, which is
349: dependent on the solution method.
351: Level: intermediate
353: .seealso: LMEGetDimensions()
354: @*/
355: PetscErrorCode LMESetDimensions(LME lme,PetscInt ncv)356: {
360: if (ncv == PETSC_DECIDE || ncv == PETSC_DEFAULT) {
361: lme->ncv = PETSC_DEFAULT;
362: } else {
363: if (ncv<1) SETERRQ(PetscObjectComm((PetscObject)lme),PETSC_ERR_ARG_OUTOFRANGE,"Illegal value of ncv. Must be > 0");
364: lme->ncv = ncv;
365: }
366: lme->setupcalled = 0;
367: return(0);
368: }
370: /*@
371: LMESetErrorIfNotConverged - Causes LMESolve() to generate an error if the
372: solver has not converged.
374: Logically Collective on lme
376: Input Parameters:
377: + lme - the linear matrix equation solver context
378: - flg - PETSC_TRUE indicates you want the error generated
380: Options Database Keys:
381: . -lme_error_if_not_converged - this takes an optional truth value (0/1/no/yes/true/false)
383: Level: intermediate
385: Note:
386: Normally SLEPc continues if the solver fails to converge, you can call
387: LMEGetConvergedReason() after a LMESolve() to determine if it has converged.
389: .seealso: LMEGetErrorIfNotConverged()
390: @*/
391: PetscErrorCode LMESetErrorIfNotConverged(LME lme,PetscBool flg)392: {
396: lme->errorifnotconverged = flg;
397: return(0);
398: }
400: /*@
401: LMEGetErrorIfNotConverged - Return a flag indicating whether LMESolve() will
402: generate an error if the solver does not converge.
404: Not Collective
406: Input Parameter:
407: . lme - the linear matrix equation solver context
409: Output Parameter:
410: . flag - PETSC_TRUE if it will generate an error, else PETSC_FALSE
412: Level: intermediate
414: .seealso: LMESetErrorIfNotConverged()
415: @*/
416: PetscErrorCode LMEGetErrorIfNotConverged(LME lme,PetscBool *flag)417: {
421: *flag = lme->errorifnotconverged;
422: return(0);
423: }
425: /*@C
426: LMESetOptionsPrefix - Sets the prefix used for searching for all
427: LME options in the database.
429: Logically Collective on lme
431: Input Parameters:
432: + lme - the linear matrix equation solver context
433: - prefix - the prefix string to prepend to all LME option requests
435: Notes:
436: A hyphen (-) must NOT be given at the beginning of the prefix name.
437: The first character of all runtime options is AUTOMATICALLY the
438: hyphen.
440: For example, to distinguish between the runtime options for two
441: different LME contexts, one could call
442: .vb
443: LMESetOptionsPrefix(lme1,"fun1_")
444: LMESetOptionsPrefix(lme2,"fun2_")
445: .ve
447: Level: advanced
449: .seealso: LMEAppendOptionsPrefix(), LMEGetOptionsPrefix()
450: @*/
451: PetscErrorCode LMESetOptionsPrefix(LME lme,const char *prefix)452: {
457: if (!lme->V) { LMEGetBV(lme,&lme->V); }
458: BVSetOptionsPrefix(lme->V,prefix);
459: PetscObjectSetOptionsPrefix((PetscObject)lme,prefix);
460: return(0);
461: }
463: /*@C
464: LMEAppendOptionsPrefix - Appends to the prefix used for searching for all
465: LME options in the database.
467: Logically Collective on lme
469: Input Parameters:
470: + lme - the linear matrix equation solver context
471: - prefix - the prefix string to prepend to all LME option requests
473: Notes:
474: A hyphen (-) must NOT be given at the beginning of the prefix name.
475: The first character of all runtime options is AUTOMATICALLY the hyphen.
477: Level: advanced
479: .seealso: LMESetOptionsPrefix(), LMEGetOptionsPrefix()
480: @*/
481: PetscErrorCode LMEAppendOptionsPrefix(LME lme,const char *prefix)482: {
487: if (!lme->V) { LMEGetBV(lme,&lme->V); }
488: BVAppendOptionsPrefix(lme->V,prefix);
489: PetscObjectAppendOptionsPrefix((PetscObject)lme,prefix);
490: return(0);
491: }
493: /*@C
494: LMEGetOptionsPrefix - Gets the prefix used for searching for all
495: LME options in the database.
497: Not Collective
499: Input Parameters:
500: . lme - the linear matrix equation solver context
502: Output Parameters:
503: . prefix - pointer to the prefix string used is returned
505: Note:
506: On the Fortran side, the user should pass in a string 'prefix' of
507: sufficient length to hold the prefix.
509: Level: advanced
511: .seealso: LMESetOptionsPrefix(), LMEAppendOptionsPrefix()
512: @*/
513: PetscErrorCode LMEGetOptionsPrefix(LME lme,const char *prefix[])514: {
520: PetscObjectGetOptionsPrefix((PetscObject)lme,prefix);
521: return(0);
522: }