Actual source code: stsles.c

slepc-3.6.1 2015-09-03
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-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 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->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 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->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 ST

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

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