Actual source code: stsolve.c

  1: /*
  2:     The ST (spectral transformation) interface routines, callable by users.

  4:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  5:    SLEPc - Scalable Library for Eigenvalue Problem Computations
  6:    Copyright (c) 2002-2012, Universitat Politecnica de Valencia, Spain

  8:    This file is part of SLEPc.
  9:       
 10:    SLEPc is free software: you can redistribute it and/or modify it under  the
 11:    terms of version 3 of the GNU Lesser General Public License as published by
 12:    the Free Software Foundation.

 14:    SLEPc  is  distributed in the hope that it will be useful, but WITHOUT  ANY 
 15:    WARRANTY;  without even the implied warranty of MERCHANTABILITY or  FITNESS 
 16:    FOR  A  PARTICULAR PURPOSE. See the GNU Lesser General Public  License  for 
 17:    more details.

 19:    You  should have received a copy of the GNU Lesser General  Public  License
 20:    along with SLEPc. If not, see <http://www.gnu.org/licenses/>.
 21:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 22: */

 24: #include <slepc-private/stimpl.h>            /*I "slepcst.h" I*/

 28: /*@
 29:    STApply - Applies the spectral transformation operator to a vector, for
 30:    instance (A - sB)^-1 B in the case of the shift-and-invert tranformation
 31:    and generalized eigenproblem.

 33:    Collective on ST and Vec

 35:    Input Parameters:
 36: +  st - the spectral transformation context
 37: -  x  - input vector

 39:    Output Parameter:
 40: .  y - output vector

 42:    Level: developer

 44: .seealso: STApplyTranspose()
 45: @*/
 46: PetscErrorCode STApply(ST st,Vec x,Vec y)
 47: {

 54:   if (x == y) SETERRQ(((PetscObject)st)->comm,PETSC_ERR_ARG_IDN,"x and y must be different vectors");

 56:   if (!st->setupcalled) { STSetUp(st); }

 58:   if (!st->ops->apply) SETERRQ(((PetscObject)st)->comm,PETSC_ERR_SUP,"ST does not have apply");
 59:   PetscLogEventBegin(ST_Apply,st,x,y,0);
 60:   st->applys++;
 61:   if (st->D) { /* with balancing */
 62:     VecPointwiseDivide(st->wb,x,st->D);
 63:     (*st->ops->apply)(st,st->wb,y);
 64:     VecPointwiseMult(y,y,st->D);
 65:   }
 66:   else {
 67:     (*st->ops->apply)(st,x,y);
 68:   }
 69:   PetscLogEventEnd(ST_Apply,st,x,y,0);
 70:   return(0);
 71: }

 75: /*@
 76:    STGetBilinearForm - Returns the matrix used in the bilinear form with a 
 77:    generalized problem with semi-definite B.

 79:    Not collective, though a parallel Mat may be returned

 81:    Input Parameters:
 82: .  st - the spectral transformation context

 84:    Output Parameter:
 85: .  B - output matrix

 87:    Notes:
 88:    The output matrix B must be destroyed after use. It will be PETSC_NULL in
 89:    case of standard eigenproblems.
 90:    
 91:    Level: developer
 92: @*/
 93: PetscErrorCode STGetBilinearForm(ST st,Mat *B)
 94: {

100:   (*st->ops->getbilinearform)(st,B);
101:   return(0);
102: }

106: PetscErrorCode STGetBilinearForm_Default(ST st,Mat *B)
107: {

111:   *B = st->B;
112:   if (*B) {
113:      PetscObjectReference((PetscObject)*B);
114:   }
115:   return(0);
116: }

120: /*@
121:    STApplyTranspose - Applies the transpose of the operator to a vector, for
122:    instance B^T(A - sB)^-T in the case of the shift-and-invert tranformation
123:    and generalized eigenproblem.

125:    Collective on ST and Vec

127:    Input Parameters:
128: +  st - the spectral transformation context
129: -  x  - input vector

131:    Output Parameter:
132: .  y - output vector

134:    Level: developer

136: .seealso: STApply()
137: @*/
138: PetscErrorCode STApplyTranspose(ST st,Vec x,Vec y)
139: {

146:   if (x == y) SETERRQ(((PetscObject)st)->comm,PETSC_ERR_ARG_IDN,"x and y must be different vectors");

148:   if (!st->setupcalled) { STSetUp(st); }

150:   if (!st->ops->applytrans) SETERRQ(((PetscObject)st)->comm,PETSC_ERR_SUP,"ST does not have applytrans");
151:   PetscLogEventBegin(ST_ApplyTranspose,st,x,y,0);
152:   st->applys++;
153:   if (st->D) { /* with balancing */
154:     VecPointwiseMult(st->wb,x,st->D);
155:     (*st->ops->applytrans)(st,st->wb,y);
156:     VecPointwiseDivide(y,y,st->D);
157:   }
158:   else {
159:     (*st->ops->applytrans)(st,x,y);
160:   }
161:   PetscLogEventEnd(ST_ApplyTranspose,st,x,y,0);
162:   return(0);
163: }

167: /*@
168:    STComputeExplicitOperator - Computes the explicit operator associated
169:    to the eigenvalue problem with the specified spectral transformation.  

171:    Collective on ST

173:    Input Parameter:
174: .  st - the spectral transform context

176:    Output Parameter:
177: .  mat - the explicit operator

179:    Notes:
180:    This routine builds a matrix containing the explicit operator. For 
181:    example, in generalized problems with shift-and-invert spectral
182:    transformation the result would be matrix (A - s B)^-1 B.

184:    This computation is done by applying the operator to columns of the 
185:    identity matrix. This is analogous to MatComputeExplicitOperator().

187:    Level: advanced

189: .seealso: STApply()   
190: @*/
191: PetscErrorCode STComputeExplicitOperator(ST st,Mat *mat)
192: {
193:   PetscErrorCode    ierr;
194:   Vec               in,out;
195:   PetscInt          i,M,m,*rows,start,end;
196:   const PetscScalar *array;
197:   PetscScalar       one = 1.0;
198:   PetscMPIInt       size;

203:   MPI_Comm_size(((PetscObject)st)->comm,&size);

205:   MatGetVecs(st->A,&in,&out);
206:   VecGetSize(out,&M);
207:   VecGetLocalSize(out,&m);
208:   VecSetOption(in,VEC_IGNORE_OFF_PROC_ENTRIES,PETSC_TRUE);
209:   VecGetOwnershipRange(out,&start,&end);
210:   PetscMalloc(m*sizeof(PetscInt),&rows);
211:   for (i=0;i<m;i++) rows[i] = start + i;

213:   MatCreate(((PetscObject)st)->comm,mat);
214:   MatSetSizes(*mat,m,m,M,M);
215:   if (size == 1) {
216:     MatSetType(*mat,MATSEQDENSE);
217:     MatSeqDenseSetPreallocation(*mat,PETSC_NULL);
218:   } else {
219:     MatSetType(*mat,MATMPIAIJ);
220:     MatMPIAIJSetPreallocation(*mat,m,PETSC_NULL,M-m,PETSC_NULL);
221:   }

223:   for (i=0;i<M;i++) {
224:     VecSet(in,0.0);
225:     VecSetValues(in,1,&i,&one,INSERT_VALUES);
226:     VecAssemblyBegin(in);
227:     VecAssemblyEnd(in);

229:     STApply(st,in,out);
230: 
231:     VecGetArrayRead(out,&array);
232:     MatSetValues(*mat,m,rows,1,&i,array,INSERT_VALUES);
233:     VecRestoreArrayRead(out,&array);
234:   }
235:   PetscFree(rows);
236:   VecDestroy(&in);
237:   VecDestroy(&out);
238:   MatAssemblyBegin(*mat,MAT_FINAL_ASSEMBLY);
239:   MatAssemblyEnd(*mat,MAT_FINAL_ASSEMBLY);
240:   return(0);
241: }

245: /*@
246:    STSetUp - Prepares for the use of a spectral transformation.

248:    Collective on ST

250:    Input Parameter:
251: .  st - the spectral transformation context

253:    Level: advanced

255: .seealso: STCreate(), STApply(), STDestroy()
256: @*/
257: PetscErrorCode STSetUp(ST st)
258: {
259:   PetscInt       n,k;

264:   if (!st->A) SETERRQ(((PetscObject)st)->comm,PETSC_ERR_ARG_WRONGSTATE,"Matrix must be set first");
265:   if (st->setupcalled) return(0);
266:   PetscInfo(st,"Setting up new ST\n");
267:   PetscLogEventBegin(ST_SetUp,st,0,0,0);
268:   if (!((PetscObject)st)->type_name) {
269:     STSetType(st,STSHIFT);
270:   }
271:   VecDestroy(&st->w);
272:   MatGetVecs(st->A,&st->w,PETSC_NULL);
273:   if (st->D) {
274:     MatGetLocalSize(st->A,PETSC_NULL,&n);
275:     VecGetLocalSize(st->D,&k);
276:     if (n != k) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Balance matrix has wrong dimension %D (should be %D)",k,n);
277:     VecDestroy(&st->wb);
278:     VecDuplicate(st->D,&st->wb);
279:   }
280:   if (st->ops->setup) { (*st->ops->setup)(st); }
281:   st->setupcalled = 1;
282:   PetscLogEventEnd(ST_SetUp,st,0,0,0);
283:   return(0);
284: }

288: /*@
289:    STPostSolve - Optional post-solve phase, intended for any actions that must 
290:    be performed on the ST object after the eigensolver has finished.

292:    Collective on ST

294:    Input Parameters:
295: .  st  - the spectral transformation context

297:    Level: developer

299: .seealso: EPSSolve()
300: @*/
301: PetscErrorCode STPostSolve(ST st)
302: {

307:   if (st->ops->postsolve) {
308:     (*st->ops->postsolve)(st);
309:   }
310:   return(0);
311: }

315: /*@
316:    STBackTransform - Back-transformation phase, intended for 
317:    spectral transformations which require to transform the computed 
318:    eigenvalues back to the original eigenvalue problem.

320:    Not Collective

322:    Input Parameters:
323:    st   - the spectral transformation context
324:    eigr - real part of a computed eigenvalue
325:    eigi - imaginary part of a computed eigenvalue

327:    Level: developer
328: @*/
329: PetscErrorCode STBackTransform(ST st,PetscInt n,PetscScalar* eigr,PetscScalar* eigi)
330: {

335:   if (st->ops->backtr) {
336:     (*st->ops->backtr)(st,n,eigr,eigi);
337:   }
338:   return(0);
339: }