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-2016, 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->state!=ST_STATE_SETUP) { 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->state!=ST_STATE_SETUP) { 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->state!=ST_STATE_SETUP) { 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->state!=ST_STATE_SETUP) { 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
292: @*/
293: PetscErrorCode STSetKSP(ST st,KSP ksp)294: {
301: PetscObjectReference((PetscObject)ksp);
302: KSPDestroy(&st->ksp);
303: st->ksp = ksp;
304: PetscLogObjectParent((PetscObject)st,(PetscObject)st->ksp);
305: return(0);
306: }
310: /*@
311: STGetKSP - Gets the KSP object associated with the spectral
312: transformation.
314: Not Collective
316: Input Parameter:
317: . st - the spectral transformation context
319: Output Parameter:
320: . ksp - the linear system context
322: Level: intermediate
323: @*/
324: PetscErrorCode STGetKSP(ST st,KSP* ksp)325: {
331: if (!st->ksp) {
332: KSPCreate(PetscObjectComm((PetscObject)st),&st->ksp);
333: KSPSetOptionsPrefix(st->ksp,((PetscObject)st)->prefix);
334: KSPAppendOptionsPrefix(st->ksp,"st_");
335: PetscObjectIncrementTabLevel((PetscObject)st->ksp,(PetscObject)st,1);
336: PetscLogObjectParent((PetscObject)st,(PetscObject)st->ksp);
337: KSPSetTolerances(st->ksp,SLEPC_DEFAULT_TOL,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);
338: }
339: *ksp = st->ksp;
340: return(0);
341: }
345: PetscErrorCode STCheckNullSpace_Default(ST st,BV V)346: {
348: PetscInt nc,i,c;
349: PetscReal norm;
350: Vec *T,w,vi;
351: Mat A;
352: PC pc;
353: MatNullSpace nullsp;
356: BVGetNumConstraints(V,&nc);
357: PetscMalloc1(nc,&T);
358: if (!st->ksp) { STGetKSP(st,&st->ksp); }
359: KSPGetPC(st->ksp,&pc);
360: PCGetOperators(pc,&A,NULL);
361: MatCreateVecs(A,NULL,&w);
362: c = 0;
363: for (i=0;i<nc;i++) {
364: BVGetColumn(V,-nc+i,&vi);
365: MatMult(A,vi,w);
366: VecNorm(w,NORM_2,&norm);
367: if (norm < 1e-8) {
368: PetscInfo2(st,"Vector %D norm=%g\n",i,(double)norm);
369: BVCreateVec(V,T+c);
370: VecCopy(vi,T[c]);
371: c++;
372: }
373: BVRestoreColumn(V,-nc+i,&vi);
374: }
375: VecDestroy(&w);
376: if (c>0) {
377: MatNullSpaceCreate(PetscObjectComm((PetscObject)st),PETSC_FALSE,c,T,&nullsp);
378: MatSetNullSpace(A,nullsp);
379: MatNullSpaceDestroy(&nullsp);
380: VecDestroyVecs(c,&T);
381: } else {
382: PetscFree(T);
383: }
384: return(0);
385: }
389: /*@
390: STCheckNullSpace - Given a basis vectors object, this function tests each
391: of its constraint vectors to be a nullspace vector of the coefficient
392: matrix of the associated KSP object. All these nullspace vectors are passed
393: to the KSP object.
395: Collective on ST397: Input Parameters:
398: + st - the spectral transformation context
399: - V - basis vectors to be checked
401: Note:
402: This function allows to handle singular pencils and to solve some problems
403: in which the nullspace is important (see the users guide for details).
405: Level: developer
407: .seealso: EPSSetDeflationSpace()
408: @*/
409: PetscErrorCode STCheckNullSpace(ST st,BV V)410: {
412: PetscInt nc;
420: BVGetNumConstraints(V,&nc);
421: if (nc && st->ops->checknullspace) {
422: (*st->ops->checknullspace)(st,V);
423: }
424: return(0);
425: }