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: }