Actual source code: stsles.c
1: /*
2: The ST (spectral transformation) interface routines related to the
3: KSP object associated to it.
5: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6: SLEPc - Scalable Library for Eigenvalue Problem Computations
7: Copyright (c) 2002-2013, Universitat Politecnica de Valencia, Spain
9: This file is part of SLEPc.
11: SLEPc is free software: you can redistribute it and/or modify it under the
12: terms of version 3 of the GNU Lesser General Public License as published by
13: the Free Software Foundation.
15: SLEPc is distributed in the hope that it will be useful, but WITHOUT ANY
16: WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17: FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
18: more details.
20: You should have received a copy of the GNU Lesser General Public License
21: along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
22: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
23: */
25: #include <slepc-private/stimpl.h> /*I "slepcst.h" I*/
26: #include <slepcsys.h>
30: /*@
31: STMatMult - Computes the matrix-vector product y = T[k] x, where T[k] is
32: the k-th matrix of the spectral transformation.
34: Collective on ST
36: Input Parameters:
37: + st - the spectral transformation context
38: . k - index of matrix to use
39: - x - the vector to be multiplied
41: Output Parameter:
42: . y - the result
44: Level: developer
46: .seealso: STMatMultTranspose()
47: @*/
48: PetscErrorCode STMatMult(ST st,PetscInt k,Vec x,Vec y)
49: {
53: if (k<0 || k>=PetscMax(2,st->nmat)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"k must be between 0 and %d",st->nmat);
54: if (x == y) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_IDN,"x and y must be different vectors");
56: if (!st->setupcalled) { STSetUp(st); }
57: if (!st->T[k]) {
58: /* T[k]=NULL means identity matrix */
59: VecCopy(x,y);
60: } else {
61: MatMult(st->T[k],x,y);
62: }
63: return(0);
64: }
68: /*@
69: STMatMultTranspose - Computes the matrix-vector product y = T[k]' x, where T[k] is
70: the k-th matrix of the spectral transformation.
72: Collective on ST
74: Input Parameters:
75: + st - the spectral transformation context
76: . k - index of matrix to use
77: - x - the vector to be multiplied
79: Output Parameter:
80: . y - the result
82: Level: developer
84: .seealso: STMatMult()
85: @*/
86: PetscErrorCode STMatMultTranspose(ST st,PetscInt k,Vec x,Vec y)
87: {
91: if (k<0 || k>=PetscMax(2,st->nmat)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"k must be between 0 and %d",st->nmat);
92: if (x == y) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_IDN,"x and y must be different vectors");
94: if (!st->setupcalled) { STSetUp(st); }
95: if (!st->T[k]) {
96: /* T[k]=NULL means identity matrix */
97: VecCopy(x,y);
98: } else {
99: MatMultTranspose(st->T[k],x,y);
100: }
101: return(0);
102: }
106: /*@
107: STMatSolve - Solves T[k] x = b, where T[k] is the k-th matrix of
108: the spectral transformation, using a KSP object stored internally.
110: Collective on ST
112: Input Parameters:
113: + st - the spectral transformation context
114: . k - index of matrix to use
115: - b - right hand side vector
117: Output Parameter:
118: . x - computed solution
120: Level: developer
122: .seealso: STMatSolveTranspose()
123: @*/
124: PetscErrorCode STMatSolve(ST st,PetscInt k,Vec b,Vec x)
125: {
126: PetscErrorCode ierr;
127: PetscInt its;
128: PetscBool flg;
129: KSPConvergedReason reason;
132: if (k<0 || k>=PetscMax(2,st->nmat)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"k must be between 0 and %d",st->nmat);
133: if (x == b) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
135: if (!st->setupcalled) { STSetUp(st); }
136: PetscObjectTypeCompareAny((PetscObject)st,&flg,STFOLD,STPRECOND,STSHELL,"");
137: if (!flg && !st->T[k]) {
138: /* T[k]=NULL means identity matrix */
139: VecCopy(b,x);
140: return(0);
141: }
142: if (!st->ksp) { STGetKSP(st,&st->ksp); }
143: if (!flg && k!=st->kspidx) {
144: /* change of coefficient matrix; should not happen normally */
145: KSPSetOperators(st->ksp,st->T[k],st->T[k],DIFFERENT_NONZERO_PATTERN);
146: KSPSetUp(st->ksp);
147: st->kspidx = k;
148: }
149: KSPSolve(st->ksp,b,x);
150: KSPGetConvergedReason(st->ksp,&reason);
151: if (reason<0) SETERRQ1(PetscObjectComm((PetscObject)st),PETSC_ERR_NOT_CONVERGED,"KSP did not converge (reason=%s)",KSPConvergedReasons[reason]);
152: KSPGetIterationNumber(st->ksp,&its);
153: st->lineariterations += its;
154: PetscInfo1(st,"Linear solve iterations=%D\n",its);
155: return(0);
156: }
160: /*@
161: STMatSolveTranspose - Solves T[k]' x = b, where T[k] is the k-th matrix of
162: the spectral transformation, using a KSP object stored internally.
164: Collective on ST
166: Input Parameters:
167: . st - the spectral transformation context
168: . b - right hand side vector
170: Output Parameter:
171: . x - computed solution
173: Level: developer
175: .seealso: STMatSolve()
176: @*/
177: PetscErrorCode STMatSolveTranspose(ST st,PetscInt k,Vec b,Vec x)
178: {
179: PetscErrorCode ierr;
180: PetscInt its;
181: PetscBool flg;
182: KSPConvergedReason reason;
185: if (k<0 || k>=PetscMax(2,st->nmat)) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"k must be between 0 and %d",st->nmat);
186: PetscObjectTypeCompareAny((PetscObject)st,&flg,STFOLD,STPRECOND,STSHELL,"");
187: if (x == b) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
189: if (!st->setupcalled) { STSetUp(st); }
190: if (!flg && !st->T[k]) {
191: /* T[k]=NULL means identity matrix */
192: VecCopy(b,x);
193: return(0);
194: }
195: if (!st->ksp) { STGetKSP(st,&st->ksp); }
196: if (!flg && k!=st->kspidx) {
197: /* change of coefficient matrix; should not happen normally */
198: KSPSetOperators(st->ksp,st->T[k],st->T[k],DIFFERENT_NONZERO_PATTERN);
199: KSPSetUp(st->ksp);
200: st->kspidx = k;
201: }
202: KSPSolveTranspose(st->ksp,b,x);
203: KSPGetConvergedReason(st->ksp,&reason);
204: if (reason<0) SETERRQ1(PetscObjectComm((PetscObject)st),PETSC_ERR_NOT_CONVERGED,"KSP did not converge (reason=%s)",KSPConvergedReasons[reason]);
205: KSPGetIterationNumber(st->ksp,&its);
206: st->lineariterations += its;
207: PetscInfo1(st,"Linear solve iterations=%D\n",its);
208: return(0);
209: }
213: /*
214: STMatSetHermitian - Sets the Hermitian flag to the ST matrix.
216: Input Parameters:
217: . st - the spectral transformation context
218: . M - matrix
219: */
220: PetscErrorCode STMatSetHermitian(ST st,Mat M)
221: {
222: #if defined(PETSC_USE_COMPLEX)
224: PetscBool set,aherm,mherm;
225: PetscInt i;
226: #endif
229: #if defined(PETSC_USE_COMPLEX)
230: mherm = PETSC_FALSE;
231: for (i=0;i<st->nmat;i++) {
232: MatIsHermitianKnown(st->A[i],&set,&aherm);
233: if (!set) aherm = PETSC_FALSE;
234: mherm = (mherm && aherm)? PETSC_TRUE: PETSC_FALSE;
235: if (PetscRealPart(st->sigma)==0.0) break;
236: }
237: mherm = (mherm && PetscImaginaryPart(st->sigma)==0.0)? PETSC_TRUE: PETSC_FALSE;
238: MatSetOption(M,MAT_HERMITIAN,mherm);
239: #endif
240: return(0);
241: }
245: /*@
246: STSetKSP - Sets the KSP object associated with the spectral
247: transformation.
249: Collective on ST
251: Input Parameters:
252: + st - the spectral transformation context
253: - ksp - the linear system context
255: Level: advanced
257: @*/
258: PetscErrorCode STSetKSP(ST st,KSP ksp)
259: {
266: PetscObjectReference((PetscObject)ksp);
267: KSPDestroy(&st->ksp);
268: st->ksp = ksp;
269: PetscLogObjectParent(st,st->ksp);
270: return(0);
271: }
275: /*@
276: STGetKSP - Gets the KSP object associated with the spectral
277: transformation.
279: Not Collective
281: Input Parameter:
282: . st - the spectral transformation context
284: Output Parameter:
285: . ksp - the linear system context
287: Notes:
288: On output, the value of ksp can be NULL if the combination of
289: eigenproblem type and selected transformation does not require to
290: solve a linear system of equations.
292: Level: intermediate
294: @*/
295: PetscErrorCode STGetKSP(ST st,KSP* ksp)
296: {
302: if (!st->ksp) {
303: KSPCreate(PetscObjectComm((PetscObject)st),&st->ksp);
304: KSPSetOptionsPrefix(st->ksp,((PetscObject)st)->prefix);
305: KSPAppendOptionsPrefix(st->ksp,"st_");
306: PetscObjectIncrementTabLevel((PetscObject)st->ksp,(PetscObject)st,1);
307: PetscLogObjectParent(st,st->ksp);
308: KSPSetTolerances(st->ksp,SLEPC_DEFAULT_TOL,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);
309: }
310: *ksp = st->ksp;
311: return(0);
312: }
316: /*@
317: STGetOperationCounters - Gets the total number of operator applications
318: and linear solver iterations used by the ST object.
320: Not Collective
322: Input Parameter:
323: . st - the spectral transformation context
325: Output Parameter:
326: + ops - number of operator applications
327: - lits - number of linear solver iterations
329: Notes:
330: Any output parameter may be NULL on input if not needed.
332: Level: intermediate
334: .seealso: STResetOperationCounters()
335: @*/
336: PetscErrorCode STGetOperationCounters(ST st,PetscInt* ops,PetscInt* lits)
337: {
340: if (ops) *ops = st->applys;
341: if (lits) *lits = st->lineariterations;
342: return(0);
343: }
347: /*@
348: STResetOperationCounters - Resets the counters for operator applications,
349: inner product operations and total number of linear iterations used by
350: the ST object.
352: Logically Collective on ST
354: Input Parameter:
355: . st - the spectral transformation context
357: Level: intermediate
359: .seealso: STGetOperationCounters()
360: @*/
361: PetscErrorCode STResetOperationCounters(ST st)
362: {
365: st->lineariterations = 0;
366: st->applys = 0;
367: return(0);
368: }
372: PetscErrorCode STCheckNullSpace_Default(ST st,PetscInt n,const Vec V[])
373: {
375: PetscInt i,c;
376: PetscReal norm;
377: Vec *T,w;
378: Mat A;
379: PC pc;
380: MatNullSpace nullsp;
383: PetscMalloc(n*sizeof(Vec),&T);
384: if (!st->ksp) { STGetKSP(st,&st->ksp); }
385: KSPGetPC(st->ksp,&pc);
386: PCGetOperators(pc,&A,NULL,NULL);
387: MatGetVecs(A,NULL,&w);
388: c = 0;
389: for (i=0;i<n;i++) {
390: MatMult(A,V[i],w);
391: VecNorm(w,NORM_2,&norm);
392: if (norm < 1e-8) {
393: PetscInfo2(st,"Vector %D norm=%g\n",i,(double)norm);
394: T[c] = V[i];
395: c++;
396: }
397: }
398: VecDestroy(&w);
399: if (c>0) {
400: MatNullSpaceCreate(PetscObjectComm((PetscObject)st),PETSC_FALSE,c,T,&nullsp);
401: KSPSetNullSpace(st->ksp,nullsp);
402: MatNullSpaceDestroy(&nullsp);
403: }
404: PetscFree(T);
405: return(0);
406: }
410: /*@
411: STCheckNullSpace - Given a set of vectors, this function tests each of
412: them to be a nullspace vector of the coefficient matrix of the associated
413: KSP object. All these nullspace vectors are passed to the KSP object.
415: Collective on ST
417: Input Parameters:
418: + st - the spectral transformation context
419: . n - number of vectors
420: - V - vectors to be checked
422: Note:
423: This function allows to handle singular pencils and to solve some problems
424: in which the nullspace is important (see the users guide for details).
426: Level: developer
428: .seealso: EPSSetDeflationSpace()
429: @*/
430: PetscErrorCode STCheckNullSpace(ST st,PetscInt n,const Vec V[])
431: {
437: if (n>0 && st->ops->checknullspace) {
440: (*st->ops->checknullspace)(st,n,V);
441: }
442: return(0);
443: }