Actual source code: peprefine.c

slepc-3.17.0 2022-03-31
Report Typos and Errors
  1: /*
  2:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  3:    SLEPc - Scalable Library for Eigenvalue Problem Computations
  4:    Copyright (c) 2002-, 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:    Newton refinement for PEP, simple version
 12: */

 14: #include <slepc/private/pepimpl.h>
 15: #include <slepcblaslapack.h>

 17: #define NREF_MAXIT 10

 19: typedef struct {
 20:   VecScatter *scatter_id,nst;
 21:   Mat        *A;
 22:   Vec        nv,vg,v,w;
 23: } PEPSimpNRefctx;

 25: typedef struct {
 26:   Mat          M1;
 27:   Vec          M2,M3;
 28:   PetscScalar  M4,m3;
 29: } PEP_REFINES_MATSHELL;

 31: static PetscErrorCode MatMult_FS(Mat M ,Vec x,Vec y)
 32: {
 33:   PEP_REFINES_MATSHELL *ctx;
 34:   PetscScalar          t;

 36:   MatShellGetContext(M,&ctx);
 37:   VecDot(x,ctx->M3,&t);
 38:   t *= ctx->m3/ctx->M4;
 39:   MatMult(ctx->M1,x,y);
 40:   VecAXPY(y,-t,ctx->M2);
 41:   PetscFunctionReturn(0);
 42: }

 44: static PetscErrorCode PEPSimpleNRefSetUp(PEP pep,PEPSimpNRefctx **ctx_)
 45: {
 46:   PetscInt       i,si,j,n0,m0,nloc,*idx1,*idx2,ne;
 47:   IS             is1,is2;
 48:   PEPSimpNRefctx *ctx;
 49:   Vec            v;
 50:   PetscMPIInt    rank,size;
 51:   MPI_Comm       child;

 53:   PetscCalloc1(1,ctx_);
 54:   ctx = *ctx_;
 55:   if (pep->npart==1) {
 56:     pep->refinesubc = NULL;
 57:     ctx->scatter_id = NULL;
 58:     ctx->A = pep->A;
 59:   } else {
 60:     PetscSubcommGetChild(pep->refinesubc,&child);
 61:     PetscMalloc2(pep->nmat,&ctx->A,pep->npart,&ctx->scatter_id);

 63:     /* Duplicate matrices */
 64:     for (i=0;i<pep->nmat;i++) {
 65:       MatCreateRedundantMatrix(pep->A[i],0,child,MAT_INITIAL_MATRIX,&ctx->A[i]);
 66:       PetscLogObjectParent((PetscObject)pep,(PetscObject)ctx->A[i]);
 67:     }
 68:     MatCreateVecs(ctx->A[0],&ctx->v,NULL);
 69:     PetscLogObjectParent((PetscObject)pep,(PetscObject)ctx->v);

 71:     /* Create scatters for sending vectors to each subcommucator */
 72:     BVGetColumn(pep->V,0,&v);
 73:     VecGetOwnershipRange(v,&n0,&m0);
 74:     BVRestoreColumn(pep->V,0,&v);
 75:     VecGetLocalSize(ctx->v,&nloc);
 76:     PetscMalloc2(m0-n0,&idx1,m0-n0,&idx2);
 77:     VecCreateMPI(PetscObjectComm((PetscObject)pep),nloc,PETSC_DECIDE,&ctx->vg);
 78:     for (si=0;si<pep->npart;si++) {
 79:       j = 0;
 80:       for (i=n0;i<m0;i++) {
 81:         idx1[j]   = i;
 82:         idx2[j++] = i+pep->n*si;
 83:       }
 84:       ISCreateGeneral(PetscObjectComm((PetscObject)pep),(m0-n0),idx1,PETSC_COPY_VALUES,&is1);
 85:       ISCreateGeneral(PetscObjectComm((PetscObject)pep),(m0-n0),idx2,PETSC_COPY_VALUES,&is2);
 86:       BVGetColumn(pep->V,0,&v);
 87:       VecScatterCreate(v,is1,ctx->vg,is2,&ctx->scatter_id[si]);
 88:       BVRestoreColumn(pep->V,0,&v);
 89:       ISDestroy(&is1);
 90:       ISDestroy(&is2);
 91:     }
 92:     PetscFree2(idx1,idx2);
 93:   }
 94:   if (pep->scheme==PEP_REFINE_SCHEME_EXPLICIT) {
 95:     MPI_Comm_rank(PetscObjectComm((PetscObject)ctx->A[0]),&rank);
 96:     MPI_Comm_size(PetscObjectComm((PetscObject)ctx->A[0]),&size);
 97:     if (size>1) {
 98:       if (pep->npart==1) BVGetColumn(pep->V,0,&v);
 99:       else v = ctx->v;
100:       VecGetOwnershipRange(v,&n0,&m0);
101:       ne = (rank == size-1)?pep->n:0;
102:       VecCreateMPI(PetscObjectComm((PetscObject)ctx->A[0]),ne,PETSC_DECIDE,&ctx->nv);
103:       PetscMalloc1(m0-n0,&idx1);
104:       for (i=n0;i<m0;i++) idx1[i-n0] = i;
105:       ISCreateGeneral(PetscObjectComm((PetscObject)ctx->A[0]),(m0-n0),idx1,PETSC_COPY_VALUES,&is1);
106:       VecScatterCreate(v,is1,ctx->nv,is1,&ctx->nst);
107:       if (pep->npart==1) BVRestoreColumn(pep->V,0,&v);
108:       PetscFree(idx1);
109:       ISDestroy(&is1);
110:     }
111:   }
112:   PetscFunctionReturn(0);
113: }

115: /*
116:   Gather Eigenpair idx from subcommunicator with color sc
117: */
118: static PetscErrorCode PEPSimpleNRefGatherEigenpair(PEP pep,PEPSimpNRefctx *ctx,PetscInt sc,PetscInt idx,PetscInt *fail)
119: {
120:   PetscMPIInt       nproc,p;
121:   MPI_Comm          comm=((PetscObject)pep)->comm;
122:   Vec               v;
123:   const PetscScalar *array;

125:   MPI_Comm_size(comm,&nproc);
126:   p = (nproc/pep->npart)*(sc+1)+PetscMin(nproc%pep->npart,sc+1)-1;
127:   if (pep->npart>1) {
128:     /* Communicate convergence successful */
129:     MPI_Bcast(fail,1,MPIU_INT,p,comm);
130:     if (!(*fail)) {
131:       /* Process 0 of subcommunicator sc broadcasts the eigenvalue */
132:       MPI_Bcast(&pep->eigr[idx],1,MPIU_SCALAR,p,comm);
133:       /* Gather pep->V[idx] from the subcommuniator sc */
134:       BVGetColumn(pep->V,idx,&v);
135:       if (pep->refinesubc->color==sc) {
136:         VecGetArrayRead(ctx->v,&array);
137:         VecPlaceArray(ctx->vg,array);
138:       }
139:       VecScatterBegin(ctx->scatter_id[sc],ctx->vg,v,INSERT_VALUES,SCATTER_REVERSE);
140:       VecScatterEnd(ctx->scatter_id[sc],ctx->vg,v,INSERT_VALUES,SCATTER_REVERSE);
141:       if (pep->refinesubc->color==sc) {
142:         VecResetArray(ctx->vg);
143:         VecRestoreArrayRead(ctx->v,&array);
144:       }
145:       BVRestoreColumn(pep->V,idx,&v);
146:     }
147:   } else {
148:     if (pep->scheme==PEP_REFINE_SCHEME_EXPLICIT && !(*fail)) MPI_Bcast(&pep->eigr[idx],1,MPIU_SCALAR,p,comm);
149:   }
150:   PetscFunctionReturn(0);
151: }

153: static PetscErrorCode PEPSimpleNRefScatterEigenvector(PEP pep,PEPSimpNRefctx *ctx,PetscInt sc,PetscInt idx)
154: {
155:   Vec               v;
156:   const PetscScalar *array;

158:   if (pep->npart>1) {
159:     BVGetColumn(pep->V,idx,&v);
160:     if (pep->refinesubc->color==sc) {
161:       VecGetArrayRead(ctx->v,&array);
162:       VecPlaceArray(ctx->vg,array);
163:     }
164:     VecScatterBegin(ctx->scatter_id[sc],v,ctx->vg,INSERT_VALUES,SCATTER_FORWARD);
165:     VecScatterEnd(ctx->scatter_id[sc],v,ctx->vg,INSERT_VALUES,SCATTER_FORWARD);
166:     if (pep->refinesubc->color==sc) {
167:       VecResetArray(ctx->vg);
168:       VecRestoreArrayRead(ctx->v,&array);
169:     }
170:     BVRestoreColumn(pep->V,idx,&v);
171:   }
172:   PetscFunctionReturn(0);
173: }

175: static PetscErrorCode PEPEvaluateFunctionDerivatives(PEP pep,PetscScalar alpha,PetscScalar *vals)
176: {
177:   PetscInt    i,nmat=pep->nmat;
178:   PetscScalar a0,a1,a2;
179:   PetscReal   *a=pep->pbc,*b=a+nmat,*g=b+nmat;

181:   a0 = 0.0;
182:   a1 = 1.0;
183:   vals[0] = 0.0;
184:   if (nmat>1) vals[1] = 1/a[0];
185:   for (i=2;i<nmat;i++) {
186:     a2 = ((alpha-b[i-2])*a1-g[i-2]*a0)/a[i-2];
187:     vals[i] = (a2+(alpha-b[i-1])*vals[i-1]-g[i-1]*vals[i-2])/a[i-1];
188:     a0 = a1; a1 = a2;
189:   }
190:   PetscFunctionReturn(0);
191: }

193: static PetscErrorCode PEPSimpleNRefSetUpSystem(PEP pep,Mat *A,PEPSimpNRefctx *ctx,PetscInt idx,Mat *Mt,Mat *T,Mat *P,PetscBool ini,Vec t,Vec v)
194: {
195:   PetscErrorCode       ierr;
196:   PetscInt             i,nmat=pep->nmat,ml,m0,n0,m1,mg;
197:   PetscInt             *dnz,*onz,ncols,*cols2=NULL,*nnz;
198:   PetscScalar          zero=0.0,*coeffs,*coeffs2;
199:   PetscMPIInt          rank,size;
200:   MPI_Comm             comm;
201:   const PetscInt       *cols;
202:   const PetscScalar    *vals,*array;
203:   MatStructure         str;
204:   PEP_REFINES_MATSHELL *fctx;
205:   PEPRefineScheme      scheme=pep->scheme;
206:   Vec                  w=ctx->w;
207:   Mat                  M;

209:   STGetMatStructure(pep->st,&str);
210:   PetscMalloc2(nmat,&coeffs,nmat,&coeffs2);
211:   switch (scheme) {
212:   case PEP_REFINE_SCHEME_SCHUR:
213:     if (ini) {
214:       PetscCalloc1(1,&fctx);
215:       MatGetSize(A[0],&m0,&n0);
216:       MatCreateShell(PetscObjectComm((PetscObject)A[0]),PETSC_DECIDE,PETSC_DECIDE,m0,n0,fctx,T);
217:       MatShellSetOperation(*T,MATOP_MULT,(void(*)(void))MatMult_FS);
218:     } else MatShellGetContext(*T,&fctx);
219:     M=fctx->M1;
220:     break;
221:   case PEP_REFINE_SCHEME_MBE:
222:     M=*T;
223:     break;
224:   case PEP_REFINE_SCHEME_EXPLICIT:
225:     M=*Mt;
226:     break;
227:   }
228:   if (ini) MatDuplicate(A[0],MAT_COPY_VALUES,&M);
229:   else MatCopy(A[0],M,DIFFERENT_NONZERO_PATTERN);
230:   PEPEvaluateBasis(pep,pep->eigr[idx],0,coeffs,NULL);
231:   MatScale(M,coeffs[0]);
232:   for (i=1;i<nmat;i++) MatAXPY(M,coeffs[i],A[i],(ini)?str:SUBSET_NONZERO_PATTERN);
233:   PEPEvaluateFunctionDerivatives(pep,pep->eigr[idx],coeffs2);
234:   for (i=0;i<nmat && PetscAbsScalar(coeffs2[i])==0.0;i++);
235:   MatMult(A[i],v,w);
236:   if (coeffs2[i]!=1.0) VecScale(w,coeffs2[i]);
237:   for (i++;i<nmat;i++) {
238:     MatMult(A[i],v,t);
239:     VecAXPY(w,coeffs2[i],t);
240:   }
241:   switch (scheme) {
242:   case PEP_REFINE_SCHEME_EXPLICIT:
243:     comm = PetscObjectComm((PetscObject)A[0]);
244:     MPI_Comm_rank(comm,&rank);
245:     MPI_Comm_size(comm,&size);
246:     MatGetSize(M,&mg,NULL);
247:     MatGetOwnershipRange(M,&m0,&m1);
248:     if (ini) {
249:       MatCreate(comm,T);
250:       MatGetLocalSize(M,&ml,NULL);
251:       if (rank==size-1) ml++;
252:       MatSetSizes(*T,ml,ml,mg+1,mg+1);
253:       MatSetFromOptions(*T);
254:       MatSetUp(*T);
255:       /* Preallocate M */
256:       if (size>1) {
257:         ierr = MatPreallocateInitialize(comm,ml,ml,dnz,onz);
258:         for (i=m0;i<m1;i++) {
259:           MatGetRow(M,i,&ncols,&cols,NULL);
260:           MatPreallocateSet(i,ncols,cols,dnz,onz);
261:           MatPreallocateSet(i,1,&mg,dnz,onz);
262:           MatRestoreRow(M,i,&ncols,&cols,NULL);
263:         }
264:         if (rank==size-1) {
265:           PetscCalloc1(mg+1,&cols2);
266:           for (i=0;i<mg+1;i++) cols2[i]=i;
267:           MatPreallocateSet(m1,mg+1,cols2,dnz,onz);
268:           PetscFree(cols2);
269:         }
270:         MatMPIAIJSetPreallocation(*T,0,dnz,0,onz);
271:         ierr = MatPreallocateFinalize(dnz,onz);
272:       } else {
273:         PetscCalloc1(mg+1,&nnz);
274:         for (i=0;i<mg;i++) {
275:           MatGetRow(M,i,&ncols,NULL,NULL);
276:           nnz[i] = ncols+1;
277:           MatRestoreRow(M,i,&ncols,NULL,NULL);
278:         }
279:         nnz[mg] = mg+1;
280:         MatSeqAIJSetPreallocation(*T,0,nnz);
281:         PetscFree(nnz);
282:       }
283:       *Mt = M;
284:       *P  = *T;
285:     }

287:     /* Set values */
288:     VecGetArrayRead(w,&array);
289:     for (i=m0;i<m1;i++) {
290:       MatGetRow(M,i,&ncols,&cols,&vals);
291:       MatSetValues(*T,1,&i,ncols,cols,vals,INSERT_VALUES);
292:       MatRestoreRow(M,i,&ncols,&cols,&vals);
293:       MatSetValues(*T,1,&i,1,&mg,array+i-m0,INSERT_VALUES);
294:     }
295:     VecRestoreArrayRead(w,&array);
296:     VecConjugate(v);
297:     MPI_Comm_size(PetscObjectComm((PetscObject)A[0]),&size);
298:     MPI_Comm_rank(PetscObjectComm((PetscObject)A[0]),&rank);
299:     if (size>1) {
300:       if (rank==size-1) {
301:         PetscMalloc1(pep->n,&cols2);
302:         for (i=0;i<pep->n;i++) cols2[i]=i;
303:       }
304:       VecScatterBegin(ctx->nst,v,ctx->nv,INSERT_VALUES,SCATTER_FORWARD);
305:       VecScatterEnd(ctx->nst,v,ctx->nv,INSERT_VALUES,SCATTER_FORWARD);
306:       VecGetArrayRead(ctx->nv,&array);
307:       if (rank==size-1) {
308:         MatSetValues(*T,1,&mg,pep->n,cols2,array,INSERT_VALUES);
309:         MatSetValues(*T,1,&mg,1,&mg,&zero,INSERT_VALUES);
310:       }
311:         VecRestoreArrayRead(ctx->nv,&array);
312:     } else {
313:       PetscMalloc1(m1-m0,&cols2);
314:       for (i=0;i<m1-m0;i++) cols2[i]=m0+i;
315:       VecGetArrayRead(v,&array);
316:       MatSetValues(*T,1,&mg,m1-m0,cols2,array,INSERT_VALUES);
317:       MatSetValues(*T,1,&mg,1,&mg,&zero,INSERT_VALUES);
318:       VecRestoreArrayRead(v,&array);
319:     }
320:     VecConjugate(v);
321:     MatAssemblyBegin(*T,MAT_FINAL_ASSEMBLY);
322:     MatAssemblyEnd(*T,MAT_FINAL_ASSEMBLY);
323:     PetscFree(cols2);
324:     break;
325:   case PEP_REFINE_SCHEME_SCHUR:
326:     fctx->M2 = w;
327:     fctx->M3 = v;
328:     fctx->m3 = 0.0;
329:     for (i=1;i<nmat-1;i++) fctx->m3 += PetscConj(coeffs[i])*coeffs[i];
330:     fctx->M4 = 0.0;
331:     for (i=1;i<nmat-1;i++) fctx->M4 += PetscConj(coeffs[i])*coeffs2[i];
332:     fctx->M1 = M;
333:     if (ini) MatDuplicate(M,MAT_COPY_VALUES,P);
334:     else MatCopy(M,*P,SAME_NONZERO_PATTERN);
335:     if (fctx->M4!=0.0) {
336:       VecConjugate(v);
337:       VecPointwiseMult(t,v,w);
338:       VecConjugate(v);
339:       VecScale(t,-fctx->m3/fctx->M4);
340:       MatDiagonalSet(*P,t,ADD_VALUES);
341:     }
342:     break;
343:   case PEP_REFINE_SCHEME_MBE:
344:     *T = M;
345:     *P = M;
346:     break;
347:   }
348:   PetscFree2(coeffs,coeffs2);
349:   PetscFunctionReturn(0);
350: }

352: PetscErrorCode PEPNewtonRefinementSimple(PEP pep,PetscInt *maxits,PetscReal tol,PetscInt k)
353: {
354:   PetscInt             i,n,its,idx=0,*idx_sc,*its_sc,color,*fail_sc;
355:   PetscMPIInt          rank,size;
356:   Mat                  Mt=NULL,T=NULL,P=NULL;
357:   MPI_Comm             comm;
358:   Vec                  r,v,dv,rr=NULL,dvv=NULL,t[2];
359:   PetscScalar          *array2,deig=0.0,tt[2],ttt;
360:   const PetscScalar    *array;
361:   PetscReal            norm,error;
362:   PetscBool            ini=PETSC_TRUE,sc_pend,solved=PETSC_FALSE;
363:   PEPSimpNRefctx       *ctx;
364:   PEP_REFINES_MATSHELL *fctx=NULL;
365:   KSPConvergedReason   reason;

367:   PetscLogEventBegin(PEP_Refine,pep,0,0,0);
368:   PEPSimpleNRefSetUp(pep,&ctx);
369:   its = (maxits)?*maxits:NREF_MAXIT;
370:   if (!pep->refineksp) PEPRefineGetKSP(pep,&pep->refineksp);
371:   if (pep->npart==1) BVGetColumn(pep->V,0,&v);
372:   else v = ctx->v;
373:   VecDuplicate(v,&ctx->w);
374:   VecDuplicate(v,&r);
375:   VecDuplicate(v,&dv);
376:   VecDuplicate(v,&t[0]);
377:   VecDuplicate(v,&t[1]);
378:   if (pep->npart==1) {
379:     BVRestoreColumn(pep->V,0,&v);
380:     PetscObjectGetComm((PetscObject)pep,&comm);
381:   } else PetscSubcommGetChild(pep->refinesubc,&comm);
382:   MPI_Comm_size(comm,&size);
383:   MPI_Comm_rank(comm,&rank);
384:   VecGetLocalSize(r,&n);
385:   PetscMalloc3(pep->npart,&idx_sc,pep->npart,&its_sc,pep->npart,&fail_sc);
386:   for (i=0;i<pep->npart;i++) fail_sc[i] = 0;
387:   for (i=0;i<pep->npart;i++) its_sc[i] = 0;
388:   color = (pep->npart==1)?0:pep->refinesubc->color;

390:   /* Loop performing iterative refinements */
391:   while (!solved) {
392:     for (i=0;i<pep->npart;i++) {
393:       sc_pend = PETSC_TRUE;
394:       if (its_sc[i]==0) {
395:         idx_sc[i] = idx++;
396:         if (idx_sc[i]>=k) {
397:           sc_pend = PETSC_FALSE;
398:         } else PEPSimpleNRefScatterEigenvector(pep,ctx,i,idx_sc[i]);
399:       }  else { /* Gather Eigenpair from subcommunicator i */
400:         PEPSimpleNRefGatherEigenpair(pep,ctx,i,idx_sc[i],&fail_sc[i]);
401:       }
402:       while (sc_pend) {
403:         if (!fail_sc[i]) PEPComputeError(pep,idx_sc[i],PEP_ERROR_BACKWARD,&error);
404:         if (error<=tol || its_sc[i]>=its || fail_sc[i]) {
405:           idx_sc[i] = idx++;
406:           its_sc[i] = 0;
407:           fail_sc[i] = 0;
408:           if (idx_sc[i]<k) PEPSimpleNRefScatterEigenvector(pep,ctx,i,idx_sc[i]);
409:         } else {
410:           sc_pend = PETSC_FALSE;
411:           its_sc[i]++;
412:         }
413:         if (idx_sc[i]>=k) sc_pend = PETSC_FALSE;
414:       }
415:     }
416:     solved = PETSC_TRUE;
417:     for (i=0;i<pep->npart&&solved;i++) solved = PetscNot(idx_sc[i]<k);
418:     if (idx_sc[color]<k) {
419: #if !defined(PETSC_USE_COMPLEX)
421: #endif
422:       if (pep->npart==1) BVGetColumn(pep->V,idx_sc[color],&v);
423:       else v = ctx->v;
424:       PEPSimpleNRefSetUpSystem(pep,ctx->A,ctx,idx_sc[color],&Mt,&T,&P,ini,t[0],v);
425:       PEP_KSPSetOperators(pep->refineksp,T,P);
426:       if (ini) {
427:         KSPSetFromOptions(pep->refineksp);
428:         if (pep->scheme==PEP_REFINE_SCHEME_EXPLICIT) {
429:           MatCreateVecs(T,&dvv,NULL);
430:           VecDuplicate(dvv,&rr);
431:         }
432:         ini = PETSC_FALSE;
433:       }

435:       switch (pep->scheme) {
436:       case PEP_REFINE_SCHEME_EXPLICIT:
437:         MatMult(Mt,v,r);
438:         VecGetArrayRead(r,&array);
439:         if (rank==size-1) {
440:           VecGetArray(rr,&array2);
441:           PetscArraycpy(array2,array,n);
442:           array2[n] = 0.0;
443:           VecRestoreArray(rr,&array2);
444:         } else VecPlaceArray(rr,array);
445:         KSPSolve(pep->refineksp,rr,dvv);
446:         KSPGetConvergedReason(pep->refineksp,&reason);
447:         if (reason>0) {
448:           if (rank != size-1) VecResetArray(rr);
449:           VecRestoreArrayRead(r,&array);
450:           VecGetArrayRead(dvv,&array);
451:           VecPlaceArray(dv,array);
452:           VecAXPY(v,-1.0,dv);
453:           VecNorm(v,NORM_2,&norm);
454:           VecScale(v,1.0/norm);
455:           VecResetArray(dv);
456:           if (rank==size-1) pep->eigr[idx_sc[color]] -= array[n];
457:           VecRestoreArrayRead(dvv,&array);
458:         } else fail_sc[color] = 1;
459:         break;
460:       case PEP_REFINE_SCHEME_MBE:
461:         MatMult(T,v,r);
462:         /* Mixed block elimination */
463:         VecConjugate(v);
464:         KSPSolveTranspose(pep->refineksp,v,t[0]);
465:         KSPGetConvergedReason(pep->refineksp,&reason);
466:         if (reason>0) {
467:           VecConjugate(t[0]);
468:           VecDot(ctx->w,t[0],&tt[0]);
469:           KSPSolve(pep->refineksp,ctx->w,t[1]);
470:           KSPGetConvergedReason(pep->refineksp,&reason);
471:           if (reason>0) {
472:             VecDot(t[1],v,&tt[1]);
473:             VecDot(r,t[0],&ttt);
474:             tt[0] = ttt/tt[0];
475:             VecAXPY(r,-tt[0],ctx->w);
476:             KSPSolve(pep->refineksp,r,dv);
477:             KSPGetConvergedReason(pep->refineksp,&reason);
478:             if (reason>0) {
479:               VecDot(dv,v,&ttt);
480:               tt[1] = ttt/tt[1];
481:               VecAXPY(dv,-tt[1],t[1]);
482:               deig = tt[0]+tt[1];
483:             }
484:           }
485:           VecConjugate(v);
486:           VecAXPY(v,-1.0,dv);
487:           VecNorm(v,NORM_2,&norm);
488:           VecScale(v,1.0/norm);
489:           pep->eigr[idx_sc[color]] -= deig;
490:           fail_sc[color] = 0;
491:         } else {
492:           VecConjugate(v);
493:           fail_sc[color] = 1;
494:         }
495:         break;
496:       case PEP_REFINE_SCHEME_SCHUR:
497:         fail_sc[color] = 1;
498:         MatShellGetContext(T,&fctx);
499:         if (fctx->M4!=0.0) {
500:           MatMult(fctx->M1,v,r);
501:           KSPSolve(pep->refineksp,r,dv);
502:           KSPGetConvergedReason(pep->refineksp,&reason);
503:           if (reason>0) {
504:             VecDot(dv,v,&deig);
505:             deig *= -fctx->m3/fctx->M4;
506:             VecAXPY(v,-1.0,dv);
507:             VecNorm(v,NORM_2,&norm);
508:             VecScale(v,1.0/norm);
509:             pep->eigr[idx_sc[color]] -= deig;
510:             fail_sc[color] = 0;
511:           }
512:         }
513:         break;
514:       }
515:       if (pep->npart==1) BVRestoreColumn(pep->V,idx_sc[color],&v);
516:     }
517:   }
518:   VecDestroy(&t[0]);
519:   VecDestroy(&t[1]);
520:   VecDestroy(&dv);
521:   VecDestroy(&ctx->w);
522:   VecDestroy(&r);
523:   PetscFree3(idx_sc,its_sc,fail_sc);
524:   VecScatterDestroy(&ctx->nst);
525:   if (pep->npart>1) {
526:     VecDestroy(&ctx->vg);
527:     VecDestroy(&ctx->v);
528:     for (i=0;i<pep->nmat;i++) MatDestroy(&ctx->A[i]);
529:     for (i=0;i<pep->npart;i++) VecScatterDestroy(&ctx->scatter_id[i]);
530:     PetscFree2(ctx->A,ctx->scatter_id);
531:   }
532:   if (fctx && pep->scheme==PEP_REFINE_SCHEME_SCHUR) {
533:     MatDestroy(&P);
534:     MatDestroy(&fctx->M1);
535:     PetscFree(fctx);
536:   }
537:   if (pep->scheme==PEP_REFINE_SCHEME_EXPLICIT) {
538:     MatDestroy(&Mt);
539:     VecDestroy(&dvv);
540:     VecDestroy(&rr);
541:     VecDestroy(&ctx->nv);
542:   }
543:   MatDestroy(&T);
544:   PetscFree(ctx);
545:   PetscLogEventEnd(PEP_Refine,pep,0,0,0);
546:   PetscFunctionReturn(0);
547: }