1: /*
2: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
3: SLEPc - Scalable Library for Eigenvalue Problem Computations
4: Copyright (c) 2002-2017, 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: ST interface routines related to the KSP object associated with it
12: */
14: #include <slepc/private/stimpl.h> /*I "slepcst.h" I*/
16: /*
17: This is used to set a default type for the KSP and PC objects.
18: It is called at STSetFromOptions (before KSPSetFromOptions)
19: and also at STSetUp (in case STSetFromOptions was not called).
20: */
21: PetscErrorCode STSetDefaultKSP(ST st) 22: {
28: if (!st->ksp) { STGetKSP(st,&st->ksp); }
29: if (st->ops->setdefaultksp) { (*st->ops->setdefaultksp)(st); }
30: return(0);
31: }
33: /*
34: This is done by all ST types except PRECOND.
35: The default is an LU direct solver, or GMRES+Jacobi if matmode=shell.
36: */
37: PetscErrorCode STSetDefaultKSP_Default(ST st) 38: {
40: PC pc;
41: PCType pctype;
42: KSPType ksptype;
45: KSPGetPC(st->ksp,&pc);
46: KSPGetType(st->ksp,&ksptype);
47: PCGetType(pc,&pctype);
48: if (!pctype && !ksptype) {
49: if (st->shift_matrix == ST_MATMODE_SHELL) {
50: KSPSetType(st->ksp,KSPGMRES);
51: PCSetType(pc,PCJACOBI);
52: } else {
53: KSPSetType(st->ksp,KSPPREONLY);
54: PCSetType(pc,PCLU);
55: }
56: }
57: KSPSetErrorIfNotConverged(st->ksp,PETSC_TRUE);
58: return(0);
59: }
61: /*@
62: STMatMult - Computes the matrix-vector product y = T[k] x, where T[k] is
63: the k-th matrix of the spectral transformation.
65: Collective on ST 67: Input Parameters:
68: + st - the spectral transformation context
69: . k - index of matrix to use
70: - x - the vector to be multiplied
72: Output Parameter:
73: . y - the result
75: Level: developer
77: .seealso: STMatMultTranspose()
78: @*/
79: PetscErrorCode STMatMult(ST st,PetscInt k,Vec x,Vec y) 80: {
88: STCheckMatrices(st,1);
89: if (k<0 || k>=PetscMax(2,st->nmat)) SETERRQ1(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_OUTOFRANGE,"k must be between 0 and %D",st->nmat);
90: if (x == y) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_IDN,"x and y must be different vectors");
91: VecLocked(y,3);
93: if (st->state!=ST_STATE_SETUP) { STSetUp(st); }
94: VecLockPush(x);
95: PetscLogEventBegin(ST_MatMult,st,x,y,0);
96: if (!st->T[k]) {
97: /* T[k]=NULL means identity matrix */
98: VecCopy(x,y);
99: } else {
100: MatMult(st->T[k],x,y);
101: }
102: PetscLogEventEnd(ST_MatMult,st,x,y,0);
103: VecLockPop(x);
104: return(0);
105: }
107: /*@
108: STMatMultTranspose - Computes the matrix-vector product y = T[k]' x, where T[k] is
109: the k-th matrix of the spectral transformation.
111: Collective on ST113: Input Parameters:
114: + st - the spectral transformation context
115: . k - index of matrix to use
116: - x - the vector to be multiplied
118: Output Parameter:
119: . y - the result
121: Level: developer
123: .seealso: STMatMult()
124: @*/
125: PetscErrorCode STMatMultTranspose(ST st,PetscInt k,Vec x,Vec y)126: {
134: STCheckMatrices(st,1);
135: if (k<0 || k>=PetscMax(2,st->nmat)) SETERRQ1(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_OUTOFRANGE,"k must be between 0 and %D",st->nmat);
136: if (x == y) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_IDN,"x and y must be different vectors");
137: VecLocked(y,3);
139: if (st->state!=ST_STATE_SETUP) { STSetUp(st); }
140: VecLockPush(x);
141: PetscLogEventBegin(ST_MatMultTranspose,st,x,y,0);
142: if (!st->T[k]) {
143: /* T[k]=NULL means identity matrix */
144: VecCopy(x,y);
145: } else {
146: MatMultTranspose(st->T[k],x,y);
147: }
148: PetscLogEventEnd(ST_MatMultTranspose,st,x,y,0);
149: VecLockPop(x);
150: return(0);
151: }
153: /*@
154: STMatSolve - Solves P x = b, where P is the preconditioner matrix of
155: the spectral transformation, using a KSP object stored internally.
157: Collective on ST159: Input Parameters:
160: + st - the spectral transformation context
161: - b - right hand side vector
163: Output Parameter:
164: . x - computed solution
166: Level: developer
168: .seealso: STMatSolveTranspose()
169: @*/
170: PetscErrorCode STMatSolve(ST st,Vec b,Vec x)171: {
173: PetscInt its;
174: PetscBool flg;
180: STCheckMatrices(st,1);
181: if (x == b) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
182: VecLocked(x,3);
184: if (st->state!=ST_STATE_SETUP) { STSetUp(st); }
185: VecLockPush(b);
186: PetscLogEventBegin(ST_MatSolve,st,b,x,0);
187: PetscObjectTypeCompareAny((PetscObject)st,&flg,STPRECOND,STSHELL,"");
188: if (!flg && !st->P) {
189: /* P=NULL means identity matrix */
190: VecCopy(b,x);
191: return(0);
192: }
193: if (!st->ksp) { STGetKSP(st,&st->ksp); }
194: KSPSolve(st->ksp,b,x);
195: KSPGetIterationNumber(st->ksp,&its);
196: PetscInfo1(st,"Linear solve iterations=%D\n",its);
197: PetscLogEventEnd(ST_MatSolve,st,b,x,0);
198: VecLockPop(b);
199: return(0);
200: }
202: /*@
203: STMatSolveTranspose - Solves P' x = b, where P is the preconditioner matrix of
204: the spectral transformation, using a KSP object stored internally.
206: Collective on ST208: Input Parameters:
209: . st - the spectral transformation context
210: . b - right hand side vector
212: Output Parameter:
213: . x - computed solution
215: Level: developer
217: .seealso: STMatSolve()
218: @*/
219: PetscErrorCode STMatSolveTranspose(ST st,Vec b,Vec x)220: {
222: PetscInt its;
223: PetscBool flg;
229: STCheckMatrices(st,1);
230: if (x == b) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_IDN,"x and b must be different vectors");
231: VecLocked(x,3);
233: if (st->state!=ST_STATE_SETUP) { STSetUp(st); }
234: VecLockPush(b);
235: PetscLogEventBegin(ST_MatSolveTranspose,st,b,x,0);
236: PetscObjectTypeCompareAny((PetscObject)st,&flg,STPRECOND,STSHELL,"");
237: if (!flg && !st->P) {
238: /* P=NULL means identity matrix */
239: VecCopy(b,x);
240: return(0);
241: }
242: if (!st->ksp) { STGetKSP(st,&st->ksp); }
243: KSPSolveTranspose(st->ksp,b,x);
244: KSPGetIterationNumber(st->ksp,&its);
245: PetscInfo1(st,"Linear solve iterations=%D\n",its);
246: PetscLogEventEnd(ST_MatSolveTranspose,st,b,x,0);
247: VecLockPop(b);
248: return(0);
249: }
251: /*
252: STMatSetHermitian - Sets the Hermitian flag to the ST matrix.
254: Input Parameters:
255: . st - the spectral transformation context
256: . M - matrix
257: */
258: PetscErrorCode STMatSetHermitian(ST st,Mat M)259: {
260: #if defined(PETSC_USE_COMPLEX)
262: PetscBool set,aherm,mherm;
263: PetscInt i;
264: #endif
267: #if defined(PETSC_USE_COMPLEX)
268: mherm = PETSC_FALSE;
269: for (i=0;i<st->nmat;i++) {
270: MatIsHermitianKnown(st->A[i],&set,&aherm);
271: if (!set) aherm = PETSC_FALSE;
272: mherm = (mherm && aherm)? PETSC_TRUE: PETSC_FALSE;
273: if (PetscRealPart(st->sigma)==0.0) break;
274: }
275: mherm = (mherm && PetscImaginaryPart(st->sigma)==0.0)? PETSC_TRUE: PETSC_FALSE;
276: MatSetOption(M,MAT_HERMITIAN,mherm);
277: #endif
278: return(0);
279: }
281: PetscErrorCode STCheckFactorPackage(ST st)282: {
283: PetscErrorCode ierr;
284: PC pc;
285: PetscMPIInt size;
286: PetscBool flg;
287: const MatSolverPackage stype;
290: MPI_Comm_size(PetscObjectComm((PetscObject)st),&size);
291: if (size==1) return(0);
292: KSPGetPC(st->ksp,&pc);
293: PCFactorGetMatSolverPackage(pc,&stype);
294: if (stype) { /* currently selected PC is a factorization */
295: PetscStrcmp(stype,MATSOLVERPETSC,&flg);
296: 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");
297: }
298: return(0);
299: }
301: /*@
302: STSetKSP - Sets the KSP object associated with the spectral
303: transformation.
305: Collective on ST307: Input Parameters:
308: + st - the spectral transformation context
309: - ksp - the linear system context
311: Level: advanced
312: @*/
313: PetscErrorCode STSetKSP(ST st,KSP ksp)314: {
321: PetscObjectReference((PetscObject)ksp);
322: KSPDestroy(&st->ksp);
323: st->ksp = ksp;
324: PetscLogObjectParent((PetscObject)st,(PetscObject)st->ksp);
325: return(0);
326: }
328: /*@
329: STGetKSP - Gets the KSP object associated with the spectral
330: transformation.
332: Not Collective
334: Input Parameter:
335: . st - the spectral transformation context
337: Output Parameter:
338: . ksp - the linear system context
340: Level: intermediate
341: @*/
342: PetscErrorCode STGetKSP(ST st,KSP* ksp)343: {
349: if (!st->ksp) {
350: KSPCreate(PetscObjectComm((PetscObject)st),&st->ksp);
351: KSPSetOptionsPrefix(st->ksp,((PetscObject)st)->prefix);
352: KSPAppendOptionsPrefix(st->ksp,"st_");
353: PetscObjectIncrementTabLevel((PetscObject)st->ksp,(PetscObject)st,1);
354: PetscLogObjectParent((PetscObject)st,(PetscObject)st->ksp);
355: KSPSetTolerances(st->ksp,SLEPC_DEFAULT_TOL,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);
356: }
357: *ksp = st->ksp;
358: return(0);
359: }
361: PetscErrorCode STCheckNullSpace_Default(ST st,BV V)362: {
364: PetscInt nc,i,c;
365: PetscReal norm;
366: Vec *T,w,vi;
367: Mat A;
368: PC pc;
369: MatNullSpace nullsp;
372: BVGetNumConstraints(V,&nc);
373: PetscMalloc1(nc,&T);
374: if (!st->ksp) { STGetKSP(st,&st->ksp); }
375: KSPGetPC(st->ksp,&pc);
376: PCGetOperators(pc,&A,NULL);
377: MatCreateVecs(A,NULL,&w);
378: c = 0;
379: for (i=0;i<nc;i++) {
380: BVGetColumn(V,-nc+i,&vi);
381: MatMult(A,vi,w);
382: VecNorm(w,NORM_2,&norm);
383: if (norm < 1e-8) {
384: PetscInfo2(st,"Vector %D norm=%g\n",i,(double)norm);
385: BVCreateVec(V,T+c);
386: VecCopy(vi,T[c]);
387: c++;
388: }
389: BVRestoreColumn(V,-nc+i,&vi);
390: }
391: VecDestroy(&w);
392: if (c>0) {
393: MatNullSpaceCreate(PetscObjectComm((PetscObject)st),PETSC_FALSE,c,T,&nullsp);
394: MatSetNullSpace(A,nullsp);
395: MatNullSpaceDestroy(&nullsp);
396: VecDestroyVecs(c,&T);
397: } else {
398: PetscFree(T);
399: }
400: return(0);
401: }
403: /*@
404: STCheckNullSpace - Given a basis vectors object, this function tests each
405: of its constraint vectors to be a nullspace vector of the coefficient
406: matrix of the associated KSP object. All these nullspace vectors are passed
407: to the KSP object.
409: Collective on ST411: Input Parameters:
412: + st - the spectral transformation context
413: - V - basis vectors to be checked
415: Note:
416: This function allows to handle singular pencils and to solve some problems
417: in which the nullspace is important (see the users guide for details).
419: Level: developer
421: .seealso: EPSSetDeflationSpace()
422: @*/
423: PetscErrorCode STCheckNullSpace(ST st,BV V)424: {
426: PetscInt nc;
433: if (!st->state) SETERRQ(PetscObjectComm((PetscObject)st),PETSC_ERR_ARG_WRONGSTATE,"Must call STSolve() first");
435: BVGetNumConstraints(V,&nc);
436: if (nc && st->ops->checknullspace) {
437: (*st->ops->checknullspace)(st,V);
438: }
439: return(0);
440: }