Actual source code: lmebasic.c
slepc-3.18.1 2022-11-02
1: /*
2: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3: SLEPc - Scalable Library for Eigenvalue Problem Computations
4: Copyright (c) 2002-, 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: Basic LME routines
12: */
14: #include <slepc/private/lmeimpl.h>
16: /* Logging support */
17: PetscClassId LME_CLASSID = 0;
18: PetscLogEvent LME_SetUp = 0,LME_Solve = 0,LME_ComputeError = 0;
20: /* List of registered LME routines */
21: PetscFunctionList LMEList = NULL;
22: PetscBool LMERegisterAllCalled = PETSC_FALSE;
24: /* List of registered LME monitors */
25: PetscFunctionList LMEMonitorList = NULL;
26: PetscFunctionList LMEMonitorCreateList = NULL;
27: PetscFunctionList LMEMonitorDestroyList = NULL;
28: PetscBool LMEMonitorRegisterAllCalled = PETSC_FALSE;
30: /*@C
31: LMEView - Prints the LME data structure.
33: Collective on lme
35: Input Parameters:
36: + lme - the linear matrix equation solver context
37: - viewer - optional visualization context
39: Options Database Key:
40: . -lme_view - Calls LMEView() at end of LMESolve()
42: Note:
43: The available visualization contexts include
44: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
45: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
46: output where only the first processor opens
47: the file. All other processors send their
48: data to the first processor to print.
50: The user can open an alternative visualization context with
51: PetscViewerASCIIOpen() - output to a specified file.
53: Level: beginner
55: .seealso: LMECreate()
56: @*/
57: PetscErrorCode LMEView(LME lme,PetscViewer viewer)
58: {
59: PetscBool isascii;
60: const char *eqname[] = {
61: "continuous-time Lyapunov",
62: "continuous-time Sylvester",
63: "generalized Lyapunov",
64: "generalized Sylvester",
65: "Stein",
66: "discrete-time Lyapunov"
67: };
70: if (!viewer) PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)lme),&viewer);
74: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
75: if (isascii) {
76: PetscObjectPrintClassNamePrefixType((PetscObject)lme,viewer);
77: PetscViewerASCIIPushTab(viewer);
78: PetscTryTypeMethod(lme,view,viewer);
79: PetscViewerASCIIPopTab(viewer);
80: PetscViewerASCIIPrintf(viewer," equation type: %s\n",eqname[lme->problem_type]);
81: PetscViewerASCIIPrintf(viewer," number of column vectors (ncv): %" PetscInt_FMT "\n",lme->ncv);
82: PetscViewerASCIIPrintf(viewer," maximum number of iterations: %" PetscInt_FMT "\n",lme->max_it);
83: PetscViewerASCIIPrintf(viewer," tolerance: %g\n",(double)lme->tol);
84: } else PetscTryTypeMethod(lme,view,viewer);
85: PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO);
86: if (!lme->V) LMEGetBV(lme,&lme->V);
87: BVView(lme->V,viewer);
88: PetscViewerPopFormat(viewer);
89: return 0;
90: }
92: /*@C
93: LMEViewFromOptions - View from options
95: Collective on LME
97: Input Parameters:
98: + lme - the linear matrix equation context
99: . obj - optional object
100: - name - command line option
102: Level: intermediate
104: .seealso: LMEView(), LMECreate()
105: @*/
106: PetscErrorCode LMEViewFromOptions(LME lme,PetscObject obj,const char name[])
107: {
109: PetscObjectViewFromOptions((PetscObject)lme,obj,name);
110: return 0;
111: }
112: /*@C
113: LMEConvergedReasonView - Displays the reason an LME solve converged or diverged.
115: Collective on lme
117: Input Parameters:
118: + lme - the linear matrix equation context
119: - viewer - the viewer to display the reason
121: Options Database Keys:
122: . -lme_converged_reason - print reason for convergence, and number of iterations
124: Note:
125: To change the format of the output call PetscViewerPushFormat(viewer,format) before
126: this call. Use PETSC_VIEWER_DEFAULT for the default, use PETSC_VIEWER_FAILED to only
127: display a reason if it fails. The latter can be set in the command line with
128: -lme_converged_reason ::failed
130: Level: intermediate
132: .seealso: LMESetTolerances(), LMEGetIterationNumber(), LMEConvergedReasonViewFromOptions()
133: @*/
134: PetscErrorCode LMEConvergedReasonView(LME lme,PetscViewer viewer)
135: {
136: PetscBool isAscii;
137: PetscViewerFormat format;
139: if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)lme));
140: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isAscii);
141: if (isAscii) {
142: PetscViewerGetFormat(viewer,&format);
143: PetscViewerASCIIAddTab(viewer,((PetscObject)lme)->tablevel);
144: if (lme->reason > 0 && format != PETSC_VIEWER_FAILED) PetscViewerASCIIPrintf(viewer,"%s Linear matrix equation solve converged due to %s; iterations %" PetscInt_FMT "\n",((PetscObject)lme)->prefix?((PetscObject)lme)->prefix:"",LMEConvergedReasons[lme->reason],lme->its);
145: else if (lme->reason <= 0) PetscViewerASCIIPrintf(viewer,"%s Linear matrix equation solve did not converge due to %s; iterations %" PetscInt_FMT "\n",((PetscObject)lme)->prefix?((PetscObject)lme)->prefix:"",LMEConvergedReasons[lme->reason],lme->its);
146: PetscViewerASCIISubtractTab(viewer,((PetscObject)lme)->tablevel);
147: }
148: return 0;
149: }
151: /*@
152: LMEConvergedReasonViewFromOptions - Processes command line options to determine if/how
153: the LME converged reason is to be viewed.
155: Collective on lme
157: Input Parameter:
158: . lme - the linear matrix equation context
160: Level: developer
162: .seealso: LMEConvergedReasonView()
163: @*/
164: PetscErrorCode LMEConvergedReasonViewFromOptions(LME lme)
165: {
166: PetscViewer viewer;
167: PetscBool flg;
168: static PetscBool incall = PETSC_FALSE;
169: PetscViewerFormat format;
171: if (incall) return 0;
172: incall = PETSC_TRUE;
173: PetscOptionsGetViewer(PetscObjectComm((PetscObject)lme),((PetscObject)lme)->options,((PetscObject)lme)->prefix,"-lme_converged_reason",&viewer,&format,&flg);
174: if (flg) {
175: PetscViewerPushFormat(viewer,format);
176: LMEConvergedReasonView(lme,viewer);
177: PetscViewerPopFormat(viewer);
178: PetscViewerDestroy(&viewer);
179: }
180: incall = PETSC_FALSE;
181: return 0;
182: }
184: /*@
185: LMECreate - Creates the default LME context.
187: Collective
189: Input Parameter:
190: . comm - MPI communicator
192: Output Parameter:
193: . outlme - location to put the LME context
195: Note:
196: The default LME type is LMEKRYLOV
198: Level: beginner
200: .seealso: LMESetUp(), LMESolve(), LMEDestroy(), LME
201: @*/
202: PetscErrorCode LMECreate(MPI_Comm comm,LME *outlme)
203: {
204: LME lme;
207: *outlme = NULL;
208: LMEInitializePackage();
209: SlepcHeaderCreate(lme,LME_CLASSID,"LME","Linear Matrix Equation","LME",comm,LMEDestroy,LMEView);
211: lme->A = NULL;
212: lme->B = NULL;
213: lme->D = NULL;
214: lme->E = NULL;
215: lme->C = NULL;
216: lme->X = NULL;
217: lme->problem_type = LME_LYAPUNOV;
218: lme->max_it = PETSC_DEFAULT;
219: lme->ncv = PETSC_DEFAULT;
220: lme->tol = PETSC_DEFAULT;
221: lme->errorifnotconverged = PETSC_FALSE;
223: lme->numbermonitors = 0;
225: lme->V = NULL;
226: lme->nwork = 0;
227: lme->work = NULL;
228: lme->data = NULL;
230: lme->its = 0;
231: lme->errest = 0;
232: lme->setupcalled = 0;
233: lme->reason = LME_CONVERGED_ITERATING;
235: *outlme = lme;
236: return 0;
237: }
239: /*@C
240: LMESetType - Selects the particular solver to be used in the LME object.
242: Logically Collective on lme
244: Input Parameters:
245: + lme - the linear matrix equation context
246: - type - a known method
248: Options Database Key:
249: . -lme_type <method> - Sets the method; use -help for a list
250: of available methods
252: Notes:
253: See "slepc/include/slepclme.h" for available methods. The default
254: is LMEKRYLOV
256: Normally, it is best to use the LMESetFromOptions() command and
257: then set the LME type from the options database rather than by using
258: this routine. Using the options database provides the user with
259: maximum flexibility in evaluating the different available methods.
260: The LMESetType() routine is provided for those situations where it
261: is necessary to set the iterative solver independently of the command
262: line or options database.
264: Level: intermediate
266: .seealso: LMEType
267: @*/
268: PetscErrorCode LMESetType(LME lme,LMEType type)
269: {
270: PetscErrorCode (*r)(LME);
271: PetscBool match;
276: PetscObjectTypeCompare((PetscObject)lme,type,&match);
277: if (match) return 0;
279: PetscFunctionListFind(LMEList,type,&r);
282: PetscTryTypeMethod(lme,destroy);
283: PetscMemzero(lme->ops,sizeof(struct _LMEOps));
285: lme->setupcalled = 0;
286: PetscObjectChangeTypeName((PetscObject)lme,type);
287: (*r)(lme);
288: return 0;
289: }
291: /*@C
292: LMEGetType - Gets the LME type as a string from the LME object.
294: Not Collective
296: Input Parameter:
297: . lme - the linear matrix equation context
299: Output Parameter:
300: . type - name of LME method
302: Level: intermediate
304: .seealso: LMESetType()
305: @*/
306: PetscErrorCode LMEGetType(LME lme,LMEType *type)
307: {
310: *type = ((PetscObject)lme)->type_name;
311: return 0;
312: }
314: /*@C
315: LMERegister - Adds a method to the linear matrix equation solver package.
317: Not Collective
319: Input Parameters:
320: + name - name of a new user-defined solver
321: - function - routine to create the solver context
323: Notes:
324: LMERegister() may be called multiple times to add several user-defined solvers.
326: Sample usage:
327: .vb
328: LMERegister("my_solver",MySolverCreate);
329: .ve
331: Then, your solver can be chosen with the procedural interface via
332: $ LMESetType(lme,"my_solver")
333: or at runtime via the option
334: $ -lme_type my_solver
336: Level: advanced
338: .seealso: LMERegisterAll()
339: @*/
340: PetscErrorCode LMERegister(const char *name,PetscErrorCode (*function)(LME))
341: {
342: LMEInitializePackage();
343: PetscFunctionListAdd(&LMEList,name,function);
344: return 0;
345: }
347: /*@C
348: LMEMonitorRegister - Adds LME monitor routine.
350: Not Collective
352: Input Parameters:
353: + name - name of a new monitor routine
354: . vtype - a PetscViewerType for the output
355: . format - a PetscViewerFormat for the output
356: . monitor - monitor routine
357: . create - creation routine, or NULL
358: - destroy - destruction routine, or NULL
360: Notes:
361: LMEMonitorRegister() may be called multiple times to add several user-defined monitors.
363: Sample usage:
364: .vb
365: LMEMonitorRegister("my_monitor",PETSCVIEWERASCII,PETSC_VIEWER_ASCII_INFO_DETAIL,MyMonitor,NULL,NULL);
366: .ve
368: Then, your monitor can be chosen with the procedural interface via
369: $ LMEMonitorSetFromOptions(lme,"-lme_monitor_my_monitor","my_monitor",NULL)
370: or at runtime via the option
371: $ -lme_monitor_my_monitor
373: Level: advanced
375: .seealso: LMEMonitorRegisterAll()
376: @*/
377: PetscErrorCode LMEMonitorRegister(const char name[],PetscViewerType vtype,PetscViewerFormat format,PetscErrorCode (*monitor)(LME,PetscInt,PetscReal,PetscViewerAndFormat*),PetscErrorCode (*create)(PetscViewer,PetscViewerFormat,void*,PetscViewerAndFormat**),PetscErrorCode (*destroy)(PetscViewerAndFormat**))
378: {
379: char key[PETSC_MAX_PATH_LEN];
381: LMEInitializePackage();
382: SlepcMonitorMakeKey_Internal(name,vtype,format,key);
383: PetscFunctionListAdd(&LMEMonitorList,key,monitor);
384: if (create) PetscFunctionListAdd(&LMEMonitorCreateList,key,create);
385: if (destroy) PetscFunctionListAdd(&LMEMonitorDestroyList,key,destroy);
386: return 0;
387: }
389: /*@
390: LMEReset - Resets the LME context to the initial state (prior to setup)
391: and destroys any allocated Vecs and Mats.
393: Collective on lme
395: Input Parameter:
396: . lme - linear matrix equation context obtained from LMECreate()
398: Level: advanced
400: .seealso: LMEDestroy()
401: @*/
402: PetscErrorCode LMEReset(LME lme)
403: {
405: if (!lme) return 0;
406: PetscTryTypeMethod(lme,reset);
407: MatDestroy(&lme->A);
408: MatDestroy(&lme->B);
409: MatDestroy(&lme->D);
410: MatDestroy(&lme->E);
411: MatDestroy(&lme->C);
412: MatDestroy(&lme->X);
413: BVDestroy(&lme->V);
414: VecDestroyVecs(lme->nwork,&lme->work);
415: lme->nwork = 0;
416: lme->setupcalled = 0;
417: return 0;
418: }
420: /*@C
421: LMEDestroy - Destroys the LME context.
423: Collective on lme
425: Input Parameter:
426: . lme - linear matrix equation context obtained from LMECreate()
428: Level: beginner
430: .seealso: LMECreate(), LMESetUp(), LMESolve()
431: @*/
432: PetscErrorCode LMEDestroy(LME *lme)
433: {
434: if (!*lme) return 0;
436: if (--((PetscObject)(*lme))->refct > 0) { *lme = NULL; return 0; }
437: LMEReset(*lme);
438: PetscTryTypeMethod(*lme,destroy);
439: LMEMonitorCancel(*lme);
440: PetscHeaderDestroy(lme);
441: return 0;
442: }
444: /*@
445: LMESetBV - Associates a basis vectors object to the linear matrix equation solver.
447: Collective on lme
449: Input Parameters:
450: + lme - linear matrix equation context obtained from LMECreate()
451: - bv - the basis vectors object
453: Note:
454: Use LMEGetBV() to retrieve the basis vectors context (for example,
455: to free it at the end of the computations).
457: Level: advanced
459: .seealso: LMEGetBV()
460: @*/
461: PetscErrorCode LMESetBV(LME lme,BV bv)
462: {
466: PetscObjectReference((PetscObject)bv);
467: BVDestroy(&lme->V);
468: lme->V = bv;
469: return 0;
470: }
472: /*@
473: LMEGetBV - Obtain the basis vectors object associated to the matrix
474: function solver.
476: Not Collective
478: Input Parameters:
479: . lme - linear matrix equation context obtained from LMECreate()
481: Output Parameter:
482: . bv - basis vectors context
484: Level: advanced
486: .seealso: LMESetBV()
487: @*/
488: PetscErrorCode LMEGetBV(LME lme,BV *bv)
489: {
492: if (!lme->V) {
493: BVCreate(PetscObjectComm((PetscObject)lme),&lme->V);
494: PetscObjectIncrementTabLevel((PetscObject)lme->V,(PetscObject)lme,0);
495: PetscObjectSetOptions((PetscObject)lme->V,((PetscObject)lme)->options);
496: }
497: *bv = lme->V;
498: return 0;
499: }