Actual source code: stfunc.c
slepc-main 2024-11-09
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: The ST interface routines, callable by users
12: */
14: #include <slepc/private/stimpl.h>
16: PetscClassId ST_CLASSID = 0;
17: PetscLogEvent ST_SetUp = 0,ST_ComputeOperator = 0,ST_Apply = 0,ST_ApplyTranspose = 0,ST_ApplyHermitianTranspose = 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_",NULL};
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: {
32: PetscFunctionBegin;
33: PetscCall(PetscFunctionListDestroy(&STList));
34: STPackageInitialized = PETSC_FALSE;
35: STRegisterAllCalled = PETSC_FALSE;
36: PetscFunctionReturn(PETSC_SUCCESS);
37: }
39: /*@C
40: STInitializePackage - This function initializes everything in the ST package.
41: It is called from PetscDLLibraryRegister() when using dynamic libraries, and
42: on the first call to STCreate() when using static libraries.
44: Level: developer
46: .seealso: SlepcInitialize()
47: @*/
48: PetscErrorCode STInitializePackage(void)
49: {
50: char logList[256];
51: PetscBool opt,pkg;
52: PetscClassId classids[1];
54: PetscFunctionBegin;
55: if (STPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS);
56: STPackageInitialized = PETSC_TRUE;
57: /* Register Classes */
58: PetscCall(PetscClassIdRegister("Spectral Transform",&ST_CLASSID));
59: /* Register Constructors */
60: PetscCall(STRegisterAll());
61: /* Register Events */
62: PetscCall(PetscLogEventRegister("STSetUp",ST_CLASSID,&ST_SetUp));
63: PetscCall(PetscLogEventRegister("STComputeOperatr",ST_CLASSID,&ST_ComputeOperator));
64: PetscCall(PetscLogEventRegister("STApply",ST_CLASSID,&ST_Apply));
65: PetscCall(PetscLogEventRegister("STApplyTranspose",ST_CLASSID,&ST_ApplyTranspose));
66: PetscCall(PetscLogEventRegister("STApplyHermTrans",ST_CLASSID,&ST_ApplyHermitianTranspose));
67: PetscCall(PetscLogEventRegister("STMatSetUp",ST_CLASSID,&ST_MatSetUp));
68: PetscCall(PetscLogEventRegister("STMatMult",ST_CLASSID,&ST_MatMult));
69: PetscCall(PetscLogEventRegister("STMatMultTranspose",ST_CLASSID,&ST_MatMultTranspose));
70: PetscCall(PetscLogEventRegister("STMatSolve",ST_CLASSID,&ST_MatSolve));
71: PetscCall(PetscLogEventRegister("STMatSolveTranspose",ST_CLASSID,&ST_MatSolveTranspose));
72: /* Process Info */
73: classids[0] = ST_CLASSID;
74: PetscCall(PetscInfoProcessClass("st",1,&classids[0]));
75: /* Process summary exclusions */
76: PetscCall(PetscOptionsGetString(NULL,NULL,"-log_exclude",logList,sizeof(logList),&opt));
77: if (opt) {
78: PetscCall(PetscStrInList("st",logList,',',&pkg));
79: if (pkg) PetscCall(PetscLogEventDeactivateClass(ST_CLASSID));
80: }
81: /* Register package finalizer */
82: PetscCall(PetscRegisterFinalize(STFinalizePackage));
83: PetscFunctionReturn(PETSC_SUCCESS);
84: }
86: /*@
87: STReset - Resets the ST context to the initial state (prior to setup)
88: and destroys any allocated Vecs and Mats.
90: Collective
92: Input Parameter:
93: . st - the spectral transformation context
95: Level: advanced
97: .seealso: STDestroy()
98: @*/
99: PetscErrorCode STReset(ST st)
100: {
101: PetscFunctionBegin;
103: if (!st) PetscFunctionReturn(PETSC_SUCCESS);
104: STCheckNotSeized(st,1);
105: PetscTryTypeMethod(st,reset);
106: if (st->ksp) PetscCall(KSPReset(st->ksp));
107: PetscCall(MatDestroyMatrices(PetscMax(2,st->nmat),&st->T));
108: PetscCall(MatDestroyMatrices(PetscMax(2,st->nmat),&st->A));
109: st->nmat = 0;
110: PetscCall(PetscFree(st->Astate));
111: PetscCall(MatDestroy(&st->Op));
112: PetscCall(MatDestroy(&st->P));
113: PetscCall(MatDestroy(&st->Pmat));
114: PetscCall(MatDestroyMatrices(st->nsplit,&st->Psplit));
115: st->nsplit = 0;
116: PetscCall(VecDestroyVecs(st->nwork,&st->work));
117: st->nwork = 0;
118: PetscCall(VecDestroy(&st->wb));
119: PetscCall(VecDestroy(&st->wht));
120: PetscCall(VecDestroy(&st->D));
121: st->state = ST_STATE_INITIAL;
122: st->opready = PETSC_FALSE;
123: PetscFunctionReturn(PETSC_SUCCESS);
124: }
126: /*@
127: STDestroy - Destroys ST context that was created with STCreate().
129: Collective
131: Input Parameter:
132: . st - the spectral transformation context
134: Level: beginner
136: .seealso: STCreate(), STSetUp()
137: @*/
138: PetscErrorCode STDestroy(ST *st)
139: {
140: PetscFunctionBegin;
141: if (!*st) PetscFunctionReturn(PETSC_SUCCESS);
143: if (--((PetscObject)*st)->refct > 0) { *st = NULL; PetscFunctionReturn(PETSC_SUCCESS); }
144: PetscCall(STReset(*st));
145: PetscTryTypeMethod(*st,destroy);
146: PetscCall(KSPDestroy(&(*st)->ksp));
147: PetscCall(PetscHeaderDestroy(st));
148: PetscFunctionReturn(PETSC_SUCCESS);
149: }
151: /*@
152: STCreate - Creates a spectral transformation context.
154: Collective
156: Input Parameter:
157: . comm - MPI communicator
159: Output Parameter:
160: . newst - location to put the spectral transformation context
162: Level: beginner
164: .seealso: STSetUp(), STApply(), STDestroy(), ST
165: @*/
166: PetscErrorCode STCreate(MPI_Comm comm,ST *newst)
167: {
168: ST st;
170: PetscFunctionBegin;
171: PetscAssertPointer(newst,2);
172: PetscCall(STInitializePackage());
173: PetscCall(SlepcHeaderCreate(st,ST_CLASSID,"ST","Spectral Transformation","ST",comm,STDestroy,STView));
175: st->A = NULL;
176: st->nmat = 0;
177: st->sigma = 0.0;
178: st->defsigma = 0.0;
179: st->matmode = ST_MATMODE_COPY;
180: st->str = UNKNOWN_NONZERO_PATTERN;
181: st->transform = PETSC_FALSE;
182: st->structured = PETSC_FALSE;
183: st->D = NULL;
184: st->Pmat = NULL;
185: st->Pmat_set = PETSC_FALSE;
186: st->Psplit = NULL;
187: st->nsplit = 0;
188: st->strp = UNKNOWN_NONZERO_PATTERN;
190: st->ksp = NULL;
191: st->usesksp = PETSC_FALSE;
192: st->nwork = 0;
193: st->work = NULL;
194: st->wb = NULL;
195: st->wht = NULL;
196: st->state = ST_STATE_INITIAL;
197: st->Astate = NULL;
198: st->T = NULL;
199: st->Op = NULL;
200: st->opseized = PETSC_FALSE;
201: st->opready = PETSC_FALSE;
202: st->P = NULL;
203: st->M = NULL;
204: st->sigma_set = PETSC_FALSE;
205: st->asymm = PETSC_FALSE;
206: st->aherm = PETSC_FALSE;
207: st->data = NULL;
209: *newst = st;
210: PetscFunctionReturn(PETSC_SUCCESS);
211: }
213: /*
214: Checks whether the ST matrices are all symmetric or hermitian.
215: */
216: static inline PetscErrorCode STMatIsSymmetricKnown(ST st,PetscBool *symm,PetscBool *herm)
217: {
218: PetscInt i;
219: PetscBool sbaij=PETSC_FALSE,set,flg=PETSC_FALSE;
221: PetscFunctionBegin;
222: /* check if problem matrices are all sbaij */
223: for (i=0;i<st->nmat;i++) {
224: PetscCall(PetscObjectTypeCompareAny((PetscObject)st->A[i],&sbaij,MATSEQSBAIJ,MATMPISBAIJ,""));
225: if (!sbaij) break;
226: }
227: /* check if user has set the symmetric flag */
228: *symm = PETSC_TRUE;
229: for (i=0;i<st->nmat;i++) {
230: PetscCall(MatIsSymmetricKnown(st->A[i],&set,&flg));
231: if (!set || !flg) { *symm = PETSC_FALSE; break; }
232: }
233: if (sbaij) *symm = PETSC_TRUE;
234: #if defined(PETSC_USE_COMPLEX)
235: /* check if user has set the hermitian flag */
236: *herm = PETSC_TRUE;
237: for (i=0;i<st->nmat;i++) {
238: PetscCall(MatIsHermitianKnown(st->A[i],&set,&flg));
239: if (!set || !flg) { *herm = PETSC_FALSE; break; }
240: }
241: #else
242: *herm = *symm;
243: #endif
244: PetscFunctionReturn(PETSC_SUCCESS);
245: }
247: /*@
248: STSetMatrices - Sets the matrices associated with the eigenvalue problem.
250: Collective
252: Input Parameters:
253: + st - the spectral transformation context
254: . n - number of matrices in array A
255: - A - the array of matrices associated with the eigensystem
257: Notes:
258: It must be called before STSetUp(). If it is called again after STSetUp() then
259: the ST object is reset.
261: Level: intermediate
263: .seealso: STGetMatrix(), STGetNumMatrices(), STSetUp(), STReset()
264: @*/
265: PetscErrorCode STSetMatrices(ST st,PetscInt n,Mat A[])
266: {
267: PetscInt i;
268: PetscBool same=PETSC_TRUE;
270: PetscFunctionBegin;
273: PetscCheck(n>0,PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_OUTOFRANGE,"Must have one or more matrices, you have %" PetscInt_FMT,n);
274: PetscAssertPointer(A,3);
275: PetscCheckSameComm(st,1,*A,3);
276: STCheckNotSeized(st,1);
277: PetscCheck(!st->nsplit || st->nsplit==n,PetscObjectComm((PetscObject)st),PETSC_ERR_SUP,"The number of matrices must be the same as in STSetSplitPreconditioner()");
279: if (st->state) {
280: if (n!=st->nmat) same = PETSC_FALSE;
281: for (i=0;same&&i<n;i++) {
282: if (A[i]!=st->A[i]) same = PETSC_FALSE;
283: }
284: if (!same) PetscCall(STReset(st));
285: } else same = PETSC_FALSE;
286: if (!same) {
287: PetscCall(MatDestroyMatrices(PetscMax(2,st->nmat),&st->A));
288: PetscCall(PetscCalloc1(PetscMax(2,n),&st->A));
289: PetscCall(PetscFree(st->Astate));
290: PetscCall(PetscMalloc1(PetscMax(2,n),&st->Astate));
291: }
292: for (i=0;i<n;i++) {
294: PetscCall(PetscObjectReference((PetscObject)A[i]));
295: PetscCall(MatDestroy(&st->A[i]));
296: st->A[i] = A[i];
297: st->Astate[i] = ((PetscObject)A[i])->state;
298: }
299: if (n==1) {
300: st->A[1] = NULL;
301: st->Astate[1] = 0;
302: }
303: st->nmat = n;
304: if (same) st->state = ST_STATE_UPDATED;
305: else st->state = ST_STATE_INITIAL;
306: PetscCheck(!same || !st->Psplit,PetscObjectComm((PetscObject)st),PETSC_ERR_SUP,"Support for changing the matrices while using a split preconditioner is not implemented yet");
307: st->opready = PETSC_FALSE;
308: if (!same) PetscCall(STMatIsSymmetricKnown(st,&st->asymm,&st->aherm));
309: PetscFunctionReturn(PETSC_SUCCESS);
310: }
312: /*@
313: STGetMatrix - Gets the matrices associated with the original eigensystem.
315: Not Collective
317: Input Parameters:
318: + st - the spectral transformation context
319: - k - the index of the requested matrix (starting in 0)
321: Output Parameters:
322: . A - the requested matrix
324: Level: intermediate
326: .seealso: STSetMatrices(), STGetNumMatrices()
327: @*/
328: PetscErrorCode STGetMatrix(ST st,PetscInt k,Mat *A)
329: {
330: PetscFunctionBegin;
333: PetscAssertPointer(A,3);
334: STCheckMatrices(st,1);
335: PetscCheck(k>=0 && k<st->nmat,PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_OUTOFRANGE,"k must be between 0 and %" PetscInt_FMT,st->nmat-1);
336: PetscCheck(((PetscObject)st->A[k])->state==st->Astate[k],PetscObjectComm((PetscObject)st),PETSC_ERR_SUP,"Cannot retrieve original matrices (have been modified)");
337: *A = st->A[k];
338: PetscFunctionReturn(PETSC_SUCCESS);
339: }
341: /*@
342: STGetMatrixTransformed - Gets the matrices associated with the transformed eigensystem.
344: Not Collective
346: Input Parameters:
347: + st - the spectral transformation context
348: - k - the index of the requested matrix (starting in 0)
350: Output Parameters:
351: . T - the requested matrix
353: Level: developer
355: .seealso: STGetMatrix(), STGetNumMatrices()
356: @*/
357: PetscErrorCode STGetMatrixTransformed(ST st,PetscInt k,Mat *T)
358: {
359: PetscFunctionBegin;
362: PetscAssertPointer(T,3);
363: STCheckMatrices(st,1);
364: PetscCheck(k>=0 && k<st->nmat,PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_OUTOFRANGE,"k must be between 0 and %" PetscInt_FMT,st->nmat-1);
365: PetscCheck(st->T,PetscObjectComm((PetscObject)st),PETSC_ERR_POINTER,"There are no transformed matrices");
366: *T = st->T[k];
367: PetscFunctionReturn(PETSC_SUCCESS);
368: }
370: /*@
371: STGetNumMatrices - Returns the number of matrices stored in the ST.
373: Not Collective
375: Input Parameter:
376: . st - the spectral transformation context
378: Output Parameters:
379: . n - the number of matrices passed in STSetMatrices()
381: Level: intermediate
383: .seealso: STSetMatrices()
384: @*/
385: PetscErrorCode STGetNumMatrices(ST st,PetscInt *n)
386: {
387: PetscFunctionBegin;
389: PetscAssertPointer(n,2);
390: *n = st->nmat;
391: PetscFunctionReturn(PETSC_SUCCESS);
392: }
394: /*@
395: STResetMatrixState - Resets the stored state of the matrices in the ST.
397: Logically Collective
399: Input Parameter:
400: . st - the spectral transformation context
402: Note:
403: This is useful in solvers where the user matrices are modified during
404: the computation, as in nonlinear inverse iteration. The effect is that
405: STGetMatrix() will retrieve the modified matrices as if they were
406: the matrices originally provided by the user.
408: Level: developer
410: .seealso: STGetMatrix(), EPSPowerSetNonlinear()
411: @*/
412: PetscErrorCode STResetMatrixState(ST st)
413: {
414: PetscInt i;
416: PetscFunctionBegin;
418: for (i=0;i<st->nmat;i++) st->Astate[i] = ((PetscObject)st->A[i])->state;
419: PetscFunctionReturn(PETSC_SUCCESS);
420: }
422: /*@
423: STSetPreconditionerMat - Sets the matrix to be used to build the preconditioner.
425: Collective
427: Input Parameters:
428: + st - the spectral transformation context
429: - mat - the matrix that will be used in constructing the preconditioner
431: Notes:
432: This matrix will be passed to the internal KSP object (via the last argument
433: of KSPSetOperators()) as the matrix to be used when constructing the preconditioner.
434: If no matrix is set or mat is set to NULL, A-sigma*B will be used
435: to build the preconditioner, being sigma the value set by STSetShift().
437: More precisely, this is relevant for spectral transformations that represent
438: a rational matrix function, and use a KSP object for the denominator, called
439: K in the description of STGetOperator(). It includes also the STPRECOND case.
440: If the user has a good approximation to matrix K that can be used to build a
441: cheap preconditioner, it can be passed with this function. Note that it affects
442: only the Pmat argument of KSPSetOperators(), not the Amat argument.
444: If a preconditioner matrix is set, the default is to use an iterative KSP
445: rather than a direct method.
447: An alternative to pass an approximation of A-sigma*B with this function is
448: to provide approximations of A and B via STSetSplitPreconditioner(). The
449: difference is that when sigma changes the preconditioner is recomputed.
451: Use NULL to remove a previously set matrix.
453: Level: advanced
455: .seealso: STGetPreconditionerMat(), STSetShift(), STGetOperator(), STSetSplitPreconditioner()
456: @*/
457: PetscErrorCode STSetPreconditionerMat(ST st,Mat mat)
458: {
459: PetscFunctionBegin;
461: if (mat) {
463: PetscCheckSameComm(st,1,mat,2);
464: }
465: STCheckNotSeized(st,1);
466: PetscCheck(!mat || !st->Psplit,PetscObjectComm((PetscObject)st),PETSC_ERR_SUP,"Cannot call both STSetPreconditionerMat and STSetSplitPreconditioner");
467: if (mat) PetscCall(PetscObjectReference((PetscObject)mat));
468: PetscCall(MatDestroy(&st->Pmat));
469: st->Pmat = mat;
470: st->Pmat_set = mat? PETSC_TRUE: PETSC_FALSE;
471: st->state = ST_STATE_INITIAL;
472: st->opready = PETSC_FALSE;
473: PetscFunctionReturn(PETSC_SUCCESS);
474: }
476: /*@
477: STGetPreconditionerMat - Returns the matrix previously set by STSetPreconditionerMat().
479: Not Collective
481: Input Parameter:
482: . st - the spectral transformation context
484: Output Parameter:
485: . mat - the matrix that will be used in constructing the preconditioner or
486: NULL if no matrix was set by STSetPreconditionerMat().
488: Level: advanced
490: .seealso: STSetPreconditionerMat()
491: @*/
492: PetscErrorCode STGetPreconditionerMat(ST st,Mat *mat)
493: {
494: PetscFunctionBegin;
496: PetscAssertPointer(mat,2);
497: *mat = st->Pmat_set? st->Pmat: NULL;
498: PetscFunctionReturn(PETSC_SUCCESS);
499: }
501: /*@
502: STSetSplitPreconditioner - Sets the matrices from which to build the preconditioner
503: in split form.
505: Collective
507: Input Parameters:
508: + st - the spectral transformation context
509: . n - number of matrices
510: . Psplit - array of matrices
511: - strp - structure flag for Psplit matrices
513: Notes:
514: The number of matrices passed here must be the same as in STSetMatrices().
516: For linear eigenproblems, the preconditioner matrix is computed as
517: Pmat(sigma) = A0-sigma*B0, where A0 and B0 are approximations of A and B
518: (the eigenproblem matrices) provided via the Psplit array in this function.
519: Compared to STSetPreconditionerMat(), this function allows setting a preconditioner
520: in a way that is independent of the shift sigma. Whenever the value of sigma
521: changes the preconditioner is recomputed.
523: Similarly, for polynomial eigenproblems the matrix for the preconditioner
524: is expressed as Pmat(sigma) = sum_i Psplit_i*phi_i(sigma), for i=1,...,n, where
525: the phi_i's are the polynomial basis functions.
527: The structure flag provides information about the relative nonzero pattern of the
528: Psplit_i matrices, in the same way as in STSetMatStructure().
530: Use n=0 to reset a previously set split preconditioner.
532: Level: advanced
534: .seealso: STGetSplitPreconditionerTerm(), STGetSplitPreconditionerInfo(), STSetPreconditionerMat(), STSetMatrices(), STSetMatStructure()
535: @*/
536: PetscErrorCode STSetSplitPreconditioner(ST st,PetscInt n,Mat Psplit[],MatStructure strp)
537: {
538: PetscInt i,N=0,M,M0=0,mloc,nloc,mloc0=0;
540: PetscFunctionBegin;
543: PetscCheck(n>=0,PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_OUTOFRANGE,"Negative value of n = %" PetscInt_FMT,n);
544: PetscCheck(!n || !st->Pmat_set,PetscObjectComm((PetscObject)st),PETSC_ERR_SUP,"Cannot call both STSetPreconditionerMat and STSetSplitPreconditioner");
545: PetscCheck(!n || !st->nmat || st->nmat==n,PetscObjectComm((PetscObject)st),PETSC_ERR_SUP,"The number of matrices must be the same as in STSetMatrices()");
546: if (n) PetscAssertPointer(Psplit,3);
548: STCheckNotSeized(st,1);
550: for (i=0;i<n;i++) {
552: PetscCheckSameComm(st,1,Psplit[i],3);
553: PetscCall(MatGetSize(Psplit[i],&M,&N));
554: PetscCall(MatGetLocalSize(Psplit[i],&mloc,&nloc));
555: PetscCheck(M==N,PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_WRONG,"Psplit[%" PetscInt_FMT "] is a non-square matrix (%" PetscInt_FMT " rows, %" PetscInt_FMT " cols)",i,M,N);
556: PetscCheck(mloc==nloc,PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_WRONG,"Psplit[%" PetscInt_FMT "] does not have equal row and column local sizes (%" PetscInt_FMT ", %" PetscInt_FMT ")",i,mloc,nloc);
557: if (!i) { M0 = M; mloc0 = mloc; }
558: PetscCheck(M==M0,PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_INCOMP,"Dimensions of Psplit[%" PetscInt_FMT "] do not match with previous matrices (%" PetscInt_FMT ", %" PetscInt_FMT ")",i,M,M0);
559: PetscCheck(mloc==mloc0,PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_INCOMP,"Local dimensions of Psplit[%" PetscInt_FMT "] do not match with previous matrices (%" PetscInt_FMT ", %" PetscInt_FMT ")",i,mloc,mloc0);
560: PetscCall(PetscObjectReference((PetscObject)Psplit[i]));
561: }
563: if (st->Psplit) PetscCall(MatDestroyMatrices(st->nsplit,&st->Psplit));
565: /* allocate space and copy matrices */
566: if (n) {
567: PetscCall(PetscMalloc1(n,&st->Psplit));
568: for (i=0;i<n;i++) st->Psplit[i] = Psplit[i];
569: }
570: st->nsplit = n;
571: st->strp = strp;
572: st->state = ST_STATE_INITIAL;
573: PetscFunctionReturn(PETSC_SUCCESS);
574: }
576: /*@
577: STGetSplitPreconditionerTerm - Gets the matrices associated with
578: the split preconditioner.
580: Not Collective
582: Input Parameters:
583: + st - the spectral transformation context
584: - k - the index of the requested matrix (starting in 0)
586: Output Parameter:
587: . Psplit - the returned matrix
589: Level: advanced
591: .seealso: STSetSplitPreconditioner(), STGetSplitPreconditionerInfo()
592: @*/
593: PetscErrorCode STGetSplitPreconditionerTerm(ST st,PetscInt k,Mat *Psplit)
594: {
595: PetscFunctionBegin;
598: PetscAssertPointer(Psplit,3);
599: PetscCheck(k>=0 && k<st->nsplit,PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_OUTOFRANGE,"k must be between 0 and %" PetscInt_FMT,st->nsplit-1);
600: PetscCheck(st->Psplit,PetscObjectComm((PetscObject)st),PETSC_ERR_ORDER,"You have not called STSetSplitPreconditioner()");
601: *Psplit = st->Psplit[k];
602: PetscFunctionReturn(PETSC_SUCCESS);
603: }
605: /*@
606: STGetSplitPreconditionerInfo - Returns the number of matrices of the split
607: preconditioner, as well as the structure flag.
609: Not Collective
611: Input Parameter:
612: . st - the spectral transformation context
614: Output Parameters:
615: + n - the number of matrices passed in STSetSplitPreconditioner()
616: - strp - the matrix structure flag passed in STSetSplitPreconditioner()
618: Level: advanced
620: .seealso: STSetSplitPreconditioner(), STGetSplitPreconditionerTerm()
621: @*/
622: PetscErrorCode STGetSplitPreconditionerInfo(ST st,PetscInt *n,MatStructure *strp)
623: {
624: PetscFunctionBegin;
626: if (n) *n = st->nsplit;
627: if (strp) *strp = st->strp;
628: PetscFunctionReturn(PETSC_SUCCESS);
629: }
631: /*@
632: STSetShift - Sets the shift associated with the spectral transformation.
634: Collective
636: Input Parameters:
637: + st - the spectral transformation context
638: - shift - the value of the shift
640: Notes:
641: In some spectral transformations, changing the shift may have associated
642: a lot of work, for example recomputing a factorization.
644: This function is normally not directly called by users, since the shift is
645: indirectly set by EPSSetTarget().
647: Level: intermediate
649: .seealso: EPSSetTarget(), STGetShift(), STSetDefaultShift()
650: @*/
651: PetscErrorCode STSetShift(ST st,PetscScalar shift)
652: {
653: PetscFunctionBegin;
657: if (st->sigma != shift) {
658: STCheckNotSeized(st,1);
659: if (st->state==ST_STATE_SETUP) PetscTryTypeMethod(st,setshift,shift);
660: st->sigma = shift;
661: }
662: st->sigma_set = PETSC_TRUE;
663: PetscFunctionReturn(PETSC_SUCCESS);
664: }
666: /*@
667: STGetShift - Gets the shift associated with the spectral transformation.
669: Not Collective
671: Input Parameter:
672: . st - the spectral transformation context
674: Output Parameter:
675: . shift - the value of the shift
677: Level: intermediate
679: .seealso: STSetShift()
680: @*/
681: PetscErrorCode STGetShift(ST st,PetscScalar* shift)
682: {
683: PetscFunctionBegin;
685: PetscAssertPointer(shift,2);
686: *shift = st->sigma;
687: PetscFunctionReturn(PETSC_SUCCESS);
688: }
690: /*@
691: STSetDefaultShift - Sets the value of the shift that should be employed if
692: the user did not specify one.
694: Logically Collective
696: Input Parameters:
697: + st - the spectral transformation context
698: - defaultshift - the default value of the shift
700: Level: developer
702: .seealso: STSetShift()
703: @*/
704: PetscErrorCode STSetDefaultShift(ST st,PetscScalar defaultshift)
705: {
706: PetscFunctionBegin;
709: if (st->defsigma != defaultshift) {
710: st->defsigma = defaultshift;
711: st->state = ST_STATE_INITIAL;
712: st->opready = PETSC_FALSE;
713: }
714: PetscFunctionReturn(PETSC_SUCCESS);
715: }
717: /*@
718: STScaleShift - Multiply the shift with a given factor.
720: Logically Collective
722: Input Parameters:
723: + st - the spectral transformation context
724: - factor - the scaling factor
726: Note:
727: This function does not update the transformation matrices, as opposed to
728: STSetShift().
730: Level: developer
732: .seealso: STSetShift()
733: @*/
734: PetscErrorCode STScaleShift(ST st,PetscScalar factor)
735: {
736: PetscFunctionBegin;
739: st->sigma *= factor;
740: PetscFunctionReturn(PETSC_SUCCESS);
741: }
743: /*@
744: STSetBalanceMatrix - Sets the diagonal matrix to be used for balancing.
746: Collective
748: Input Parameters:
749: + st - the spectral transformation context
750: - D - the diagonal matrix (represented as a vector)
752: Notes:
753: If this matrix is set, STApply will effectively apply D*OP*D^{-1}. Use NULL
754: to reset a previously passed D.
756: Balancing is usually set via EPSSetBalance, but the advanced user may use
757: this function to bypass the usual balancing methods.
759: Level: developer
761: .seealso: EPSSetBalance(), STApply(), STGetBalanceMatrix()
762: @*/
763: PetscErrorCode STSetBalanceMatrix(ST st,Vec D)
764: {
765: PetscFunctionBegin;
767: if (st->D == D) PetscFunctionReturn(PETSC_SUCCESS);
768: STCheckNotSeized(st,1);
769: if (D) {
771: PetscCheckSameComm(st,1,D,2);
772: PetscCall(PetscObjectReference((PetscObject)D));
773: }
774: PetscCall(VecDestroy(&st->D));
775: st->D = D;
776: st->state = ST_STATE_INITIAL;
777: st->opready = PETSC_FALSE;
778: PetscFunctionReturn(PETSC_SUCCESS);
779: }
781: /*@
782: STGetBalanceMatrix - Gets the balance matrix used by the spectral transformation.
784: Not Collective
786: Input Parameter:
787: . st - the spectral transformation context
789: Output Parameter:
790: . D - the diagonal matrix (represented as a vector)
792: Note:
793: If the matrix was not set, a null pointer will be returned.
795: Level: developer
797: .seealso: STSetBalanceMatrix()
798: @*/
799: PetscErrorCode STGetBalanceMatrix(ST st,Vec *D)
800: {
801: PetscFunctionBegin;
803: PetscAssertPointer(D,2);
804: *D = st->D;
805: PetscFunctionReturn(PETSC_SUCCESS);
806: }
808: /*@
809: STMatCreateVecs - Get vector(s) compatible with the ST matrices.
811: Collective
813: Input Parameter:
814: . st - the spectral transformation context
816: Output Parameters:
817: + right - (optional) vector that the matrix can be multiplied against
818: - left - (optional) vector that the matrix vector product can be stored in
820: Level: developer
822: .seealso: STMatCreateVecsEmpty()
823: @*/
824: PetscErrorCode STMatCreateVecs(ST st,Vec *right,Vec *left)
825: {
826: PetscFunctionBegin;
827: STCheckMatrices(st,1);
828: PetscCall(MatCreateVecs(st->A[0],right,left));
829: PetscFunctionReturn(PETSC_SUCCESS);
830: }
832: /*@
833: STMatCreateVecsEmpty - Get vector(s) compatible with the ST matrices, i.e. with the same
834: parallel layout, but without internal array.
836: Collective
838: Input Parameter:
839: . st - the spectral transformation context
841: Output Parameters:
842: + right - (optional) vector that the matrix can be multiplied against
843: - left - (optional) vector that the matrix vector product can be stored in
845: Level: developer
847: .seealso: STMatCreateVecs(), MatCreateVecsEmpty()
848: @*/
849: PetscErrorCode STMatCreateVecsEmpty(ST st,Vec *right,Vec *left)
850: {
851: PetscFunctionBegin;
852: STCheckMatrices(st,1);
853: PetscCall(MatCreateVecsEmpty(st->A[0],right,left));
854: PetscFunctionReturn(PETSC_SUCCESS);
855: }
857: /*@
858: STMatGetSize - Returns the number of rows and columns of the ST matrices.
860: Not Collective
862: Input Parameter:
863: . st - the spectral transformation context
865: Output Parameters:
866: + m - the number of global rows
867: - n - the number of global columns
869: Level: developer
871: .seealso: STMatGetLocalSize()
872: @*/
873: PetscErrorCode STMatGetSize(ST st,PetscInt *m,PetscInt *n)
874: {
875: PetscFunctionBegin;
876: STCheckMatrices(st,1);
877: PetscCall(MatGetSize(st->A[0],m,n));
878: PetscFunctionReturn(PETSC_SUCCESS);
879: }
881: /*@
882: STMatGetLocalSize - Returns the number of local rows and columns of the ST matrices.
884: Not Collective
886: Input Parameter:
887: . st - the spectral transformation context
889: Output Parameters:
890: + m - the number of local rows
891: - n - the number of local columns
893: Level: developer
895: .seealso: STMatGetSize()
896: @*/
897: PetscErrorCode STMatGetLocalSize(ST st,PetscInt *m,PetscInt *n)
898: {
899: PetscFunctionBegin;
900: STCheckMatrices(st,1);
901: PetscCall(MatGetLocalSize(st->A[0],m,n));
902: PetscFunctionReturn(PETSC_SUCCESS);
903: }
905: /*@
906: STSetOptionsPrefix - Sets the prefix used for searching for all
907: ST options in the database.
909: Logically Collective
911: Input Parameters:
912: + st - the spectral transformation context
913: - prefix - the prefix string to prepend to all ST option requests
915: Notes:
916: A hyphen (-) must NOT be given at the beginning of the prefix name.
917: The first character of all runtime options is AUTOMATICALLY the
918: hyphen.
920: Level: advanced
922: .seealso: STAppendOptionsPrefix(), STGetOptionsPrefix()
923: @*/
924: PetscErrorCode STSetOptionsPrefix(ST st,const char *prefix)
925: {
926: PetscFunctionBegin;
928: if (!st->ksp) PetscCall(STGetKSP(st,&st->ksp));
929: PetscCall(KSPSetOptionsPrefix(st->ksp,prefix));
930: PetscCall(KSPAppendOptionsPrefix(st->ksp,"st_"));
931: PetscCall(PetscObjectSetOptionsPrefix((PetscObject)st,prefix));
932: PetscFunctionReturn(PETSC_SUCCESS);
933: }
935: /*@
936: STAppendOptionsPrefix - Appends to the prefix used for searching for all
937: ST options in the database.
939: Logically Collective
941: Input Parameters:
942: + st - the spectral transformation context
943: - prefix - the prefix string to prepend to all ST option requests
945: Notes:
946: A hyphen (-) must NOT be given at the beginning of the prefix name.
947: The first character of all runtime options is AUTOMATICALLY the
948: hyphen.
950: Level: advanced
952: .seealso: STSetOptionsPrefix(), STGetOptionsPrefix()
953: @*/
954: PetscErrorCode STAppendOptionsPrefix(ST st,const char *prefix)
955: {
956: PetscFunctionBegin;
958: PetscCall(PetscObjectAppendOptionsPrefix((PetscObject)st,prefix));
959: if (!st->ksp) PetscCall(STGetKSP(st,&st->ksp));
960: PetscCall(KSPSetOptionsPrefix(st->ksp,((PetscObject)st)->prefix));
961: PetscCall(KSPAppendOptionsPrefix(st->ksp,"st_"));
962: PetscFunctionReturn(PETSC_SUCCESS);
963: }
965: /*@
966: STGetOptionsPrefix - Gets the prefix used for searching for all
967: ST options in the database.
969: Not Collective
971: Input Parameters:
972: . st - the spectral transformation context
974: Output Parameters:
975: . prefix - pointer to the prefix string used, is returned
977: Note:
978: On the Fortran side, the user should pass in a string 'prefix' of
979: sufficient length to hold the prefix.
981: Level: advanced
983: .seealso: STSetOptionsPrefix(), STAppendOptionsPrefix()
984: @*/
985: PetscErrorCode STGetOptionsPrefix(ST st,const char *prefix[])
986: {
987: PetscFunctionBegin;
989: PetscAssertPointer(prefix,2);
990: PetscCall(PetscObjectGetOptionsPrefix((PetscObject)st,prefix));
991: PetscFunctionReturn(PETSC_SUCCESS);
992: }
994: /*@
995: STView - Prints the ST data structure.
997: Collective
999: Input Parameters:
1000: + st - the ST context
1001: - viewer - optional visualization context
1003: Note:
1004: The available visualization contexts include
1005: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
1006: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
1007: output where only the first processor opens
1008: the file. All other processors send their
1009: data to the first processor to print.
1011: The user can open an alternative visualization contexts with
1012: PetscViewerASCIIOpen() (output to a specified file).
1014: Level: beginner
1016: .seealso: EPSView()
1017: @*/
1018: PetscErrorCode STView(ST st,PetscViewer viewer)
1019: {
1020: STType cstr;
1021: char str[50];
1022: PetscBool isascii,isstring;
1024: PetscFunctionBegin;
1026: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)st),&viewer));
1028: PetscCheckSameComm(st,1,viewer,2);
1030: PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
1031: PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring));
1032: if (isascii) {
1033: PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)st,viewer));
1034: PetscCall(PetscViewerASCIIPushTab(viewer));
1035: PetscTryTypeMethod(st,view,viewer);
1036: PetscCall(PetscViewerASCIIPopTab(viewer));
1037: PetscCall(SlepcSNPrintfScalar(str,sizeof(str),st->sigma,PETSC_FALSE));
1038: PetscCall(PetscViewerASCIIPrintf(viewer," shift: %s\n",str));
1039: PetscCall(PetscViewerASCIIPrintf(viewer," number of matrices: %" PetscInt_FMT "\n",st->nmat));
1040: switch (st->matmode) {
1041: case ST_MATMODE_COPY:
1042: break;
1043: case ST_MATMODE_INPLACE:
1044: PetscCall(PetscViewerASCIIPrintf(viewer," shifting the matrix and unshifting at exit\n"));
1045: break;
1046: case ST_MATMODE_SHELL:
1047: PetscCall(PetscViewerASCIIPrintf(viewer," using a shell matrix\n"));
1048: break;
1049: }
1050: if (st->nmat>1 && st->matmode != ST_MATMODE_SHELL) PetscCall(PetscViewerASCIIPrintf(viewer," nonzero pattern of the matrices: %s\n",MatStructures[st->str]));
1051: if (st->Psplit) PetscCall(PetscViewerASCIIPrintf(viewer," using split preconditioner matrices with %s\n",MatStructures[st->strp]));
1052: if (st->transform && st->nmat>2) PetscCall(PetscViewerASCIIPrintf(viewer," computing transformed matrices\n"));
1053: if (st->structured) PetscCall(PetscViewerASCIIPrintf(viewer," exploiting structure in the application of the operator\n"));
1054: } else if (isstring) {
1055: PetscCall(STGetType(st,&cstr));
1056: PetscCall(PetscViewerStringSPrintf(viewer," %-7.7s",cstr));
1057: PetscTryTypeMethod(st,view,viewer);
1058: }
1059: if (st->usesksp) {
1060: if (!st->ksp) PetscCall(STGetKSP(st,&st->ksp));
1061: PetscCall(PetscViewerASCIIPushTab(viewer));
1062: PetscCall(KSPView(st->ksp,viewer));
1063: PetscCall(PetscViewerASCIIPopTab(viewer));
1064: }
1065: PetscFunctionReturn(PETSC_SUCCESS);
1066: }
1068: /*@
1069: STViewFromOptions - View from options
1071: Collective
1073: Input Parameters:
1074: + st - the spectral transformation context
1075: . obj - optional object
1076: - name - command line option
1078: Level: intermediate
1080: .seealso: STView(), STCreate()
1081: @*/
1082: PetscErrorCode STViewFromOptions(ST st,PetscObject obj,const char name[])
1083: {
1084: PetscFunctionBegin;
1086: PetscCall(PetscObjectViewFromOptions((PetscObject)st,obj,name));
1087: PetscFunctionReturn(PETSC_SUCCESS);
1088: }
1090: /*@C
1091: STRegister - Adds a method to the spectral transformation package.
1093: Not Collective
1095: Input Parameters:
1096: + name - name of a new user-defined transformation
1097: - function - routine to create method context
1099: Notes:
1100: STRegister() may be called multiple times to add several user-defined
1101: spectral transformations.
1103: Example Usage:
1104: .vb
1105: STRegister("my_transform",MyTransformCreate);
1106: .ve
1108: Then, your spectral transform can be chosen with the procedural interface via
1109: $ STSetType(st,"my_transform")
1110: or at runtime via the option
1111: $ -st_type my_transform
1113: Level: advanced
1115: .seealso: STRegisterAll()
1116: @*/
1117: PetscErrorCode STRegister(const char *name,PetscErrorCode (*function)(ST))
1118: {
1119: PetscFunctionBegin;
1120: PetscCall(STInitializePackage());
1121: PetscCall(PetscFunctionListAdd(&STList,name,function));
1122: PetscFunctionReturn(PETSC_SUCCESS);
1123: }