Actual source code: lmebasic.c
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: /*@
31: LMEView - Prints the `LME` data structure.
33: Collective
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: Notes:
43: The available visualization contexts include
44: + `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
45: - `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard output where only the
46: first process opens the file; all other processes send their data to the
47: first one to print
49: The user can open an alternative visualization context with `PetscViewerASCIIOpen()`
50: to output to a specified file.
52: Level: beginner
54: .seealso: [](ch:lme), `LMECreate()`, `LMEViewFromOptions()`
55: @*/
56: PetscErrorCode LMEView(LME lme,PetscViewer viewer)
57: {
58: PetscBool isascii;
60: PetscFunctionBegin;
62: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)lme),&viewer));
64: PetscCheckSameComm(lme,1,viewer,2);
66: PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
67: if (isascii) {
68: PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)lme,viewer));
69: PetscCall(PetscViewerASCIIPushTab(viewer));
70: PetscTryTypeMethod(lme,view,viewer);
71: PetscCall(PetscViewerASCIIPopTab(viewer));
72: PetscCall(PetscViewerASCIIPrintf(viewer," equation type: %s\n",LMEProblemTypes[lme->problem_type]));
73: PetscCall(PetscViewerASCIIPrintf(viewer," number of column vectors (ncv): %" PetscInt_FMT "\n",lme->ncv));
74: PetscCall(PetscViewerASCIIPrintf(viewer," maximum number of iterations: %" PetscInt_FMT "\n",lme->max_it));
75: PetscCall(PetscViewerASCIIPrintf(viewer," tolerance: %g\n",(double)lme->tol));
76: } else PetscTryTypeMethod(lme,view,viewer);
77: PetscCall(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO));
78: if (!lme->V) PetscCall(LMEGetBV(lme,&lme->V));
79: PetscCall(BVView(lme->V,viewer));
80: PetscCall(PetscViewerPopFormat(viewer));
81: PetscFunctionReturn(PETSC_SUCCESS);
82: }
84: /*@
85: LMEViewFromOptions - View (print) an `LME` object based on values in the options database.
87: Collective
89: Input Parameters:
90: + lme - the linear matrix equation solver context
91: . obj - optional object that provides the options prefix used to query the options database
92: - name - command line option
94: Level: intermediate
96: .seealso: [](ch:lme), `LMEView()`, `LMECreate()`, `PetscObjectViewFromOptions()`
97: @*/
98: PetscErrorCode LMEViewFromOptions(LME lme,PetscObject obj,const char name[])
99: {
100: PetscFunctionBegin;
102: PetscCall(PetscObjectViewFromOptions((PetscObject)lme,obj,name));
103: PetscFunctionReturn(PETSC_SUCCESS);
104: }
105: /*@
106: LMEConvergedReasonView - Displays the reason an `LME` solve converged or diverged.
108: Collective
110: Input Parameters:
111: + lme - the linear matrix equation solver context
112: - viewer - the viewer to display the reason
114: Options Database Key:
115: . -lme_converged_reason - print reason for convergence/divergence, and number of iterations
117: Notes:
118: Use `LMEConvergedReasonViewFromOptions()` to display the reason based on values
119: in the options database.
121: To change the format of the output call `PetscViewerPushFormat()` before this
122: call. Use `PETSC_VIEWER_DEFAULT` for the default, or `PETSC_VIEWER_FAILED` to only
123: display a reason if it fails. The latter can be set in the command line with
124: `-lme_converged_reason ::failed`.
126: Level: intermediate
128: .seealso: [](ch:lme), `LMESetTolerances()`, `LMEGetIterationNumber()`, `LMEConvergedReasonViewFromOptions()`
129: @*/
130: PetscErrorCode LMEConvergedReasonView(LME lme,PetscViewer viewer)
131: {
132: PetscBool isAscii;
133: PetscViewerFormat format;
135: PetscFunctionBegin;
136: if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)lme));
137: PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isAscii));
138: if (isAscii) {
139: PetscCall(PetscViewerGetFormat(viewer,&format));
140: PetscCall(PetscViewerASCIIAddTab(viewer,((PetscObject)lme)->tablevel));
141: if (lme->reason > 0 && format != PETSC_VIEWER_FAILED) PetscCall(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));
142: else if (lme->reason <= 0) PetscCall(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));
143: PetscCall(PetscViewerASCIISubtractTab(viewer,((PetscObject)lme)->tablevel));
144: }
145: PetscFunctionReturn(PETSC_SUCCESS);
146: }
148: /*@
149: LMEConvergedReasonViewFromOptions - Processes command line options to determine if/how
150: the `LME` converged reason is to be viewed.
152: Collective
154: Input Parameter:
155: . lme - the linear matrix equation solver context
157: Level: intermediate
159: .seealso: [](ch:lme), `LMEConvergedReasonView()`
160: @*/
161: PetscErrorCode LMEConvergedReasonViewFromOptions(LME lme)
162: {
163: PetscViewer viewer;
164: PetscBool flg;
165: static PetscBool incall = PETSC_FALSE;
166: PetscViewerFormat format;
168: PetscFunctionBegin;
169: if (incall) PetscFunctionReturn(PETSC_SUCCESS);
170: incall = PETSC_TRUE;
171: PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)lme),((PetscObject)lme)->options,((PetscObject)lme)->prefix,"-lme_converged_reason",&viewer,&format,&flg));
172: if (flg) {
173: PetscCall(PetscViewerPushFormat(viewer,format));
174: PetscCall(LMEConvergedReasonView(lme,viewer));
175: PetscCall(PetscViewerPopFormat(viewer));
176: PetscCall(PetscViewerDestroy(&viewer));
177: }
178: incall = PETSC_FALSE;
179: PetscFunctionReturn(PETSC_SUCCESS);
180: }
182: /*@
183: LMECreate - Creates the `LME` context.
185: Collective
187: Input Parameter:
188: . comm - MPI communicator
190: Output Parameter:
191: . outlme - location to put the `LME` context
193: Note:
194: The default `LME` type is `LMEKRYLOV`.
196: Level: beginner
198: .seealso: [](ch:lme), `LMESetUp()`, `LMESolve()`, `LMEDestroy()`, `LME`
199: @*/
200: PetscErrorCode LMECreate(MPI_Comm comm,LME *outlme)
201: {
202: LME lme;
204: PetscFunctionBegin;
205: PetscAssertPointer(outlme,2);
206: PetscCall(LMEInitializePackage());
207: PetscCall(SlepcHeaderCreate(lme,LME_CLASSID,"LME","Linear Matrix Equation","LME",comm,LMEDestroy,LMEView));
209: lme->A = NULL;
210: lme->B = NULL;
211: lme->D = NULL;
212: lme->E = NULL;
213: lme->C = NULL;
214: lme->X = NULL;
215: lme->problem_type = LME_LYAPUNOV;
216: lme->max_it = PETSC_DETERMINE;
217: lme->ncv = PETSC_DETERMINE;
218: lme->tol = PETSC_DETERMINE;
219: lme->errorifnotconverged = PETSC_FALSE;
221: lme->numbermonitors = 0;
223: lme->V = NULL;
224: lme->nwork = 0;
225: lme->work = NULL;
226: lme->data = NULL;
228: lme->its = 0;
229: lme->errest = 0;
230: lme->setupcalled = 0;
231: lme->reason = LME_CONVERGED_ITERATING;
233: *outlme = lme;
234: PetscFunctionReturn(PETSC_SUCCESS);
235: }
237: /*@
238: LMESetType - Selects the particular solver to be used in the `LME` object.
240: Logically Collective
242: Input Parameters:
243: + lme - the linear matrix equation solver context
244: - type - a known method
246: Options Database Key:
247: . -lme_type \<type\> - sets the method; use -help for a list of available methods
249: Notes:
250: See `LMEType` for available methods. The default is `LMEKRYLOV`.
252: Normally, it is best to use the `LMESetFromOptions()` command and
253: then set the `LME` type from the options database rather than by using
254: this routine. Using the options database provides the user with
255: maximum flexibility in evaluating the different available methods.
256: The `LMESetType()` routine is provided for those situations where it
257: is necessary to set the iterative solver independently of the command
258: line or options database.
260: Level: intermediate
262: .seealso: [](ch:lme), `LMEType`
263: @*/
264: PetscErrorCode LMESetType(LME lme,LMEType type)
265: {
266: PetscErrorCode (*r)(LME);
267: PetscBool match;
269: PetscFunctionBegin;
271: PetscAssertPointer(type,2);
273: PetscCall(PetscObjectTypeCompare((PetscObject)lme,type,&match));
274: if (match) PetscFunctionReturn(PETSC_SUCCESS);
276: PetscCall(PetscFunctionListFind(LMEList,type,&r));
277: PetscCheck(r,PetscObjectComm((PetscObject)lme),PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown LME type given: %s",type);
279: PetscTryTypeMethod(lme,destroy);
280: PetscCall(PetscMemzero(lme->ops,sizeof(struct _LMEOps)));
282: lme->setupcalled = 0;
283: PetscCall(PetscObjectChangeTypeName((PetscObject)lme,type));
284: PetscCall((*r)(lme));
285: PetscFunctionReturn(PETSC_SUCCESS);
286: }
288: /*@
289: LMEGetType - Gets the `LME` type as a string from the `LME` object.
291: Not Collective
293: Input Parameter:
294: . lme - the linear matrix equation solver context
296: Output Parameter:
297: . type - name of `LME` method
299: Level: intermediate
301: .seealso: [](ch:lme), `LMESetType()`
302: @*/
303: PetscErrorCode LMEGetType(LME lme,LMEType *type)
304: {
305: PetscFunctionBegin;
307: PetscAssertPointer(type,2);
308: *type = ((PetscObject)lme)->type_name;
309: PetscFunctionReturn(PETSC_SUCCESS);
310: }
312: /*@C
313: LMERegister - Adds a method to the linear matrix equation solver package.
315: Not Collective
317: Input Parameters:
318: + name - name of a new user-defined solver
319: - function - routine to create the solver context
321: Note:
322: `LMERegister()` may be called multiple times to add several user-defined solvers.
324: Example Usage:
325: .vb
326: LMERegister("my_solver",MySolverCreate);
327: .ve
329: Then, your solver can be chosen with the procedural interface via
330: .vb
331: LMESetType(lme,"my_solver")
332: .ve
333: or at runtime via the option `-lme_type my_solver`.
335: Level: advanced
337: .seealso: [](ch:lme), `LMERegisterAll()`
338: @*/
339: PetscErrorCode LMERegister(const char *name,PetscErrorCode (*function)(LME))
340: {
341: PetscFunctionBegin;
342: PetscCall(LMEInitializePackage());
343: PetscCall(PetscFunctionListAdd(&LMEList,name,function));
344: PetscFunctionReturn(PETSC_SUCCESS);
345: }
347: /*@C
348: LMEMonitorRegister - Registers an `LME` monitor routine that may be accessed with
349: `LMEMonitorSetFromOptions()`.
351: Not Collective
353: Input Parameters:
354: + name - name of a new monitor routine
355: . vtype - a `PetscViewerType` for the output
356: . format - a `PetscViewerFormat` for the output
357: . monitor - monitor routine, see `LMEMonitorRegisterFn`
358: . create - creation routine, or `NULL`
359: - destroy - destruction routine, or `NULL`
361: Notes:
362: `LMEMonitorRegister()` may be called multiple times to add several user-defined monitors.
364: The calling sequence for the given function matches the calling sequence of `LMEMonitorFn`
365: functions passed to `LMEMonitorSet()` with the additional requirement that its final argument
366: be a `PetscViewerAndFormat`.
368: Example Usage:
369: .vb
370: LMEMonitorRegister("my_monitor",PETSCVIEWERASCII,PETSC_VIEWER_ASCII_INFO_DETAIL,MyMonitor,NULL,NULL);
371: .ve
373: Then, your monitor can be chosen with the procedural interface via
374: .vb
375: LMEMonitorSetFromOptions(lme,"-lme_monitor_my_monitor","my_monitor",NULL);
376: .ve
377: or at runtime via the option `-lme_monitor_my_monitor`.
379: Level: advanced
381: .seealso: [](ch:lme), `LMEMonitorSet()`, `LMEMonitorRegisterAll()`, `LMEMonitorSetFromOptions()`
382: @*/
383: PetscErrorCode LMEMonitorRegister(const char name[],PetscViewerType vtype,PetscViewerFormat format,LMEMonitorRegisterFn *monitor,LMEMonitorRegisterCreateFn *create,LMEMonitorRegisterDestroyFn *destroy)
384: {
385: char key[PETSC_MAX_PATH_LEN];
387: PetscFunctionBegin;
388: PetscCall(LMEInitializePackage());
389: PetscCall(SlepcMonitorMakeKey_Internal(name,vtype,format,key));
390: PetscCall(PetscFunctionListAdd(&LMEMonitorList,key,monitor));
391: if (create) PetscCall(PetscFunctionListAdd(&LMEMonitorCreateList,key,create));
392: if (destroy) PetscCall(PetscFunctionListAdd(&LMEMonitorDestroyList,key,destroy));
393: PetscFunctionReturn(PETSC_SUCCESS);
394: }
396: /*@
397: LMEReset - Resets the `LME` context to the initial state (prior to setup)
398: and destroys any allocated `Vec`s and `Mat`s.
400: Collective
402: Input Parameter:
403: . lme - the linear matrix equation solver context
405: Level: advanced
407: .seealso: [](ch:lme), `LMEDestroy()`
408: @*/
409: PetscErrorCode LMEReset(LME lme)
410: {
411: PetscFunctionBegin;
413: if (!lme) PetscFunctionReturn(PETSC_SUCCESS);
414: PetscTryTypeMethod(lme,reset);
415: PetscCall(MatDestroy(&lme->A));
416: PetscCall(MatDestroy(&lme->B));
417: PetscCall(MatDestroy(&lme->D));
418: PetscCall(MatDestroy(&lme->E));
419: PetscCall(MatDestroy(&lme->C));
420: PetscCall(MatDestroy(&lme->X));
421: PetscCall(BVDestroy(&lme->V));
422: PetscCall(VecDestroyVecs(lme->nwork,&lme->work));
423: lme->nwork = 0;
424: lme->setupcalled = 0;
425: PetscFunctionReturn(PETSC_SUCCESS);
426: }
428: /*@
429: LMEDestroy - Destroys the `LME` context.
431: Collective
433: Input Parameter:
434: . lme - the linear matrix equation solver context
436: Level: beginner
438: .seealso: [](ch:lme), `LMECreate()`, `LMESetUp()`, `LMESolve()`
439: @*/
440: PetscErrorCode LMEDestroy(LME *lme)
441: {
442: PetscFunctionBegin;
443: if (!*lme) PetscFunctionReturn(PETSC_SUCCESS);
445: if (--((PetscObject)*lme)->refct > 0) { *lme = NULL; PetscFunctionReturn(PETSC_SUCCESS); }
446: PetscCall(LMEReset(*lme));
447: PetscTryTypeMethod(*lme,destroy);
448: PetscCall(LMEMonitorCancel(*lme));
449: PetscCall(PetscHeaderDestroy(lme));
450: PetscFunctionReturn(PETSC_SUCCESS);
451: }
453: /*@
454: LMESetBV - Associates a basis vectors object to the linear matrix equation solver.
456: Collective
458: Input Parameters:
459: + lme - the linear matrix equation solver context
460: - bv - the basis vectors object
462: Note:
463: Use `LMEGetBV()` to retrieve the basis vectors context (for example,
464: to free it at the end of the computations).
466: Level: advanced
468: .seealso: [](ch:lme), `LMEGetBV()`
469: @*/
470: PetscErrorCode LMESetBV(LME lme,BV bv)
471: {
472: PetscFunctionBegin;
475: PetscCheckSameComm(lme,1,bv,2);
476: PetscCall(PetscObjectReference((PetscObject)bv));
477: PetscCall(BVDestroy(&lme->V));
478: lme->V = bv;
479: PetscFunctionReturn(PETSC_SUCCESS);
480: }
482: /*@
483: LMEGetBV - Obtain the basis vectors object associated to the matrix
484: function solver.
486: Not Collective
488: Input Parameter:
489: . lme - the linear matrix equation solver context
491: Output Parameter:
492: . bv - basis vectors context
494: Level: advanced
496: .seealso: [](ch:lme), `LMESetBV()`
497: @*/
498: PetscErrorCode LMEGetBV(LME lme,BV *bv)
499: {
500: PetscFunctionBegin;
502: PetscAssertPointer(bv,2);
503: if (!lme->V) {
504: PetscCall(BVCreate(PetscObjectComm((PetscObject)lme),&lme->V));
505: PetscCall(PetscObjectIncrementTabLevel((PetscObject)lme->V,(PetscObject)lme,0));
506: PetscCall(PetscObjectSetOptions((PetscObject)lme->V,((PetscObject)lme)->options));
507: }
508: *bv = lme->V;
509: PetscFunctionReturn(PETSC_SUCCESS);
510: }