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-2015, 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*/
29: /*@
30: STMatMult - Computes the matrix-vector product y = T[k] x, where T[k] is
31: the k-th matrix of the spectral transformation.
33: Collective on ST 35: Input Parameters:
36: + st - the spectral transformation context
37: . k - index of matrix to use
38: - x - the vector to be multiplied
40: Output Parameter:
41: . y - the result
43: Level: developer
45: .seealso: STMatMultTranspose()
46: @*/
47: PetscErrorCode STMatMult(ST st,PetscInt k,Vec x,Vec y) 48: {
56: STCheckMatrices(st,1);
57: 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);
58: if (x == y) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_IDN,"x and y must be different vectors");
59: VecLocked(y,3);
61: if (!st->setupcalled) { STSetUp(st); }
62: VecLockPush(x);
63: PetscLogEventBegin(ST_MatMult,st,x,y,0);
64: if (!st->T[k]) {
65: /* T[k]=NULL means identity matrix */
66: VecCopy(x,y);
67: } else {
68: MatMult(st->T[k],x,y);
69: }
70: PetscLogEventEnd(ST_MatMult,st,x,y,0);
71: VecLockPop(x);
72: return(0);
73: }
77: /*@
78: STMatMultTranspose - Computes the matrix-vector product y = T[k]' x, where T[k] is
79: the k-th matrix of the spectral transformation.
81: Collective on ST 83: Input Parameters:
84: + st - the spectral transformation context
85: . k - index of matrix to use
86: - x - the vector to be multiplied
88: Output Parameter:
89: . y - the result
91: Level: developer
93: .seealso: STMatMult()
94: @*/
95: PetscErrorCode STMatMultTranspose(ST st,PetscInt k,Vec x,Vec y) 96: {
104: STCheckMatrices(st,1);
105: 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);
106: if (x == y) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_IDN,"x and y must be different vectors");
107: VecLocked(y,3);
109: if (!st->setupcalled) { STSetUp(st); }
110: VecLockPush(x);
111: PetscLogEventBegin(ST_MatMultTranspose,st,x,y,0);
112: if (!st->T[k]) {
113: /* T[k]=NULL means identity matrix */
114: VecCopy(x,y);
115: } else {
116: MatMultTranspose(st->T[k],x,y);
117: }
118: PetscLogEventEnd(ST_MatMultTranspose,st,x,y,0);
119: VecLockPop(x);
120: return(0);
121: }
125: /*@
126: STMatSolve - Solves P x = b, where P is the preconditioner matrix of
127: the spectral transformation, using a KSP object stored internally.
129: Collective on ST131: Input Parameters:
132: + st - the spectral transformation context
133: - b - right hand side vector
135: Output Parameter:
136: . x - computed solution
138: Level: developer
140: .seealso: STMatSolveTranspose()
141: @*/
142: PetscErrorCode STMatSolve(ST st,Vec b,Vec x)143: {
145: PetscInt its;
146: PetscBool flg;
152: STCheckMatrices(st,1);
153: if (x == b) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
154: VecLocked(x,3);
156: if (!st->setupcalled) { STSetUp(st); }
157: VecLockPush(b);
158: PetscLogEventBegin(ST_MatSolve,st,b,x,0);
159: PetscObjectTypeCompareAny((PetscObject)st,&flg,STPRECOND,STSHELL,"");
160: if (!flg && !st->P) {
161: /* P=NULL means identity matrix */
162: VecCopy(b,x);
163: return(0);
164: }
165: if (!st->ksp) { STGetKSP(st,&st->ksp); }
166: KSPSolve(st->ksp,b,x);
167: KSPGetIterationNumber(st->ksp,&its);
168: PetscInfo1(st,"Linear solve iterations=%D\n",its);
169: PetscLogEventEnd(ST_MatSolve,st,b,x,0);
170: VecLockPop(b);
171: return(0);
172: }
176: /*@
177: STMatSolveTranspose - Solves P' x = b, where P is the preconditioner matrix of
178: the spectral transformation, using a KSP object stored internally.
180: Collective on ST182: Input Parameters:
183: . st - the spectral transformation context
184: . b - right hand side vector
186: Output Parameter:
187: . x - computed solution
189: Level: developer
191: .seealso: STMatSolve()
192: @*/
193: PetscErrorCode STMatSolveTranspose(ST st,Vec b,Vec x)194: {
196: PetscInt its;
197: PetscBool flg;
203: STCheckMatrices(st,1);
204: if (x == b) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
205: VecLocked(x,3);
207: if (!st->setupcalled) { STSetUp(st); }
208: VecLockPush(b);
209: PetscLogEventBegin(ST_MatSolveTranspose,st,b,x,0);
210: PetscObjectTypeCompareAny((PetscObject)st,&flg,STPRECOND,STSHELL,"");
211: if (!flg && !st->P) {
212: /* P=NULL means identity matrix */
213: VecCopy(b,x);
214: return(0);
215: }
216: if (!st->ksp) { STGetKSP(st,&st->ksp); }
217: KSPSolveTranspose(st->ksp,b,x);
218: KSPGetIterationNumber(st->ksp,&its);
219: PetscInfo1(st,"Linear solve iterations=%D\n",its);
220: PetscLogEventEnd(ST_MatSolveTranspose,st,b,x,0);
221: VecLockPop(b);
222: return(0);
223: }
227: /*
228: STMatSetHermitian - Sets the Hermitian flag to the ST matrix.
230: Input Parameters:
231: . st - the spectral transformation context
232: . M - matrix
233: */
234: PetscErrorCode STMatSetHermitian(ST st,Mat M)235: {
236: #if defined(PETSC_USE_COMPLEX)
238: PetscBool set,aherm,mherm;
239: PetscInt i;
240: #endif
243: #if defined(PETSC_USE_COMPLEX)
244: mherm = PETSC_FALSE;
245: for (i=0;i<st->nmat;i++) {
246: MatIsHermitianKnown(st->A[i],&set,&aherm);
247: if (!set) aherm = PETSC_FALSE;
248: mherm = (mherm && aherm)? PETSC_TRUE: PETSC_FALSE;
249: if (PetscRealPart(st->sigma)==0.0) break;
250: }
251: mherm = (mherm && PetscImaginaryPart(st->sigma)==0.0)? PETSC_TRUE: PETSC_FALSE;
252: MatSetOption(M,MAT_HERMITIAN,mherm);
253: #endif
254: return(0);
255: }
259: PetscErrorCode STCheckFactorPackage(ST st)260: {
261: PetscErrorCode ierr;
262: PC pc;
263: PetscMPIInt size;
264: PetscBool flg;
265: const MatSolverPackage stype;
268: MPI_Comm_size(PetscObjectComm((PetscObject)st),&size);
269: if (size==1) return(0);
270: KSPGetPC(st->ksp,&pc);
271: PCFactorGetMatSolverPackage(pc,&stype);
272: if (stype) { /* currently selected PC is a factorization */
273: PetscStrcmp(stype,MATSOLVERPETSC,&flg);
274: if (flg) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_SUP,"You chose to solve linear systems with a factorization, but in parallel runs you need to select an external package; see the users guide for details");
275: }
276: return(0);
277: }
281: /*@
282: STSetKSP - Sets the KSP object associated with the spectral
283: transformation.
285: Collective on ST287: Input Parameters:
288: + st - the spectral transformation context
289: - ksp - the linear system context
291: Level: advanced
293: @*/
294: PetscErrorCode STSetKSP(ST st,KSP ksp)295: {
302: PetscObjectReference((PetscObject)ksp);
303: KSPDestroy(&st->ksp);
304: st->ksp = ksp;
305: PetscLogObjectParent((PetscObject)st,(PetscObject)st->ksp);
306: return(0);
307: }
311: /*@
312: STGetKSP - Gets the KSP object associated with the spectral
313: transformation.
315: Not Collective
317: Input Parameter:
318: . st - the spectral transformation context
320: Output Parameter:
321: . ksp - the linear system context
323: Notes:
324: On output, the value of ksp can be NULL if the combination of
325: eigenproblem type and selected transformation does not require to
326: solve a linear system of equations.
328: Level: intermediate
330: @*/
331: PetscErrorCode STGetKSP(ST st,KSP* ksp)332: {
338: if (!st->ksp) {
339: KSPCreate(PetscObjectComm((PetscObject)st),&st->ksp);
340: KSPSetOptionsPrefix(st->ksp,((PetscObject)st)->prefix);
341: KSPAppendOptionsPrefix(st->ksp,"st_");
342: PetscObjectIncrementTabLevel((PetscObject)st->ksp,(PetscObject)st,1);
343: PetscLogObjectParent((PetscObject)st,(PetscObject)st->ksp);
344: KSPSetTolerances(st->ksp,SLEPC_DEFAULT_TOL,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);
345: }
346: *ksp = st->ksp;
347: return(0);
348: }
352: PetscErrorCode STCheckNullSpace_Default(ST st,BV V)353: {
355: PetscInt nc,i,c;
356: PetscReal norm;
357: Vec *T,w,vi;
358: Mat A;
359: PC pc;
360: MatNullSpace nullsp;
363: BVGetNumConstraints(V,&nc);
364: PetscMalloc1(nc,&T);
365: if (!st->ksp) { STGetKSP(st,&st->ksp); }
366: KSPGetPC(st->ksp,&pc);
367: PCGetOperators(pc,&A,NULL);
368: MatCreateVecs(A,NULL,&w);
369: c = 0;
370: for (i=0;i<nc;i++) {
371: BVGetColumn(V,-nc+i,&vi);
372: MatMult(A,vi,w);
373: VecNorm(w,NORM_2,&norm);
374: if (norm < 1e-8) {
375: PetscInfo2(st,"Vector %D norm=%g\n",i,(double)norm);
376: BVCreateVec(V,T+c);
377: VecCopy(vi,T[c]);
378: c++;
379: }
380: BVRestoreColumn(V,-nc+i,&vi);
381: }
382: VecDestroy(&w);
383: if (c>0) {
384: MatNullSpaceCreate(PetscObjectComm((PetscObject)st),PETSC_FALSE,c,T,&nullsp);
385: MatSetNullSpace(A,nullsp);
386: MatNullSpaceDestroy(&nullsp);
387: VecDestroyVecs(c,&T);
388: } else {
389: PetscFree(T);
390: }
391: return(0);
392: }
396: /*@
397: STCheckNullSpace - Given a basis vectors object, this function tests each
398: of its constraint vectors to be a nullspace vector of the coefficient
399: matrix of the associated KSP object. All these nullspace vectors are passed
400: to the KSP object.
402: Collective on ST404: Input Parameters:
405: + st - the spectral transformation context
406: - V - basis vectors to be checked
408: Note:
409: This function allows to handle singular pencils and to solve some problems
410: in which the nullspace is important (see the users guide for details).
412: Level: developer
414: .seealso: EPSSetDeflationSpace()
415: @*/
416: PetscErrorCode STCheckNullSpace(ST st,BV V)417: {
419: PetscInt nc;
427: BVGetNumConstraints(V,&nc);
428: if (nc && st->ops->checknullspace) {
429: (*st->ops->checknullspace)(st,V);
430: }
431: return(0);
432: }