Actual source code: neprefine.c

slepc-3.21.1 2024-04-26
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 NEP, simple version
 12: */

 14: #include <slepc/private/nepimpl.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:   FN            *fn;
 24: } NEPSimpNRefctx;

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

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

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

 46: static PetscErrorCode NEPSimpleNRefSetUp(NEP nep,NEPSimpNRefctx **ctx_)
 47: {
 48:   PetscInt       i,si,j,n0,m0,nloc,*idx1,*idx2,ne;
 49:   IS             is1,is2;
 50:   NEPSimpNRefctx *ctx;
 51:   Vec            v;
 52:   PetscMPIInt    rank,size;
 53:   MPI_Comm       child;

 55:   PetscFunctionBegin;
 56:   PetscCall(PetscCalloc1(1,ctx_));
 57:   ctx = *ctx_;
 58:   if (nep->npart==1) {
 59:     ctx->A  = nep->A;
 60:     ctx->fn = nep->f;
 61:     nep->refinesubc = NULL;
 62:     ctx->scatter_id = NULL;
 63:   } else {
 64:     PetscCall(PetscSubcommGetChild(nep->refinesubc,&child));
 65:     PetscCall(PetscMalloc2(nep->nt,&ctx->A,nep->npart,&ctx->scatter_id));

 67:     /* Duplicate matrices */
 68:     for (i=0;i<nep->nt;i++) PetscCall(MatCreateRedundantMatrix(nep->A[i],0,child,MAT_INITIAL_MATRIX,&ctx->A[i]));
 69:     PetscCall(MatCreateVecs(ctx->A[0],&ctx->v,NULL));

 71:     /* Duplicate FNs */
 72:     PetscCall(PetscMalloc1(nep->nt,&ctx->fn));
 73:     for (i=0;i<nep->nt;i++) PetscCall(FNDuplicate(nep->f[i],child,&ctx->fn[i]));

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

120: /*
121:   Gather Eigenpair idx from subcommunicator with color sc
122: */
123: static PetscErrorCode NEPSimpleNRefGatherEigenpair(NEP nep,NEPSimpNRefctx *ctx,PetscInt sc,PetscInt idx,PetscInt *fail)
124: {
125:   PetscMPIInt    nproc,p;
126:   MPI_Comm       comm=((PetscObject)nep)->comm;
127:   Vec            v;
128:   PetscScalar    *array;

130:   PetscFunctionBegin;
131:   PetscCallMPI(MPI_Comm_size(comm,&nproc));
132:   p = (nproc/nep->npart)*(sc+1)+PetscMin(sc+1,nproc%nep->npart)-1;
133:   if (nep->npart>1) {
134:     /* Communicate convergence successful */
135:     PetscCallMPI(MPI_Bcast(fail,1,MPIU_INT,p,comm));
136:     if (!(*fail)) {
137:       /* Process 0 of subcommunicator sc broadcasts the eigenvalue */
138:       PetscCallMPI(MPI_Bcast(&nep->eigr[idx],1,MPIU_SCALAR,p,comm));
139:       /* Gather nep->V[idx] from the subcommuniator sc */
140:       PetscCall(BVGetColumn(nep->V,idx,&v));
141:       if (nep->refinesubc->color==sc) {
142:         PetscCall(VecGetArray(ctx->v,&array));
143:         PetscCall(VecPlaceArray(ctx->vg,array));
144:       }
145:       PetscCall(VecScatterBegin(ctx->scatter_id[sc],ctx->vg,v,INSERT_VALUES,SCATTER_REVERSE));
146:       PetscCall(VecScatterEnd(ctx->scatter_id[sc],ctx->vg,v,INSERT_VALUES,SCATTER_REVERSE));
147:       if (nep->refinesubc->color==sc) {
148:         PetscCall(VecResetArray(ctx->vg));
149:         PetscCall(VecRestoreArray(ctx->v,&array));
150:       }
151:       PetscCall(BVRestoreColumn(nep->V,idx,&v));
152:     }
153:   } else {
154:     if (nep->scheme==NEP_REFINE_SCHEME_EXPLICIT && !(*fail)) PetscCallMPI(MPI_Bcast(&nep->eigr[idx],1,MPIU_SCALAR,p,comm));
155:   }
156:   PetscFunctionReturn(PETSC_SUCCESS);
157: }

159: static PetscErrorCode NEPSimpleNRefScatterEigenvector(NEP nep,NEPSimpNRefctx *ctx,PetscInt sc,PetscInt idx)
160: {
161:   Vec            v;
162:   PetscScalar    *array;

164:   PetscFunctionBegin;
165:   if (nep->npart>1) {
166:     PetscCall(BVGetColumn(nep->V,idx,&v));
167:     if (nep->refinesubc->color==sc) {
168:       PetscCall(VecGetArray(ctx->v,&array));
169:       PetscCall(VecPlaceArray(ctx->vg,array));
170:     }
171:     PetscCall(VecScatterBegin(ctx->scatter_id[sc],v,ctx->vg,INSERT_VALUES,SCATTER_FORWARD));
172:     PetscCall(VecScatterEnd(ctx->scatter_id[sc],v,ctx->vg,INSERT_VALUES,SCATTER_FORWARD));
173:     if (nep->refinesubc->color==sc) {
174:       PetscCall(VecResetArray(ctx->vg));
175:       PetscCall(VecRestoreArray(ctx->v,&array));
176:     }
177:     PetscCall(BVRestoreColumn(nep->V,idx,&v));
178:   }
179:   PetscFunctionReturn(PETSC_SUCCESS);
180: }

182: static PetscErrorCode NEPSimpleNRefSetUpSystem(NEP nep,NEPSimpNRefctx *ctx,Mat *A,PetscInt idx,Mat *Mt,Mat *T,Mat *P,PetscBool ini,Vec t,Vec v)
183: {
184:   PetscInt            i,st,ml,m0,n0,m1,mg;
185:   PetscInt            ncols,*cols2=NULL,nt=nep->nt;
186:   PetscScalar         zero=0.0,*coeffs,*coeffs2;
187:   PetscMPIInt         rank,size;
188:   MPI_Comm            comm;
189:   const PetscInt      *cols;
190:   const PetscScalar   *vals,*array;
191:   NEP_REFINE_MATSHELL *fctx;
192:   Vec                 w=ctx->w;
193:   Mat                 M;

195:   PetscFunctionBegin;
196:   PetscCall(PetscMalloc2(nt,&coeffs,nt,&coeffs2));
197:   switch (nep->scheme) {
198:   case NEP_REFINE_SCHEME_SCHUR:
199:     if (ini) {
200:       PetscCall(PetscCalloc1(1,&fctx));
201:       PetscCall(MatGetSize(A[0],&m0,&n0));
202:       PetscCall(MatCreateShell(PetscObjectComm((PetscObject)A[0]),PETSC_DECIDE,PETSC_DECIDE,m0,n0,fctx,T));
203:       PetscCall(MatShellSetOperation(*T,MATOP_MULT,(void(*)(void))MatMult_FS));
204:     } else PetscCall(MatShellGetContext(*T,&fctx));
205:     M=fctx->M1;
206:     break;
207:   case NEP_REFINE_SCHEME_MBE:
208:     M=*T;
209:     break;
210:   case NEP_REFINE_SCHEME_EXPLICIT:
211:     M=*Mt;
212:     break;
213:   }
214:   if (ini) PetscCall(MatDuplicate(A[0],MAT_COPY_VALUES,&M));
215:   else PetscCall(MatCopy(A[0],M,DIFFERENT_NONZERO_PATTERN));
216:   for (i=0;i<nt;i++) PetscCall(FNEvaluateFunction(ctx->fn[i],nep->eigr[idx],coeffs+i));
217:   if (coeffs[0]!=1.0) PetscCall(MatScale(M,coeffs[0]));
218:   for (i=1;i<nt;i++) PetscCall(MatAXPY(M,coeffs[i],A[i],(ini)?nep->mstr:SUBSET_NONZERO_PATTERN));
219:   for (i=0;i<nt;i++) PetscCall(FNEvaluateDerivative(ctx->fn[i],nep->eigr[idx],coeffs2+i));
220:   st = 0;
221:   for (i=0;i<nt && PetscAbsScalar(coeffs2[i])==0.0;i++) st++;
222:   PetscCall(MatMult(A[st],v,w));
223:   if (coeffs2[st]!=1.0) PetscCall(VecScale(w,coeffs2[st]));
224:   for (i=st+1;i<nt;i++) {
225:     PetscCall(MatMult(A[i],v,t));
226:     PetscCall(VecAXPY(w,coeffs2[i],t));
227:   }

229:   switch (nep->scheme) {
230:   case NEP_REFINE_SCHEME_EXPLICIT:
231:     comm = PetscObjectComm((PetscObject)A[0]);
232:     PetscCallMPI(MPI_Comm_rank(comm,&rank));
233:     PetscCallMPI(MPI_Comm_size(comm,&size));
234:     PetscCall(MatGetSize(M,&mg,NULL));
235:     PetscCall(MatGetOwnershipRange(M,&m0,&m1));
236:     if (ini) {
237:       PetscCall(MatCreate(comm,T));
238:       PetscCall(MatGetLocalSize(M,&ml,NULL));
239:       if (rank==size-1) ml++;
240:       PetscCall(MatSetSizes(*T,ml,ml,mg+1,mg+1));
241:       PetscCall(MatSetFromOptions(*T));
242:       *Mt = M;
243:       *P  = *T;
244:     }

246:     /* Set values */
247:     PetscCall(VecGetArrayRead(w,&array));
248:     for (i=m0;i<m1;i++) {
249:       PetscCall(MatGetRow(M,i,&ncols,&cols,&vals));
250:       PetscCall(MatSetValues(*T,1,&i,ncols,cols,vals,INSERT_VALUES));
251:       PetscCall(MatRestoreRow(M,i,&ncols,&cols,&vals));
252:       PetscCall(MatSetValues(*T,1,&i,1,&mg,array+i-m0,INSERT_VALUES));
253:     }
254:     PetscCall(VecRestoreArrayRead(w,&array));
255:     PetscCall(VecConjugate(v));
256:     PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)A[0]),&size));
257:     PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)A[0]),&rank));
258:     if (size>1) {
259:       if (rank==size-1) {
260:         PetscCall(PetscMalloc1(nep->n,&cols2));
261:         for (i=0;i<nep->n;i++) cols2[i]=i;
262:       }
263:       PetscCall(VecScatterBegin(ctx->nst,v,ctx->nv,INSERT_VALUES,SCATTER_FORWARD));
264:       PetscCall(VecScatterEnd(ctx->nst,v,ctx->nv,INSERT_VALUES,SCATTER_FORWARD));
265:       PetscCall(VecGetArrayRead(ctx->nv,&array));
266:       if (rank==size-1) {
267:         PetscCall(MatSetValues(*T,1,&mg,nep->n,cols2,array,INSERT_VALUES));
268:         PetscCall(MatSetValues(*T,1,&mg,1,&mg,&zero,INSERT_VALUES));
269:       }
270:       PetscCall(VecRestoreArrayRead(ctx->nv,&array));
271:     } else {
272:       PetscCall(PetscMalloc1(m1-m0,&cols2));
273:       for (i=0;i<m1-m0;i++) cols2[i]=m0+i;
274:       PetscCall(VecGetArrayRead(v,&array));
275:       PetscCall(MatSetValues(*T,1,&mg,m1-m0,cols2,array,INSERT_VALUES));
276:       PetscCall(MatSetValues(*T,1,&mg,1,&mg,&zero,INSERT_VALUES));
277:       PetscCall(VecRestoreArrayRead(v,&array));
278:     }
279:     PetscCall(VecConjugate(v));
280:     PetscCall(MatAssemblyBegin(*T,MAT_FINAL_ASSEMBLY));
281:     PetscCall(MatAssemblyEnd(*T,MAT_FINAL_ASSEMBLY));
282:     PetscCall(PetscFree(cols2));
283:     break;
284:   case NEP_REFINE_SCHEME_SCHUR:
285:     fctx->M2 = ctx->w;
286:     fctx->M3 = v;
287:     fctx->m3 = 1.0+PetscConj(nep->eigr[idx])*nep->eigr[idx];
288:     fctx->M4 = PetscConj(nep->eigr[idx]);
289:     fctx->M1 = M;
290:     if (ini) PetscCall(MatDuplicate(M,MAT_COPY_VALUES,P));
291:     else PetscCall(MatCopy(M,*P,SAME_NONZERO_PATTERN));
292:     if (fctx->M4!=0.0) {
293:       PetscCall(VecConjugate(v));
294:       PetscCall(VecPointwiseMult(t,v,w));
295:       PetscCall(VecConjugate(v));
296:       PetscCall(VecScale(t,-fctx->m3/fctx->M4));
297:       PetscCall(MatDiagonalSet(*P,t,ADD_VALUES));
298:     }
299:     break;
300:   case NEP_REFINE_SCHEME_MBE:
301:     *T = M;
302:     *P = M;
303:     break;
304:   }
305:   PetscCall(PetscFree2(coeffs,coeffs2));
306:   PetscFunctionReturn(PETSC_SUCCESS);
307: }

309: PetscErrorCode NEPNewtonRefinementSimple(NEP nep,PetscInt *maxits,PetscReal tol,PetscInt k)
310: {
311:   PetscInt            i,n,its,idx=0,*idx_sc,*its_sc,color,*fail_sc;
312:   PetscMPIInt         rank,size;
313:   Mat                 Mt=NULL,T=NULL,P=NULL;
314:   MPI_Comm            comm;
315:   Vec                 r,v,dv,rr=NULL,dvv=NULL,t[2];
316:   const PetscScalar   *array;
317:   PetscScalar         *array2,deig=0.0,tt[2],ttt;
318:   PetscReal           norm,error;
319:   PetscBool           ini=PETSC_TRUE,sc_pend,solved=PETSC_FALSE;
320:   NEPSimpNRefctx      *ctx;
321:   NEP_REFINE_MATSHELL *fctx=NULL;
322:   KSPConvergedReason  reason;

324:   PetscFunctionBegin;
325:   PetscCall(PetscLogEventBegin(NEP_Refine,nep,0,0,0));
326:   PetscCall(NEPSimpleNRefSetUp(nep,&ctx));
327:   its = (maxits)?*maxits:NREF_MAXIT;
328:   if (!nep->refineksp) PetscCall(NEPRefineGetKSP(nep,&nep->refineksp));
329:   if (nep->npart==1) PetscCall(BVGetColumn(nep->V,0,&v));
330:   else v = ctx->v;
331:   PetscCall(VecDuplicate(v,&ctx->w));
332:   PetscCall(VecDuplicate(v,&r));
333:   PetscCall(VecDuplicate(v,&dv));
334:   PetscCall(VecDuplicate(v,&t[0]));
335:   PetscCall(VecDuplicate(v,&t[1]));
336:   if (nep->npart==1) {
337:     PetscCall(BVRestoreColumn(nep->V,0,&v));
338:     PetscCall(PetscObjectGetComm((PetscObject)nep,&comm));
339:   } else PetscCall(PetscSubcommGetChild(nep->refinesubc,&comm));
340:   PetscCallMPI(MPI_Comm_size(comm,&size));
341:   PetscCallMPI(MPI_Comm_rank(comm,&rank));
342:   PetscCall(VecGetLocalSize(r,&n));
343:   PetscCall(PetscMalloc3(nep->npart,&idx_sc,nep->npart,&its_sc,nep->npart,&fail_sc));
344:   for (i=0;i<nep->npart;i++) fail_sc[i] = 0;
345:   for (i=0;i<nep->npart;i++) its_sc[i] = 0;
346:   color = (nep->npart==1)?0:nep->refinesubc->color;

348:   /* Loop performing iterative refinements */
349:   while (!solved) {
350:     for (i=0;i<nep->npart;i++) {
351:       sc_pend = PETSC_TRUE;
352:       if (its_sc[i]==0) {
353:         idx_sc[i] = idx++;
354:         if (idx_sc[i]>=k) {
355:           sc_pend = PETSC_FALSE;
356:         } else PetscCall(NEPSimpleNRefScatterEigenvector(nep,ctx,i,idx_sc[i]));
357:       }  else { /* Gather Eigenpair from subcommunicator i */
358:         PetscCall(NEPSimpleNRefGatherEigenpair(nep,ctx,i,idx_sc[i],&fail_sc[i]));
359:       }
360:       while (sc_pend) {
361:         if (!fail_sc[i]) PetscCall(NEPComputeError(nep,idx_sc[i],NEP_ERROR_RELATIVE,&error));
362:         if (error<=tol || its_sc[i]>=its || fail_sc[i]) {
363:           idx_sc[i] = idx++;
364:           its_sc[i] = 0;
365:           fail_sc[i] = 0;
366:           if (idx_sc[i]<k) PetscCall(NEPSimpleNRefScatterEigenvector(nep,ctx,i,idx_sc[i]));
367:         } else {
368:           sc_pend = PETSC_FALSE;
369:           its_sc[i]++;
370:         }
371:         if (idx_sc[i]>=k) sc_pend = PETSC_FALSE;
372:       }
373:     }
374:     solved = PETSC_TRUE;
375:     for (i=0;i<nep->npart&&solved;i++) solved = PetscNot(idx_sc[i]<k);
376:     if (idx_sc[color]<k) {
377: #if !defined(PETSC_USE_COMPLEX)
378:       PetscCheck(nep->eigi[idx_sc[color]]==0.0,PetscObjectComm((PetscObject)nep),PETSC_ERR_SUP,"Simple Refinement not implemented in real scalar for complex eigenvalues");
379: #endif
380:       if (nep->npart==1) PetscCall(BVGetColumn(nep->V,idx_sc[color],&v));
381:       else v = ctx->v;
382:       PetscCall(NEPSimpleNRefSetUpSystem(nep,ctx,ctx->A,idx_sc[color],&Mt,&T,&P,ini,t[0],v));
383:       PetscCall(NEP_KSPSetOperators(nep->refineksp,T,P));
384:       if (ini) {
385:         PetscCall(KSPSetFromOptions(nep->refineksp));
386:         if (nep->scheme==NEP_REFINE_SCHEME_EXPLICIT) {
387:           PetscCall(MatCreateVecs(T,&dvv,NULL));
388:           PetscCall(VecDuplicate(dvv,&rr));
389:         }
390:         ini = PETSC_FALSE;
391:       }
392:       switch (nep->scheme) {
393:       case NEP_REFINE_SCHEME_EXPLICIT:
394:         PetscCall(MatMult(Mt,v,r));
395:         PetscCall(VecGetArrayRead(r,&array));
396:         if (rank==size-1) {
397:           PetscCall(VecGetArray(rr,&array2));
398:           PetscCall(PetscArraycpy(array2,array,n));
399:           array2[n] = 0.0;
400:           PetscCall(VecRestoreArray(rr,&array2));
401:         } else PetscCall(VecPlaceArray(rr,array));
402:         PetscCall(KSPSolve(nep->refineksp,rr,dvv));
403:         PetscCall(KSPGetConvergedReason(nep->refineksp,&reason));
404:         if (reason>0) {
405:           if (rank != size-1) PetscCall(VecResetArray(rr));
406:           PetscCall(VecRestoreArrayRead(r,&array));
407:           PetscCall(VecGetArrayRead(dvv,&array));
408:           PetscCall(VecPlaceArray(dv,array));
409:           PetscCall(VecAXPY(v,-1.0,dv));
410:           PetscCall(VecNorm(v,NORM_2,&norm));
411:           PetscCall(VecScale(v,1.0/norm));
412:           PetscCall(VecResetArray(dv));
413:           if (rank==size-1) nep->eigr[idx_sc[color]] -= array[n];
414:           PetscCall(VecRestoreArrayRead(dvv,&array));
415:         } else fail_sc[color] = 1;
416:         break;
417:       case NEP_REFINE_SCHEME_MBE:
418:         PetscCall(MatMult(T,v,r));
419:         /* Mixed block elimination */
420:         PetscCall(VecConjugate(v));
421:         PetscCall(KSPSolveTranspose(nep->refineksp,v,t[0]));
422:         PetscCall(KSPGetConvergedReason(nep->refineksp,&reason));
423:         if (reason>0) {
424:           PetscCall(VecConjugate(t[0]));
425:           PetscCall(VecDot(ctx->w,t[0],&tt[0]));
426:           PetscCall(KSPSolve(nep->refineksp,ctx->w,t[1]));
427:           PetscCall(KSPGetConvergedReason(nep->refineksp,&reason));
428:           if (reason>0) {
429:             PetscCall(VecDot(t[1],v,&tt[1]));
430:             PetscCall(VecDot(r,t[0],&ttt));
431:             tt[0] = ttt/tt[0];
432:             PetscCall(VecAXPY(r,-tt[0],ctx->w));
433:             PetscCall(KSPSolve(nep->refineksp,r,dv));
434:             PetscCall(KSPGetConvergedReason(nep->refineksp,&reason));
435:             if (reason>0) {
436:               PetscCall(VecDot(dv,v,&ttt));
437:               tt[1] = ttt/tt[1];
438:               PetscCall(VecAXPY(dv,-tt[1],t[1]));
439:               deig = tt[0]+tt[1];
440:             }
441:           }
442:           PetscCall(VecConjugate(v));
443:           PetscCall(VecAXPY(v,-1.0,dv));
444:           PetscCall(VecNorm(v,NORM_2,&norm));
445:           PetscCall(VecScale(v,1.0/norm));
446:           nep->eigr[idx_sc[color]] -= deig;
447:           fail_sc[color] = 0;
448:         } else {
449:           PetscCall(VecConjugate(v));
450:           fail_sc[color] = 1;
451:         }
452:         break;
453:       case NEP_REFINE_SCHEME_SCHUR:
454:         fail_sc[color] = 1;
455:         PetscCall(MatShellGetContext(T,&fctx));
456:         if (fctx->M4!=0.0) {
457:           PetscCall(MatMult(fctx->M1,v,r));
458:           PetscCall(KSPSolve(nep->refineksp,r,dv));
459:           PetscCall(KSPGetConvergedReason(nep->refineksp,&reason));
460:           if (reason>0) {
461:             PetscCall(VecDot(dv,v,&deig));
462:             deig *= -fctx->m3/fctx->M4;
463:             PetscCall(VecAXPY(v,-1.0,dv));
464:             PetscCall(VecNorm(v,NORM_2,&norm));
465:             PetscCall(VecScale(v,1.0/norm));
466:             nep->eigr[idx_sc[color]] -= deig;
467:             fail_sc[color] = 0;
468:           }
469:         }
470:         break;
471:       }
472:       if (nep->npart==1) PetscCall(BVRestoreColumn(nep->V,idx_sc[color],&v));
473:     }
474:   }
475:   PetscCall(VecDestroy(&t[0]));
476:   PetscCall(VecDestroy(&t[1]));
477:   PetscCall(VecDestroy(&dv));
478:   PetscCall(VecDestroy(&ctx->w));
479:   PetscCall(VecDestroy(&r));
480:   PetscCall(PetscFree3(idx_sc,its_sc,fail_sc));
481:   PetscCall(VecScatterDestroy(&ctx->nst));
482:   if (nep->npart>1) {
483:     PetscCall(VecDestroy(&ctx->vg));
484:     PetscCall(VecDestroy(&ctx->v));
485:     for (i=0;i<nep->nt;i++) PetscCall(MatDestroy(&ctx->A[i]));
486:     for (i=0;i<nep->npart;i++) PetscCall(VecScatterDestroy(&ctx->scatter_id[i]));
487:     PetscCall(PetscFree2(ctx->A,ctx->scatter_id));
488:   }
489:   if (fctx && nep->scheme==NEP_REFINE_SCHEME_SCHUR) {
490:     PetscCall(MatDestroy(&P));
491:     PetscCall(MatDestroy(&fctx->M1));
492:     PetscCall(PetscFree(fctx));
493:   }
494:   if (nep->scheme==NEP_REFINE_SCHEME_EXPLICIT) {
495:     PetscCall(MatDestroy(&Mt));
496:     PetscCall(VecDestroy(&dvv));
497:     PetscCall(VecDestroy(&rr));
498:     PetscCall(VecDestroy(&ctx->nv));
499:     if (nep->npart>1) {
500:       for (i=0;i<nep->nt;i++) PetscCall(FNDestroy(&ctx->fn[i]));
501:       PetscCall(PetscFree(ctx->fn));
502:     }
503:   }
504:   if (nep->scheme==NEP_REFINE_SCHEME_MBE) {
505:     if (nep->npart>1) {
506:       for (i=0;i<nep->nt;i++) PetscCall(FNDestroy(&ctx->fn[i]));
507:       PetscCall(PetscFree(ctx->fn));
508:     }
509:   }
510:   PetscCall(MatDestroy(&T));
511:   PetscCall(PetscFree(ctx));
512:   PetscCall(PetscLogEventEnd(NEP_Refine,nep,0,0,0));
513:   PetscFunctionReturn(PETSC_SUCCESS);
514: }