Actual source code: qepbasic.c
1: /*
2: The basic QEP routines, Create, View, etc. are here.
4: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
5: SLEPc - Scalable Library for Eigenvalue Problem Computations
6: Copyright (c) 2002-2010, Universidad Politecnica de Valencia, Spain
8: This file is part of SLEPc.
9:
10: SLEPc is free software: you can redistribute it and/or modify it under the
11: terms of version 3 of the GNU Lesser General Public License as published by
12: the Free Software Foundation.
14: SLEPc is distributed in the hope that it will be useful, but WITHOUT ANY
15: WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16: FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
17: more details.
19: You should have received a copy of the GNU Lesser General Public License
20: along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
21: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
22: */
24: #include private/qepimpl.h
26: PetscFList QEPList = 0;
27: PetscCookie QEP_COOKIE = 0;
28: PetscLogEvent QEP_SetUp = 0, QEP_Solve = 0, QEP_Dense = 0;
29: static PetscTruth QEPPackageInitialized = PETSC_FALSE;
33: /*@C
34: QEPFinalizePackage - This function destroys everything in the Slepc interface to the QEP package. It is
35: called from SlepcFinalize().
37: Level: developer
39: .seealso: SlepcFinalize()
40: @*/
41: PetscErrorCode QEPFinalizePackage(void)
42: {
44: QEPPackageInitialized = PETSC_FALSE;
45: QEPList = 0;
46: return(0);
47: }
51: /*@C
52: QEPInitializePackage - This function initializes everything in the QEP package. It is called
53: from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to QEPCreate()
54: when using static libraries.
56: Input Parameter:
57: path - The dynamic library path, or PETSC_NULL
59: Level: developer
61: .seealso: SlepcInitialize()
62: @*/
63: PetscErrorCode QEPInitializePackage(char *path) {
64: char logList[256];
65: char *className;
66: PetscTruth opt;
70: if (QEPPackageInitialized) return(0);
71: QEPPackageInitialized = PETSC_TRUE;
72: /* Register Classes */
73: PetscCookieRegister("Quadratic Eigenproblem Solver",&QEP_COOKIE);
74: /* Register Constructors */
75: QEPRegisterAll(path);
76: /* Register Events */
77: PetscLogEventRegister("QEPSetUp",QEP_COOKIE,&QEP_SetUp);
78: PetscLogEventRegister("QEPSolve",QEP_COOKIE,&QEP_Solve);
79: PetscLogEventRegister("QEPDense",QEP_COOKIE,&QEP_Dense);
80: /* Process info exclusions */
81: PetscOptionsGetString(PETSC_NULL,"-log_info_exclude",logList,256,&opt);
82: if (opt) {
83: PetscStrstr(logList,"qep",&className);
84: if (className) {
85: PetscInfoDeactivateClass(QEP_COOKIE);
86: }
87: }
88: /* Process summary exclusions */
89: PetscOptionsGetString(PETSC_NULL,"-log_summary_exclude",logList,256,&opt);
90: if (opt) {
91: PetscStrstr(logList,"qep",&className);
92: if (className) {
93: PetscLogEventDeactivateClass(QEP_COOKIE);
94: }
95: }
96: PetscRegisterFinalize(QEPFinalizePackage);
97: return(0);
98: }
102: /*@C
103: QEPView - Prints the QEP data structure.
105: Collective on QEP
107: Input Parameters:
108: + qep - the quadratic eigenproblem solver context
109: - viewer - optional visualization context
111: Options Database Key:
112: . -qep_view - Calls QEPView() at end of QEPSolve()
114: Note:
115: The available visualization contexts include
116: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
117: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
118: output where only the first processor opens
119: the file. All other processors send their
120: data to the first processor to print.
122: The user can open an alternative visualization context with
123: PetscViewerASCIIOpen() - output to a specified file.
125: Level: beginner
127: .seealso: PetscViewerASCIIOpen()
128: @*/
129: PetscErrorCode QEPView(QEP qep,PetscViewer viewer)
130: {
132: const char *type;
133: PetscTruth isascii;
137: if (!viewer) viewer = PETSC_VIEWER_STDOUT_(((PetscObject)qep)->comm);
141: #if defined(PETSC_USE_COMPLEX)
142: #define HERM "hermitian"
143: #else
144: #define HERM "symmetric"
145: #endif
146: PetscTypeCompare((PetscObject)viewer,PETSC_VIEWER_ASCII,&isascii);
147: if (isascii) {
148: PetscViewerASCIIPrintf(viewer,"QEP Object:\n");
149: switch (qep->problem_type) {
150: case QEP_GENERAL: type = "general quadratic eigenvalue problem"; break;
151: case QEP_HERMITIAN: type = HERM " quadratic eigenvalue problem"; break;
152: case QEP_GYROSCOPIC: type = "gyroscopic quadratic eigenvalue problem"; break;
153: case 0: type = "not yet set"; break;
154: default: SETERRQ(1,"Wrong value of qep->problem_type");
155: }
156: PetscViewerASCIIPrintf(viewer," problem type: %s\n",type);
157: QEPGetType(qep,&type);
158: if (type) {
159: PetscViewerASCIIPrintf(viewer," method: %s\n",type);
160: } else {
161: PetscViewerASCIIPrintf(viewer," method: not yet set\n");
162: }
163: PetscViewerASCIIPrintf(viewer," selected portion of the spectrum: ");
164: if (!qep->which) {
165: PetscViewerASCIIPrintf(viewer,"not yet set\n");
166: } else switch (qep->which) {
167: case QEP_LARGEST_MAGNITUDE:
168: PetscViewerASCIIPrintf(viewer,"largest eigenvalues in magnitude\n");
169: break;
170: case QEP_SMALLEST_MAGNITUDE:
171: PetscViewerASCIIPrintf(viewer,"smallest eigenvalues in magnitude\n");
172: break;
173: case QEP_LARGEST_REAL:
174: PetscViewerASCIIPrintf(viewer,"largest real parts\n");
175: break;
176: case QEP_SMALLEST_REAL:
177: PetscViewerASCIIPrintf(viewer,"smallest real parts\n");
178: break;
179: case QEP_LARGEST_IMAGINARY:
180: PetscViewerASCIIPrintf(viewer,"largest imaginary parts\n");
181: break;
182: case QEP_SMALLEST_IMAGINARY:
183: PetscViewerASCIIPrintf(viewer,"smallest imaginary parts\n");
184: break;
185: default: SETERRQ(1,"Wrong value of qep->which");
186: }
187: if (qep->leftvecs) {
188: PetscViewerASCIIPrintf(viewer," computing left eigenvectors also\n");
189: }
190: PetscViewerASCIIPrintf(viewer," number of eigenvalues (nev): %d\n",qep->nev);
191: PetscViewerASCIIPrintf(viewer," number of column vectors (ncv): %d\n",qep->ncv);
192: PetscViewerASCIIPrintf(viewer," maximum dimension of projected problem (mpd): %d\n",qep->mpd);
193: PetscViewerASCIIPrintf(viewer," maximum number of iterations: %d\n", qep->max_it);
194: PetscViewerASCIIPrintf(viewer," tolerance: %g\n",qep->tol);
195: PetscViewerASCIIPrintf(viewer," scaling factor: %g\n",qep->sfactor);
196: if (qep->nini!=0) {
197: PetscViewerASCIIPrintf(viewer," dimension of user-provided initial space: %d\n",PetscAbs(qep->nini));
198: }
199: if (qep->ninil!=0) {
200: PetscViewerASCIIPrintf(viewer," dimension of user-provided initial left space: %d\n",PetscAbs(qep->ninil));
201: }
202: if (qep->ops->view) {
203: PetscViewerASCIIPushTab(viewer);
204: (*qep->ops->view)(qep,viewer);
205: PetscViewerASCIIPopTab(viewer);
206: }
207: PetscViewerASCIIPushTab(viewer);
208: IPView(qep->ip,viewer);
209: PetscViewerASCIIPopTab(viewer);
210: } else {
211: if (qep->ops->view) {
212: (*qep->ops->view)(qep,viewer);
213: }
214: }
215: return(0);
216: }
220: /*@C
221: QEPCreate - Creates the default QEP context.
223: Collective on MPI_Comm
225: Input Parameter:
226: . comm - MPI communicator
228: Output Parameter:
229: . qep - location to put the QEP context
231: Note:
232: The default QEP type is QEPLINEAR
234: Level: beginner
236: .seealso: QEPSetUp(), QEPSolve(), QEPDestroy(), QEP
237: @*/
238: PetscErrorCode QEPCreate(MPI_Comm comm,QEP *outqep)
239: {
241: QEP qep;
245: *outqep = 0;
247: PetscHeaderCreate(qep,_p_QEP,struct _QEPOps,QEP_COOKIE,-1,"QEP",comm,QEPDestroy,QEPView);
248: *outqep = qep;
250: PetscMemzero(qep->ops,sizeof(struct _QEPOps));
252: qep->max_it = 0;
253: qep->nev = 1;
254: qep->ncv = 0;
255: qep->mpd = 0;
256: qep->nini = 0;
257: qep->ninil = 0;
258: qep->tol = 1e-7;
259: qep->sfactor = 0.0;
260: qep->conv_func = QEPDefaultConverged;
261: qep->conv_ctx = PETSC_NULL;
262: qep->which = (QEPWhich)0;
263: qep->which_func = PETSC_NULL;
264: qep->which_ctx = PETSC_NULL;
265: qep->leftvecs = PETSC_FALSE;
266: qep->problem_type = (QEPProblemType)0;
267: qep->V = PETSC_NULL;
268: qep->IS = PETSC_NULL;
269: qep->ISL = PETSC_NULL;
270: qep->T = PETSC_NULL;
271: qep->eigr = PETSC_NULL;
272: qep->eigi = PETSC_NULL;
273: qep->errest = PETSC_NULL;
274: qep->data = PETSC_NULL;
275: qep->nconv = 0;
276: qep->its = 0;
277: qep->perm = PETSC_NULL;
278: qep->matvecs = 0;
279: qep->linits = 0;
280: qep->nwork = 0;
281: qep->work = PETSC_NULL;
282: qep->setupcalled = 0;
283: qep->reason = QEP_CONVERGED_ITERATING;
284: qep->numbermonitors = 0;
285: qep->trackall = PETSC_FALSE;
287: IPCreate(comm,&qep->ip);
288: IPSetOptionsPrefix(qep->ip,((PetscObject)qep)->prefix);
289: IPAppendOptionsPrefix(qep->ip,"qep_");
290: PetscLogObjectParent(qep,qep->ip);
291: PetscPublishAll(qep);
292: return(0);
293: }
294:
297: /*@C
298: QEPSetType - Selects the particular solver to be used in the QEP object.
300: Collective on QEP
302: Input Parameters:
303: + qep - the quadratic eigensolver context
304: - type - a known method
306: Options Database Key:
307: . -qep_type <method> - Sets the method; use -help for a list
308: of available methods
309:
310: Notes:
311: See "slepc/include/slepcqep.h" for available methods. The default
312: is QEPLINEAR.
314: Normally, it is best to use the QEPSetFromOptions() command and
315: then set the QEP type from the options database rather than by using
316: this routine. Using the options database provides the user with
317: maximum flexibility in evaluating the different available methods.
318: The QEPSetType() routine is provided for those situations where it
319: is necessary to set the iterative solver independently of the command
320: line or options database.
322: Level: intermediate
324: .seealso: QEPType
325: @*/
326: PetscErrorCode QEPSetType(QEP qep,const QEPType type)
327: {
328: PetscErrorCode ierr,(*r)(QEP);
329: PetscTruth match;
335: PetscTypeCompare((PetscObject)qep,type,&match);
336: if (match) return(0);
338: if (qep->data) {
339: /* destroy the old private QEP context */
340: (*qep->ops->destroy)(qep);
341: qep->data = 0;
342: }
344: PetscFListFind(QEPList,((PetscObject)qep)->comm,type,(void (**)(void))&r);
346: if (!r) SETERRQ1(1,"Unknown QEP type given: %s",type);
348: qep->setupcalled = 0;
349: PetscMemzero(qep->ops,sizeof(struct _QEPOps));
350: (*r)(qep);
352: PetscObjectChangeTypeName((PetscObject)qep,type);
353: return(0);
354: }
358: /*@C
359: QEPGetType - Gets the QEP type as a string from the QEP object.
361: Not Collective
363: Input Parameter:
364: . qep - the eigensolver context
366: Output Parameter:
367: . name - name of QEP method
369: Level: intermediate
371: .seealso: QEPSetType()
372: @*/
373: PetscErrorCode QEPGetType(QEP qep,const QEPType *type)
374: {
378: *type = ((PetscObject)qep)->type_name;
379: return(0);
380: }
382: /*MC
383: QEPRegisterDynamic - Adds a method to the quadratic eigenproblem solver package.
385: Synopsis:
386: QEPRegisterDynamic(char *name_solver,char *path,char *name_create,PetscErrorCode (*routine_create)(QEP))
388: Not Collective
390: Input Parameters:
391: + name_solver - name of a new user-defined solver
392: . path - path (either absolute or relative) the library containing this solver
393: . name_create - name of routine to create the solver context
394: - routine_create - routine to create the solver context
396: Notes:
397: QEPRegisterDynamic() may be called multiple times to add several user-defined solvers.
399: If dynamic libraries are used, then the fourth input argument (routine_create)
400: is ignored.
402: Sample usage:
403: .vb
404: QEPRegisterDynamic("my_solver",/home/username/my_lib/lib/libO/solaris/mylib.a,
405: "MySolverCreate",MySolverCreate);
406: .ve
408: Then, your solver can be chosen with the procedural interface via
409: $ QEPSetType(qep,"my_solver")
410: or at runtime via the option
411: $ -qep_type my_solver
413: Level: advanced
415: Environmental variables such as ${PETSC_ARCH}, ${SLEPC_DIR},
416: and others of the form ${any_environmental_variable} occuring in pathname will be
417: replaced with appropriate values.
419: .seealso: QEPRegisterDestroy(), QEPRegisterAll()
421: M*/
425: /*@C
426: QEPRegister - See QEPRegisterDynamic()
428: Level: advanced
429: @*/
430: PetscErrorCode QEPRegister(const char *sname,const char *path,const char *name,PetscErrorCode (*function)(QEP))
431: {
433: char fullname[256];
436: PetscFListConcat(path,name,fullname);
437: PetscFListAdd(&QEPList,sname,fullname,(void (*)(void))function);
438: return(0);
439: }
443: /*@
444: QEPRegisterDestroy - Frees the list of QEP methods that were
445: registered by QEPRegisterDynamic().
447: Not Collective
449: Level: advanced
451: .seealso: QEPRegisterDynamic(), QEPRegisterAll()
452: @*/
453: PetscErrorCode QEPRegisterDestroy(void)
454: {
458: PetscFListDestroy(&QEPList);
459: QEPRegisterAll(PETSC_NULL);
460: return(0);
461: }
465: /*@
466: QEPDestroy - Destroys the QEP context.
468: Collective on QEP
470: Input Parameter:
471: . qep - eigensolver context obtained from QEPCreate()
473: Level: beginner
475: .seealso: QEPCreate(), QEPSetUp(), QEPSolve()
476: @*/
477: PetscErrorCode QEPDestroy(QEP qep)
478: {
480: PetscScalar *pV;
481: PetscInt i;
485: if (--((PetscObject)qep)->refct > 0) return(0);
487: /* if memory was published with AMS then destroy it */
488: PetscObjectDepublish(qep);
490: if (qep->ops->destroy) {
491: (*qep->ops->destroy)(qep);
492: }
493:
494: PetscFree(qep->T);
496: if (qep->eigr) {
497: PetscFree(qep->eigr);
498: PetscFree(qep->eigi);
499: PetscFree(qep->perm);
500: PetscFree(qep->errest);
501: VecGetArray(qep->V[0],&pV);
502: for (i=0;i<qep->ncv;i++) {
503: VecDestroy(qep->V[i]);
504: }
505: PetscFree(pV);
506: PetscFree(qep->V);
507: }
509: QEPMonitorCancel(qep);
511: IPDestroy(qep->ip);
512: PetscRandomDestroy(qep->rand);
514: if (qep->M) { MatDestroy(qep->M); }
515: if (qep->C) { MatDestroy(qep->C); }
516: if (qep->K) { MatDestroy(qep->K); }
518: PetscHeaderDestroy(qep);
519: return(0);
520: }
524: /*@
525: QEPSetIP - Associates an inner product object to the quadratic eigensolver.
527: Collective on QEP and IP
529: Input Parameters:
530: + qep - eigensolver context obtained from QEPCreate()
531: - ip - the inner product object
533: Note:
534: Use QEPGetIP() to retrieve the inner product context (for example,
535: to free it at the end of the computations).
537: Level: advanced
539: .seealso: QEPGetIP()
540: @*/
541: PetscErrorCode QEPSetIP(QEP qep,IP ip)
542: {
549: PetscObjectReference((PetscObject)ip);
550: IPDestroy(qep->ip);
551: qep->ip = ip;
552: return(0);
553: }
557: /*@C
558: QEPGetIP - Obtain the inner product object associated
559: to the quadratic eigensolver object.
561: Not Collective
563: Input Parameters:
564: . qep - eigensolver context obtained from QEPCreate()
566: Output Parameter:
567: . ip - inner product context
569: Level: advanced
571: .seealso: QEPSetIP()
572: @*/
573: PetscErrorCode QEPGetIP(QEP qep,IP *ip)
574: {
578: *ip = qep->ip;
579: return(0);
580: }