Actual source code: stsles.c

slepc-3.7.2 2016-07-19
Report Typos and Errors
  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 ST

131:    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 ST

182:    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 ST

287:    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 ST

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