1: /*
2: The ST (spectral transformation) interface routines, callable by users.
4: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
5: SLEPc - Scalable Library for Eigenvalue Problem Computations
6: Copyright (c) 2002-2016, Universitat Politecnica de Valencia, Spain
8: This file is part of SLEPc.
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 <slepc/private/stimpl.h> /*I "slepcst.h" I*/
26: PetscClassId ST_CLASSID = 0;
27: PetscLogEvent ST_SetUp = 0,ST_Apply = 0,ST_ApplyTranspose = 0,ST_MatSetUp = 0,ST_MatMult = 0,ST_MatMultTranspose = 0,ST_MatSolve = 0,ST_MatSolveTranspose = 0;
28: static PetscBool STPackageInitialized = PETSC_FALSE;
32: /*@C
33: STFinalizePackage - This function destroys everything in the Slepc interface
34: to the ST package. It is called from SlepcFinalize().
36: Level: developer
38: .seealso: SlepcFinalize()
39: @*/
40: PetscErrorCode STFinalizePackage(void) 41: {
45: PetscFunctionListDestroy(&STList);
46: STPackageInitialized = PETSC_FALSE;
47: STRegisterAllCalled = PETSC_FALSE;
48: return(0);
49: }
53: /*@C
54: STInitializePackage - This function initializes everything in the ST package.
55: It is called from PetscDLLibraryRegister() when using dynamic libraries, and
56: on the first call to STCreate() when using static libraries.
58: Level: developer
60: .seealso: SlepcInitialize()
61: @*/
62: PetscErrorCode STInitializePackage(void) 63: {
64: char logList[256];
65: char *className;
66: PetscBool opt;
70: if (STPackageInitialized) return(0);
71: STPackageInitialized = PETSC_TRUE;
72: /* Register Classes */
73: PetscClassIdRegister("Spectral Transform",&ST_CLASSID);
74: /* Register Constructors */
75: STRegisterAll();
76: /* Register Events */
77: PetscLogEventRegister("STSetUp",ST_CLASSID,&ST_SetUp);
78: PetscLogEventRegister("STApply",ST_CLASSID,&ST_Apply);
79: PetscLogEventRegister("STApplyTranspose",ST_CLASSID,&ST_ApplyTranspose);
80: PetscLogEventRegister("STMatSetUp",ST_CLASSID,&ST_MatSetUp);
81: PetscLogEventRegister("STMatMult",ST_CLASSID,&ST_MatMult);
82: PetscLogEventRegister("STMatMultTranspose",ST_CLASSID,&ST_MatMultTranspose);
83: PetscLogEventRegister("STMatSolve",ST_CLASSID,&ST_MatSolve);
84: PetscLogEventRegister("STMatSolveTranspose",ST_CLASSID,&ST_MatSolveTranspose);
85: /* Process info exclusions */
86: PetscOptionsGetString(NULL,NULL,"-info_exclude",logList,256,&opt);
87: if (opt) {
88: PetscStrstr(logList,"st",&className);
89: if (className) {
90: PetscInfoDeactivateClass(ST_CLASSID);
91: }
92: }
93: /* Process summary exclusions */
94: PetscOptionsGetString(NULL,NULL,"-log_exclude",logList,256,&opt);
95: if (opt) {
96: PetscStrstr(logList,"st",&className);
97: if (className) {
98: PetscLogEventDeactivateClass(ST_CLASSID);
99: }
100: }
101: PetscRegisterFinalize(STFinalizePackage);
102: return(0);
103: }
107: /*@
108: STReset - Resets the ST context and removes any allocated objects.
110: Collective on ST112: Input Parameter:
113: . st - the spectral transformation context
115: Level: advanced
117: .seealso: STDestroy()
118: @*/
119: PetscErrorCode STReset(ST st)120: {
125: if (st->ops->reset) { (*st->ops->reset)(st); }
126: if (st->ksp) { KSPReset(st->ksp); }
127: MatDestroyMatrices(PetscMax(2,st->nmat),&st->T);
128: VecDestroy(&st->w);
129: VecDestroy(&st->wb);
130: st->state = ST_STATE_INITIAL;
131: return(0);
132: }
136: /*@
137: STDestroy - Destroys ST context that was created with STCreate().
139: Collective on ST141: Input Parameter:
142: . st - the spectral transformation context
144: Level: beginner
146: .seealso: STCreate(), STSetUp()
147: @*/
148: PetscErrorCode STDestroy(ST *st)149: {
153: if (!*st) return(0);
155: if (--((PetscObject)(*st))->refct > 0) { *st = 0; return(0); }
156: STReset(*st);
157: MatDestroyMatrices(PetscMax(2,(*st)->nmat),&(*st)->A);
158: PetscFree((*st)->Astate);
159: if ((*st)->ops->destroy) { (*(*st)->ops->destroy)(*st); }
160: MatDestroy(&(*st)->P);
161: VecDestroy(&(*st)->D);
162: KSPDestroy(&(*st)->ksp);
163: PetscHeaderDestroy(st);
164: return(0);
165: }
169: /*@
170: STCreate - Creates a spectral transformation context.
172: Collective on MPI_Comm
174: Input Parameter:
175: . comm - MPI communicator
177: Output Parameter:
178: . st - location to put the spectral transformation context
180: Level: beginner
182: .seealso: STSetUp(), STApply(), STDestroy(), ST183: @*/
184: PetscErrorCode STCreate(MPI_Comm comm,ST *newst)185: {
187: ST st;
191: *newst = 0;
192: STInitializePackage();
193: SlepcHeaderCreate(st,ST_CLASSID,"ST","Spectral Transformation","ST",comm,STDestroy,STView);
195: st->A = NULL;
196: st->Astate = NULL;
197: st->T = NULL;
198: st->P = NULL;
199: st->nmat = 0;
200: st->sigma = 0.0;
201: st->sigma_set = PETSC_FALSE;
202: st->defsigma = 0.0;
203: st->shift_matrix = ST_MATMODE_COPY;
204: st->str = DIFFERENT_NONZERO_PATTERN;
205: st->transform = PETSC_FALSE;
207: st->ksp = NULL;
208: st->w = NULL;
209: st->D = NULL;
210: st->wb = NULL;
211: st->data = NULL;
212: st->state = ST_STATE_INITIAL;
214: *newst = st;
215: return(0);
216: }
220: /*@
221: STSetOperators - Sets the matrices associated with the eigenvalue problem.
223: Collective on ST and Mat
225: Input Parameters:
226: + st - the spectral transformation context
227: . n - number of matrices in array A
228: - A - the array of matrices associated with the eigensystem
230: Notes:
231: It must be called before STSetUp(). If it is called again after STSetUp() then
232: the ST object is reset.
234: Level: intermediate
236: .seealso: STGetOperators(), STGetNumMatrices(), STSetUp(), STReset()
237: @*/
238: PetscErrorCode STSetOperators(ST st,PetscInt n,Mat A[])239: {
240: PetscInt i;
242: PetscBool same=PETSC_TRUE;
247: if (n <= 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Must have one or more matrices, you have %D",n);
250: if (st->state) {
251: if (n!=st->nmat) same = PETSC_FALSE;
252: for (i=0;same&&i<n;i++) {
253: if (A[i]!=st->A[i]) same = PETSC_FALSE;
254: }
255: if (!same) { STReset(st); }
256: } else same = PETSC_FALSE;
257: if (!same) {
258: MatDestroyMatrices(PetscMax(2,st->nmat),&st->A);
259: PetscCalloc1(PetscMax(2,n),&st->A);
260: PetscLogObjectMemory((PetscObject)st,PetscMax(2,n)*sizeof(Mat));
261: PetscFree(st->Astate);
262: PetscMalloc(PetscMax(2,n)*sizeof(PetscObjectState),&st->Astate);
263: PetscLogObjectMemory((PetscObject)st,PetscMax(2,n)*sizeof(PetscInt));
264: }
265: for (i=0;i<n;i++) {
267: PetscObjectReference((PetscObject)A[i]);
268: MatDestroy(&st->A[i]);
269: st->A[i] = A[i];
270: st->Astate[i] = ((PetscObject)A[i])->state;
271: }
272: if (n==1) {
273: st->A[1] = NULL;
274: st->Astate[1] = 0;
275: }
276: st->nmat = n;
277: if (same) st->state = ST_STATE_UPDATED;
278: else st->state = ST_STATE_INITIAL;
279: return(0);
280: }
284: /*@
285: STGetOperators - Gets the matrices associated with the original eigensystem.
287: Not collective, though parallel Mats are returned if the ST is parallel
289: Input Parameter:
290: + st - the spectral transformation context
291: - k - the index of the requested matrix (starting in 0)
293: Output Parameters:
294: . A - the requested matrix
296: Level: intermediate
298: .seealso: STSetOperators(), STGetNumMatrices()
299: @*/
300: PetscErrorCode STGetOperators(ST st,PetscInt k,Mat *A)301: {
306: STCheckMatrices(st,1);
307: if (k<0 || k>=st->nmat) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"k must be between 0 and %D",st->nmat-1);
308: if (((PetscObject)st->A[k])->state!=st->Astate[k]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot retrieve original matrices (have been modified)");
309: *A = st->A[k];
310: return(0);
311: }
315: /*@
316: STGetTOperators - Gets the matrices associated with the transformed eigensystem.
318: Not collective, though parallel Mats are returned if the ST is parallel
320: Input Parameter:
321: + st - the spectral transformation context
322: - k - the index of the requested matrix (starting in 0)
324: Output Parameters:
325: . T - the requested matrix
327: Level: developer
329: .seealso: STGetOperators(), STGetNumMatrices()
330: @*/
331: PetscErrorCode STGetTOperators(ST st,PetscInt k,Mat *T)332: {
337: STCheckMatrices(st,1);
338: if (k<0 || k>=st->nmat) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"k must be between 0 and %D",st->nmat-1);
339: if (!st->T) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_POINTER,"There are no transformed matrices");
340: *T = st->T[k];
341: return(0);
342: }
346: /*@
347: STGetNumMatrices - Returns the number of matrices stored in the ST.
349: Not collective
351: Input Parameter:
352: . st - the spectral transformation context
354: Output Parameters:
355: . n - the number of matrices passed in STSetOperators()
357: Level: intermediate
359: .seealso: STSetOperators()
360: @*/
361: PetscErrorCode STGetNumMatrices(ST st,PetscInt *n)362: {
366: *n = st->nmat;
367: return(0);
368: }
372: /*@
373: STSetShift - Sets the shift associated with the spectral transformation.
375: Logically Collective on ST377: Input Parameters:
378: + st - the spectral transformation context
379: - shift - the value of the shift
381: Notes:
382: In some spectral transformations, changing the shift may have associated
383: a lot of work, for example recomputing a factorization.
385: This function is normally not directly called by users, since the shift is
386: indirectly set by EPSSetTarget().
388: Level: intermediate
390: .seealso: EPSSetTarget(), STGetShift(), STSetDefaultShift()
391: @*/
392: PetscErrorCode STSetShift(ST st,PetscScalar shift)393: {
399: if (st->state==ST_STATE_SETUP && st->sigma != shift) {
400: if (st->ops->setshift) {
401: (*st->ops->setshift)(st,shift);
402: }
403: }
404: st->sigma = shift;
405: st->sigma_set = PETSC_TRUE;
406: return(0);
407: }
411: /*@
412: STGetShift - Gets the shift associated with the spectral transformation.
414: Not Collective
416: Input Parameter:
417: . st - the spectral transformation context
419: Output Parameter:
420: . shift - the value of the shift
422: Level: intermediate
424: .seealso: STSetShift()
425: @*/
426: PetscErrorCode STGetShift(ST st,PetscScalar* shift)427: {
431: *shift = st->sigma;
432: return(0);
433: }
437: /*@
438: STSetDefaultShift - Sets the value of the shift that should be employed if
439: the user did not specify one.
441: Logically Collective on ST443: Input Parameters:
444: + st - the spectral transformation context
445: - defaultshift - the default value of the shift
447: Level: developer
449: .seealso: STSetShift()
450: @*/
451: PetscErrorCode STSetDefaultShift(ST st,PetscScalar defaultshift)452: {
456: st->defsigma = defaultshift;
457: return(0);
458: }
462: /*@
463: STScaleShift - Multiply the shift with a given factor.
465: Logically Collective on ST467: Input Parameters:
468: + st - the spectral transformation context
469: - factor - the scaling factor
471: Note:
472: This function does not update the transformation matrices, as opposed to
473: STSetShift().
475: Level: developer
477: .seealso: STSetShift()
478: @*/
479: PetscErrorCode STScaleShift(ST st,PetscScalar factor)480: {
484: st->sigma *= factor;
485: return(0);
486: }
490: /*@
491: STSetBalanceMatrix - Sets the diagonal matrix to be used for balancing.
493: Collective on ST and Vec
495: Input Parameters:
496: + st - the spectral transformation context
497: - D - the diagonal matrix (represented as a vector)
499: Notes:
500: If this matrix is set, STApply will effectively apply D*OP*D^{-1}.
502: Balancing is usually set via EPSSetBalance, but the advanced user may use
503: this function to bypass the usual balancing methods.
505: Level: developer
507: .seealso: EPSSetBalance(), STApply(), STGetBalanceMatrix()
508: @*/
509: PetscErrorCode STSetBalanceMatrix(ST st,Vec D)510: {
517: PetscObjectReference((PetscObject)D);
518: VecDestroy(&st->D);
519: st->D = D;
520: st->state = ST_STATE_INITIAL;
521: return(0);
522: }
526: /*@
527: STGetBalanceMatrix - Gets the balance matrix used by the spectral transformation.
529: Not collective, but vector is shared by all processors that share the ST531: Input Parameter:
532: . st - the spectral transformation context
534: Output Parameter:
535: . D - the diagonal matrix (represented as a vector)
537: Note:
538: If the matrix was not set, a null pointer will be returned.
540: Level: developer
542: .seealso: STSetBalanceMatrix()
543: @*/
544: PetscErrorCode STGetBalanceMatrix(ST st,Vec *D)545: {
549: *D = st->D;
550: return(0);
551: }
555: /*@C
556: STMatCreateVecs - Get vector(s) compatible with the ST matrices.
558: Collective on ST560: Input Parameter:
561: . st - the spectral transformation context
563: Output Parameters:
564: + right - (optional) vector that the matrix can be multiplied against
565: - left - (optional) vector that the matrix vector product can be stored in
567: Level: developer
568: @*/
569: PetscErrorCode STMatCreateVecs(ST st,Vec *right,Vec *left)570: {
574: STCheckMatrices(st,1);
575: MatCreateVecs(st->A[0],right,left);
576: return(0);
577: }
581: /*@
582: STMatGetSize - Returns the number of rows and columns of the ST matrices.
584: Not Collective
586: Input Parameter:
587: . st - the spectral transformation context
589: Output Parameters:
590: + m - the number of global rows
591: - n - the number of global columns
593: Level: developer
594: @*/
595: PetscErrorCode STMatGetSize(ST st,PetscInt *m,PetscInt *n)596: {
600: STCheckMatrices(st,1);
601: MatGetSize(st->A[0],m,n);
602: return(0);
603: }
607: /*@
608: STMatGetLocalSize - Returns the number of local rows and columns of the ST matrices.
610: Not Collective
612: Input Parameter:
613: . st - the spectral transformation context
615: Output Parameters:
616: + m - the number of local rows
617: - n - the number of local columns
619: Level: developer
620: @*/
621: PetscErrorCode STMatGetLocalSize(ST st,PetscInt *m,PetscInt *n)622: {
626: STCheckMatrices(st,1);
627: MatGetLocalSize(st->A[0],m,n);
628: return(0);
629: }
633: /*@C
634: STSetOptionsPrefix - Sets the prefix used for searching for all
635: ST options in the database.
637: Logically Collective on ST639: Input Parameters:
640: + st - the spectral transformation context
641: - prefix - the prefix string to prepend to all ST option requests
643: Notes:
644: A hyphen (-) must NOT be given at the beginning of the prefix name.
645: The first character of all runtime options is AUTOMATICALLY the
646: hyphen.
648: Level: advanced
650: .seealso: STAppendOptionsPrefix(), STGetOptionsPrefix()
651: @*/
652: PetscErrorCode STSetOptionsPrefix(ST st,const char *prefix)653: {
658: if (!st->ksp) { STGetKSP(st,&st->ksp); }
659: KSPSetOptionsPrefix(st->ksp,prefix);
660: KSPAppendOptionsPrefix(st->ksp,"st_");
661: PetscObjectSetOptionsPrefix((PetscObject)st,prefix);
662: return(0);
663: }
667: /*@C
668: STAppendOptionsPrefix - Appends to the prefix used for searching for all
669: ST options in the database.
671: Logically Collective on ST673: Input Parameters:
674: + st - the spectral transformation context
675: - prefix - the prefix string to prepend to all ST option requests
677: Notes:
678: A hyphen (-) must NOT be given at the beginning of the prefix name.
679: The first character of all runtime options is AUTOMATICALLY the
680: hyphen.
682: Level: advanced
684: .seealso: STSetOptionsPrefix(), STGetOptionsPrefix()
685: @*/
686: PetscErrorCode STAppendOptionsPrefix(ST st,const char *prefix)687: {
692: PetscObjectAppendOptionsPrefix((PetscObject)st,prefix);
693: if (!st->ksp) { STGetKSP(st,&st->ksp); }
694: KSPSetOptionsPrefix(st->ksp,((PetscObject)st)->prefix);
695: KSPAppendOptionsPrefix(st->ksp,"st_");
696: return(0);
697: }
701: /*@C
702: STGetOptionsPrefix - Gets the prefix used for searching for all
703: ST options in the database.
705: Not Collective
707: Input Parameters:
708: . st - the spectral transformation context
710: Output Parameters:
711: . prefix - pointer to the prefix string used, is returned
713: Note:
714: On the Fortran side, the user should pass in a string 'prefix' of
715: sufficient length to hold the prefix.
717: Level: advanced
719: .seealso: STSetOptionsPrefix(), STAppendOptionsPrefix()
720: @*/
721: PetscErrorCode STGetOptionsPrefix(ST st,const char *prefix[])722: {
728: PetscObjectGetOptionsPrefix((PetscObject)st,prefix);
729: return(0);
730: }
734: /*@C
735: STView - Prints the ST data structure.
737: Collective on ST739: Input Parameters:
740: + st - the ST context
741: - viewer - optional visualization context
743: Note:
744: The available visualization contexts include
745: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
746: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
747: output where only the first processor opens
748: the file. All other processors send their
749: data to the first processor to print.
751: The user can open an alternative visualization contexts with
752: PetscViewerASCIIOpen() (output to a specified file).
754: Level: beginner
756: .seealso: EPSView(), PetscViewerASCIIOpen()
757: @*/
758: PetscErrorCode STView(ST st,PetscViewer viewer)759: {
761: STType cstr;
762: const char* pat;
763: char str[50];
764: PetscBool isascii,isstring,flg;
768: if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)st));
772: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
773: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);
774: if (isascii) {
775: PetscObjectPrintClassNamePrefixType((PetscObject)st,viewer);
776: if (st->ops->view) {
777: PetscViewerASCIIPushTab(viewer);
778: (*st->ops->view)(st,viewer);
779: PetscViewerASCIIPopTab(viewer);
780: }
781: SlepcSNPrintfScalar(str,50,st->sigma,PETSC_FALSE);
782: PetscViewerASCIIPrintf(viewer," shift: %s\n",str);
783: PetscViewerASCIIPrintf(viewer," number of matrices: %D\n",st->nmat);
784: switch (st->shift_matrix) {
785: case ST_MATMODE_COPY:
786: break;
787: case ST_MATMODE_INPLACE:
788: PetscViewerASCIIPrintf(viewer," shifting the matrix and unshifting at exit\n");
789: break;
790: case ST_MATMODE_SHELL:
791: PetscViewerASCIIPrintf(viewer," using a shell matrix\n");
792: break;
793: }
794: if (st->nmat>1 && st->shift_matrix != ST_MATMODE_SHELL) {
795: switch (st->str) {
796: case SAME_NONZERO_PATTERN: pat = "same nonzero pattern";break;
797: case DIFFERENT_NONZERO_PATTERN: pat = "different nonzero pattern";break;
798: case SUBSET_NONZERO_PATTERN: pat = "subset nonzero pattern";break;
799: default: SETERRQ(PetscObjectComm((PetscObject)st),1,"Wrong structure flag");
800: }
801: PetscViewerASCIIPrintf(viewer," all matrices have %s\n",pat);
802: }
803: if (st->transform && st->nmat>2) {
804: PetscViewerASCIIPrintf(viewer," computing transformed matrices\n");
805: }
806: } else if (isstring) {
807: STGetType(st,&cstr);
808: PetscViewerStringSPrintf(viewer," %-7.7s",cstr);
809: if (st->ops->view) { (*st->ops->view)(st,viewer); }
810: }
811: PetscObjectTypeCompare((PetscObject)st,STSHIFT,&flg);
812: if (st->nmat>1 || !flg) {
813: if (!st->ksp) { STGetKSP(st,&st->ksp); }
814: PetscViewerASCIIPushTab(viewer);
815: KSPView(st->ksp,viewer);
816: PetscViewerASCIIPopTab(viewer);
817: }
818: return(0);
819: }
823: /*@C
824: STRegister - Adds a method to the spectral transformation package.
826: Not collective
828: Input Parameters:
829: + name - name of a new user-defined transformation
830: - function - routine to create method context
832: Notes:
833: STRegister() may be called multiple times to add several user-defined
834: spectral transformations.
836: Sample usage:
837: .vb
838: STRegister("my_transform",MyTransformCreate);
839: .ve
841: Then, your spectral transform can be chosen with the procedural interface via
842: $ STSetType(st,"my_transform")
843: or at runtime via the option
844: $ -st_type my_transform
846: Level: advanced
848: .seealso: STRegisterAll()
849: @*/
850: PetscErrorCode STRegister(const char *name,PetscErrorCode (*function)(ST))851: {
855: PetscFunctionListAdd(&STList,name,function);
856: return(0);
857: }