1: /*
2: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3: SLEPc - Scalable Library for Eigenvalue Problem Computations
4: Copyright (c) 2002-2019, 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: The ST interface routines, callable by users
12: */
14: #include <slepc/private/stimpl.h> /*I "slepcst.h" I*/
16: PetscClassId ST_CLASSID = 0;
17: 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;
18: static PetscBool STPackageInitialized = PETSC_FALSE;
20: const char *STMatModes[] = {"COPY","INPLACE","SHELL","STMatMode","ST_MATMODE_",0};
22: /*@C
23: STFinalizePackage - This function destroys everything in the Slepc interface
24: to the ST package. It is called from SlepcFinalize().
26: Level: developer
28: .seealso: SlepcFinalize()
29: @*/
30: PetscErrorCode STFinalizePackage(void) 31: {
35: PetscFunctionListDestroy(&STList);
36: STPackageInitialized = PETSC_FALSE;
37: STRegisterAllCalled = PETSC_FALSE;
38: return(0);
39: }
41: /*@C
42: STInitializePackage - This function initializes everything in the ST package.
43: It is called from PetscDLLibraryRegister() when using dynamic libraries, and
44: on the first call to STCreate() when using static libraries.
46: Level: developer
48: .seealso: SlepcInitialize()
49: @*/
50: PetscErrorCode STInitializePackage(void) 51: {
52: char logList[256];
53: PetscBool opt,pkg;
57: if (STPackageInitialized) return(0);
58: STPackageInitialized = PETSC_TRUE;
59: /* Register Classes */
60: PetscClassIdRegister("Spectral Transform",&ST_CLASSID);
61: /* Register Constructors */
62: STRegisterAll();
63: /* Register Events */
64: PetscLogEventRegister("STSetUp",ST_CLASSID,&ST_SetUp);
65: PetscLogEventRegister("STApply",ST_CLASSID,&ST_Apply);
66: PetscLogEventRegister("STApplyTranspose",ST_CLASSID,&ST_ApplyTranspose);
67: PetscLogEventRegister("STMatSetUp",ST_CLASSID,&ST_MatSetUp);
68: PetscLogEventRegister("STMatMult",ST_CLASSID,&ST_MatMult);
69: PetscLogEventRegister("STMatMultTranspose",ST_CLASSID,&ST_MatMultTranspose);
70: PetscLogEventRegister("STMatSolve",ST_CLASSID,&ST_MatSolve);
71: PetscLogEventRegister("STMatSolveTranspose",ST_CLASSID,&ST_MatSolveTranspose);
72: /* Process info exclusions */
73: PetscOptionsGetString(NULL,NULL,"-info_exclude",logList,sizeof(logList),&opt);
74: if (opt) {
75: PetscStrInList("st",logList,',',&pkg);
76: if (pkg) { PetscInfoDeactivateClass(ST_CLASSID); }
77: }
78: /* Process summary exclusions */
79: PetscOptionsGetString(NULL,NULL,"-log_exclude",logList,sizeof(logList),&opt);
80: if (opt) {
81: PetscStrInList("st",logList,',',&pkg);
82: if (pkg) { PetscLogEventDeactivateClass(ST_CLASSID); }
83: }
84: /* Register package finalizer */
85: PetscRegisterFinalize(STFinalizePackage);
86: return(0);
87: }
89: /*@
90: STReset - Resets the ST context to the initial state (prior to setup)
91: and destroys any allocated Vecs and Mats.
93: Collective on ST 95: Input Parameter:
96: . st - the spectral transformation context
98: Level: advanced
100: .seealso: STDestroy()
101: @*/
102: PetscErrorCode STReset(ST st)103: {
108: if (!st) return(0);
109: if (st->ops->reset) { (*st->ops->reset)(st); }
110: if (st->ksp) { KSPReset(st->ksp); }
111: MatDestroyMatrices(PetscMax(2,st->nmat),&st->T);
112: MatDestroyMatrices(PetscMax(2,st->nmat),&st->A);
113: PetscFree(st->Astate);
114: MatDestroy(&st->P);
115: VecDestroyVecs(st->nwork,&st->work);
116: st->nwork = 0;
117: VecDestroy(&st->wb);
118: VecDestroy(&st->D);
119: st->state = ST_STATE_INITIAL;
120: return(0);
121: }
123: /*@
124: STDestroy - Destroys ST context that was created with STCreate().
126: Collective on ST128: Input Parameter:
129: . st - the spectral transformation context
131: Level: beginner
133: .seealso: STCreate(), STSetUp()
134: @*/
135: PetscErrorCode STDestroy(ST *st)136: {
140: if (!*st) return(0);
142: if (--((PetscObject)(*st))->refct > 0) { *st = 0; return(0); }
143: STReset(*st);
144: if ((*st)->ops->destroy) { (*(*st)->ops->destroy)(*st); }
145: KSPDestroy(&(*st)->ksp);
146: PetscHeaderDestroy(st);
147: return(0);
148: }
150: /*@
151: STCreate - Creates a spectral transformation context.
153: Collective on MPI_Comm
155: Input Parameter:
156: . comm - MPI communicator
158: Output Parameter:
159: . st - location to put the spectral transformation context
161: Level: beginner
163: .seealso: STSetUp(), STApply(), STDestroy(), ST164: @*/
165: PetscErrorCode STCreate(MPI_Comm comm,ST *newst)166: {
168: ST st;
172: *newst = 0;
173: STInitializePackage();
174: SlepcHeaderCreate(st,ST_CLASSID,"ST","Spectral Transformation","ST",comm,STDestroy,STView);
176: st->A = NULL;
177: st->Astate = NULL;
178: st->T = NULL;
179: st->P = NULL;
180: st->nmat = 0;
181: st->sigma = 0.0;
182: st->sigma_set = PETSC_FALSE;
183: st->defsigma = 0.0;
184: st->shift_matrix = ST_MATMODE_COPY;
185: st->str = DIFFERENT_NONZERO_PATTERN;
186: st->transform = PETSC_FALSE;
188: st->ksp = NULL;
189: st->nwork = 0;
190: st->work = NULL;
191: st->D = NULL;
192: st->wb = NULL;
193: st->data = NULL;
194: st->state = ST_STATE_INITIAL;
196: *newst = st;
197: return(0);
198: }
200: /*@
201: STSetMatrices - Sets the matrices associated with the eigenvalue problem.
203: Collective on ST and Mat
205: Input Parameters:
206: + st - the spectral transformation context
207: . n - number of matrices in array A
208: - A - the array of matrices associated with the eigensystem
210: Notes:
211: It must be called before STSetUp(). If it is called again after STSetUp() then
212: the ST object is reset.
214: Level: intermediate
216: .seealso: STGetMatrix(), STGetNumMatrices(), STSetUp(), STReset()
217: @*/
218: PetscErrorCode STSetMatrices(ST st,PetscInt n,Mat A[])219: {
220: PetscInt i;
222: PetscBool same=PETSC_TRUE;
227: if (n <= 0) SETERRQ1(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_OUTOFRANGE,"Must have one or more matrices, you have %D",n);
230: if (st->state) {
231: if (n!=st->nmat) same = PETSC_FALSE;
232: for (i=0;same&&i<n;i++) {
233: if (A[i]!=st->A[i]) same = PETSC_FALSE;
234: }
235: if (!same) { STReset(st); }
236: } else same = PETSC_FALSE;
237: if (!same) {
238: MatDestroyMatrices(PetscMax(2,st->nmat),&st->A);
239: PetscCalloc1(PetscMax(2,n),&st->A);
240: PetscLogObjectMemory((PetscObject)st,PetscMax(2,n)*sizeof(Mat));
241: PetscFree(st->Astate);
242: PetscMalloc1(PetscMax(2,n),&st->Astate);
243: PetscLogObjectMemory((PetscObject)st,PetscMax(2,n)*sizeof(PetscInt));
244: }
245: for (i=0;i<n;i++) {
247: PetscObjectReference((PetscObject)A[i]);
248: MatDestroy(&st->A[i]);
249: st->A[i] = A[i];
250: st->Astate[i] = ((PetscObject)A[i])->state;
251: }
252: if (n==1) {
253: st->A[1] = NULL;
254: st->Astate[1] = 0;
255: }
256: st->nmat = n;
257: if (same) st->state = ST_STATE_UPDATED;
258: else st->state = ST_STATE_INITIAL;
259: return(0);
260: }
262: /*@
263: STGetMatrix - Gets the matrices associated with the original eigensystem.
265: Not collective, though parallel Mats are returned if the ST is parallel
267: Input Parameter:
268: + st - the spectral transformation context
269: - k - the index of the requested matrix (starting in 0)
271: Output Parameters:
272: . A - the requested matrix
274: Level: intermediate
276: .seealso: STSetMatrices(), STGetNumMatrices()
277: @*/
278: PetscErrorCode STGetMatrix(ST st,PetscInt k,Mat *A)279: {
284: STCheckMatrices(st,1);
285: if (k<0 || k>=st->nmat) SETERRQ1(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_OUTOFRANGE,"k must be between 0 and %D",st->nmat-1);
286: if (((PetscObject)st->A[k])->state!=st->Astate[k]) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_SUP,"Cannot retrieve original matrices (have been modified)");
287: *A = st->A[k];
288: return(0);
289: }
291: /*@
292: STGetMatrixTransformed - Gets the matrices associated with the transformed eigensystem.
294: Not collective, though parallel Mats are returned if the ST is parallel
296: Input Parameter:
297: + st - the spectral transformation context
298: - k - the index of the requested matrix (starting in 0)
300: Output Parameters:
301: . T - the requested matrix
303: Level: developer
305: .seealso: STGetMatrix(), STGetNumMatrices()
306: @*/
307: PetscErrorCode STGetMatrixTransformed(ST st,PetscInt k,Mat *T)308: {
313: STCheckMatrices(st,1);
314: if (k<0 || k>=st->nmat) SETERRQ1(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_OUTOFRANGE,"k must be between 0 and %D",st->nmat-1);
315: if (!st->T) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_POINTER,"There are no transformed matrices");
316: *T = st->T[k];
317: return(0);
318: }
320: /*@
321: STGetNumMatrices - Returns the number of matrices stored in the ST.
323: Not collective
325: Input Parameter:
326: . st - the spectral transformation context
328: Output Parameters:
329: . n - the number of matrices passed in STSetMatrices()
331: Level: intermediate
333: .seealso: STSetMatrices()
334: @*/
335: PetscErrorCode STGetNumMatrices(ST st,PetscInt *n)336: {
340: *n = st->nmat;
341: return(0);
342: }
344: /*@
345: STResetMatrixState - Resets the stored state of the matrices in the ST.
347: Logically Collective on ST349: Input Parameter:
350: . st - the spectral transformation context
352: Note:
353: This is useful in solvers where the user matrices are modified during
354: the computation, as in nonlinear inverse iteration. The effect is that
355: STGetMatrix() will retrieve the modified matrices as if they were
356: the matrices originally provided by the user.
358: Level: developer
360: .seealso: STGetMatrix(), EPSPowerSetNonlinear()
361: @*/
362: PetscErrorCode STResetMatrixState(ST st)363: {
364: PetscInt i;
368: for (i=0;i<st->nmat;i++) st->Astate[i] = ((PetscObject)st->A[i])->state;
369: return(0);
370: }
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: {
400: if (st->state==ST_STATE_SETUP && st->sigma != shift) {
401: if (st->ops->setshift) {
402: (*st->ops->setshift)(st,shift);
403: }
404: }
405: st->sigma = shift;
406: st->sigma_set = PETSC_TRUE;
407: return(0);
408: }
410: /*@
411: STGetShift - Gets the shift associated with the spectral transformation.
413: Not Collective
415: Input Parameter:
416: . st - the spectral transformation context
418: Output Parameter:
419: . shift - the value of the shift
421: Level: intermediate
423: .seealso: STSetShift()
424: @*/
425: PetscErrorCode STGetShift(ST st,PetscScalar* shift)426: {
430: *shift = st->sigma;
431: return(0);
432: }
434: /*@
435: STSetDefaultShift - Sets the value of the shift that should be employed if
436: the user did not specify one.
438: Logically Collective on ST440: Input Parameters:
441: + st - the spectral transformation context
442: - defaultshift - the default value of the shift
444: Level: developer
446: .seealso: STSetShift()
447: @*/
448: PetscErrorCode STSetDefaultShift(ST st,PetscScalar defaultshift)449: {
453: st->defsigma = defaultshift;
454: return(0);
455: }
457: /*@
458: STScaleShift - Multiply the shift with a given factor.
460: Logically Collective on ST462: Input Parameters:
463: + st - the spectral transformation context
464: - factor - the scaling factor
466: Note:
467: This function does not update the transformation matrices, as opposed to
468: STSetShift().
470: Level: developer
472: .seealso: STSetShift()
473: @*/
474: PetscErrorCode STScaleShift(ST st,PetscScalar factor)475: {
479: st->sigma *= factor;
480: return(0);
481: }
483: /*@
484: STSetBalanceMatrix - Sets the diagonal matrix to be used for balancing.
486: Collective on ST and Vec
488: Input Parameters:
489: + st - the spectral transformation context
490: - D - the diagonal matrix (represented as a vector)
492: Notes:
493: If this matrix is set, STApply will effectively apply D*OP*D^{-1}.
495: Balancing is usually set via EPSSetBalance, but the advanced user may use
496: this function to bypass the usual balancing methods.
498: Level: developer
500: .seealso: EPSSetBalance(), STApply(), STGetBalanceMatrix()
501: @*/
502: PetscErrorCode STSetBalanceMatrix(ST st,Vec D)503: {
510: PetscObjectReference((PetscObject)D);
511: VecDestroy(&st->D);
512: st->D = D;
513: st->state = ST_STATE_INITIAL;
514: return(0);
515: }
517: /*@
518: STGetBalanceMatrix - Gets the balance matrix used by the spectral transformation.
520: Not collective, but vector is shared by all processors that share the ST522: Input Parameter:
523: . st - the spectral transformation context
525: Output Parameter:
526: . D - the diagonal matrix (represented as a vector)
528: Note:
529: If the matrix was not set, a null pointer will be returned.
531: Level: developer
533: .seealso: STSetBalanceMatrix()
534: @*/
535: PetscErrorCode STGetBalanceMatrix(ST st,Vec *D)536: {
540: *D = st->D;
541: return(0);
542: }
544: /*@C
545: STMatCreateVecs - Get vector(s) compatible with the ST matrices.
547: Collective on ST549: Input Parameter:
550: . st - the spectral transformation context
552: Output Parameters:
553: + right - (optional) vector that the matrix can be multiplied against
554: - left - (optional) vector that the matrix vector product can be stored in
556: Level: developer
557: @*/
558: PetscErrorCode STMatCreateVecs(ST st,Vec *right,Vec *left)559: {
563: STCheckMatrices(st,1);
564: MatCreateVecs(st->A[0],right,left);
565: return(0);
566: }
568: /*@C
569: STMatCreateVecsEmpty - Get vector(s) compatible with the ST matrices, i.e. with the same
570: parallel layout, but without internal array.
572: Collective on ST574: Input Parameter:
575: . st - the spectral transformation context
577: Output Parameters:
578: + right - (optional) vector that the matrix can be multiplied against
579: - left - (optional) vector that the matrix vector product can be stored in
581: Level: developer
583: .seealso: MatCreateVecsEmpty()
584: @*/
585: PetscErrorCode STMatCreateVecsEmpty(ST st,Vec *right,Vec *left)586: {
590: STCheckMatrices(st,1);
591: MatCreateVecsEmpty(st->A[0],right,left);
592: return(0);
593: }
595: /*@
596: STMatGetSize - Returns the number of rows and columns of the ST matrices.
598: Not Collective
600: Input Parameter:
601: . st - the spectral transformation context
603: Output Parameters:
604: + m - the number of global rows
605: - n - the number of global columns
607: Level: developer
608: @*/
609: PetscErrorCode STMatGetSize(ST st,PetscInt *m,PetscInt *n)610: {
614: STCheckMatrices(st,1);
615: MatGetSize(st->A[0],m,n);
616: return(0);
617: }
619: /*@
620: STMatGetLocalSize - Returns the number of local rows and columns of the ST matrices.
622: Not Collective
624: Input Parameter:
625: . st - the spectral transformation context
627: Output Parameters:
628: + m - the number of local rows
629: - n - the number of local columns
631: Level: developer
632: @*/
633: PetscErrorCode STMatGetLocalSize(ST st,PetscInt *m,PetscInt *n)634: {
638: STCheckMatrices(st,1);
639: MatGetLocalSize(st->A[0],m,n);
640: return(0);
641: }
643: /*@C
644: STSetOptionsPrefix - Sets the prefix used for searching for all
645: ST options in the database.
647: Logically Collective on ST649: Input Parameters:
650: + st - the spectral transformation context
651: - prefix - the prefix string to prepend to all ST option requests
653: Notes:
654: A hyphen (-) must NOT be given at the beginning of the prefix name.
655: The first character of all runtime options is AUTOMATICALLY the
656: hyphen.
658: Level: advanced
660: .seealso: STAppendOptionsPrefix(), STGetOptionsPrefix()
661: @*/
662: PetscErrorCode STSetOptionsPrefix(ST st,const char *prefix)663: {
668: if (!st->ksp) { STGetKSP(st,&st->ksp); }
669: KSPSetOptionsPrefix(st->ksp,prefix);
670: KSPAppendOptionsPrefix(st->ksp,"st_");
671: PetscObjectSetOptionsPrefix((PetscObject)st,prefix);
672: return(0);
673: }
675: /*@C
676: STAppendOptionsPrefix - Appends to the prefix used for searching for all
677: ST options in the database.
679: Logically Collective on ST681: Input Parameters:
682: + st - the spectral transformation context
683: - prefix - the prefix string to prepend to all ST option requests
685: Notes:
686: A hyphen (-) must NOT be given at the beginning of the prefix name.
687: The first character of all runtime options is AUTOMATICALLY the
688: hyphen.
690: Level: advanced
692: .seealso: STSetOptionsPrefix(), STGetOptionsPrefix()
693: @*/
694: PetscErrorCode STAppendOptionsPrefix(ST st,const char *prefix)695: {
700: PetscObjectAppendOptionsPrefix((PetscObject)st,prefix);
701: if (!st->ksp) { STGetKSP(st,&st->ksp); }
702: KSPSetOptionsPrefix(st->ksp,((PetscObject)st)->prefix);
703: KSPAppendOptionsPrefix(st->ksp,"st_");
704: return(0);
705: }
707: /*@C
708: STGetOptionsPrefix - Gets the prefix used for searching for all
709: ST options in the database.
711: Not Collective
713: Input Parameters:
714: . st - the spectral transformation context
716: Output Parameters:
717: . prefix - pointer to the prefix string used, is returned
719: Note:
720: On the Fortran side, the user should pass in a string 'prefix' of
721: sufficient length to hold the prefix.
723: Level: advanced
725: .seealso: STSetOptionsPrefix(), STAppendOptionsPrefix()
726: @*/
727: PetscErrorCode STGetOptionsPrefix(ST st,const char *prefix[])728: {
734: PetscObjectGetOptionsPrefix((PetscObject)st,prefix);
735: return(0);
736: }
738: /*@C
739: STView - Prints the ST data structure.
741: Collective on ST743: Input Parameters:
744: + st - the ST context
745: - viewer - optional visualization context
747: Note:
748: The available visualization contexts include
749: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
750: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
751: output where only the first processor opens
752: the file. All other processors send their
753: data to the first processor to print.
755: The user can open an alternative visualization contexts with
756: PetscViewerASCIIOpen() (output to a specified file).
758: Level: beginner
760: .seealso: EPSView(), PetscViewerASCIIOpen()
761: @*/
762: PetscErrorCode STView(ST st,PetscViewer viewer)763: {
765: STType cstr;
766: const char* pat=NULL;
767: char str[50];
768: PetscBool isascii,isstring,flg;
772: if (!viewer) {
773: PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)st),&viewer);
774: }
778: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
779: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);
780: if (isascii) {
781: PetscObjectPrintClassNamePrefixType((PetscObject)st,viewer);
782: if (st->ops->view) {
783: PetscViewerASCIIPushTab(viewer);
784: (*st->ops->view)(st,viewer);
785: PetscViewerASCIIPopTab(viewer);
786: }
787: SlepcSNPrintfScalar(str,50,st->sigma,PETSC_FALSE);
788: PetscViewerASCIIPrintf(viewer," shift: %s\n",str);
789: PetscViewerASCIIPrintf(viewer," number of matrices: %D\n",st->nmat);
790: switch (st->shift_matrix) {
791: case ST_MATMODE_COPY:
792: break;
793: case ST_MATMODE_INPLACE:
794: PetscViewerASCIIPrintf(viewer," shifting the matrix and unshifting at exit\n");
795: break;
796: case ST_MATMODE_SHELL:
797: PetscViewerASCIIPrintf(viewer," using a shell matrix\n");
798: break;
799: }
800: if (st->nmat>1 && st->shift_matrix != ST_MATMODE_SHELL) {
801: switch (st->str) {
802: case SAME_NONZERO_PATTERN: pat = "same nonzero pattern";break;
803: case DIFFERENT_NONZERO_PATTERN: pat = "different nonzero pattern";break;
804: case SUBSET_NONZERO_PATTERN: pat = "subset nonzero pattern";break;
805: }
806: PetscViewerASCIIPrintf(viewer," all matrices have %s\n",pat);
807: }
808: if (st->transform && st->nmat>2) {
809: PetscViewerASCIIPrintf(viewer," computing transformed matrices\n");
810: }
811: } else if (isstring) {
812: STGetType(st,&cstr);
813: PetscViewerStringSPrintf(viewer," %-7.7s",cstr);
814: if (st->ops->view) { (*st->ops->view)(st,viewer); }
815: }
816: PetscObjectTypeCompareAny((PetscObject)st,&flg,STSHIFT,STSHELL,"");
817: if (st->nmat>1 || !flg) {
818: if (!st->ksp) { STGetKSP(st,&st->ksp); }
819: PetscViewerASCIIPushTab(viewer);
820: KSPView(st->ksp,viewer);
821: PetscViewerASCIIPopTab(viewer);
822: }
823: return(0);
824: }
826: /*@C
827: STRegister - Adds a method to the spectral transformation package.
829: Not collective
831: Input Parameters:
832: + name - name of a new user-defined transformation
833: - function - routine to create method context
835: Notes:
836: STRegister() may be called multiple times to add several user-defined
837: spectral transformations.
839: Sample usage:
840: .vb
841: STRegister("my_transform",MyTransformCreate);
842: .ve
844: Then, your spectral transform can be chosen with the procedural interface via
845: $ STSetType(st,"my_transform")
846: or at runtime via the option
847: $ -st_type my_transform
849: Level: advanced
851: .seealso: STRegisterAll()
852: @*/
853: PetscErrorCode STRegister(const char *name,PetscErrorCode (*function)(ST))854: {
858: STInitializePackage();
859: PetscFunctionListAdd(&STList,name,function);
860: return(0);
861: }