Date: 2022-03-31T15:29:31+00:00

Actual source code: neprefine.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 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:   MatShellGetContext(M,&ctx);
     38:   VecDot(x,ctx->M3,&t);
     39:   t *= ctx->m3/ctx->M4;
     40:   MatMult(ctx->M1,x,y);
     41:   VecAXPY(y,-t,ctx->M2);
     42:   PetscFunctionReturn(0);
     43: }

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

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

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

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

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

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

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

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

    165:   if (nep->npart>1) {
    166:     BVGetColumn(nep->V,idx,&v);
    167:     if (nep->refinesubc->color==sc) {
    168:       VecGetArray(ctx->v,&array);
    169:       VecPlaceArray(ctx->vg,array);
    170:     }
    171:     VecScatterBegin(ctx->scatter_id[sc],v,ctx->vg,INSERT_VALUES,SCATTER_FORWARD);
    172:     VecScatterEnd(ctx->scatter_id[sc],v,ctx->vg,INSERT_VALUES,SCATTER_FORWARD);
    173:     if (nep->refinesubc->color==sc) {
    174:       VecResetArray(ctx->vg);
    175:       VecRestoreArray(ctx->v,&array);
    176:     }
    177:     BVRestoreColumn(nep->V,idx,&v);
    178:   }
    179:   PetscFunctionReturn(0);
    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:   PetscErrorCode      ierr;
    185:   PetscInt            i,st,ml,m0,n0,m1,mg;
    186:   PetscInt            *dnz,*onz,ncols,*cols2=NULL,*nnz,nt=nep->nt;
    187:   PetscScalar         zero=0.0,*coeffs,*coeffs2;
    188:   PetscMPIInt         rank,size;
    189:   MPI_Comm            comm;
    190:   const PetscInt      *cols;
    191:   const PetscScalar   *vals,*array;
    192:   NEP_REFINE_MATSHELL *fctx;
    193:   Vec                 w=ctx->w;
    194:   Mat                 M;

    196:   PetscMalloc2(nt,&coeffs,nt,&coeffs2);
    197:   switch (nep->scheme) {
    198:   case NEP_REFINE_SCHEME_SCHUR:
    199:     if (ini) {
    200:       PetscCalloc1(1,&fctx);
    201:       MatGetSize(A[0],&m0,&n0);
    202:       MatCreateShell(PetscObjectComm((PetscObject)A[0]),PETSC_DECIDE,PETSC_DECIDE,m0,n0,fctx,T);
    203:       MatShellSetOperation(*T,MATOP_MULT,(void(*)(void))MatMult_FS);
    204:     } else 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) MatDuplicate(A[0],MAT_COPY_VALUES,&M);
    215:   else MatCopy(A[0],M,DIFFERENT_NONZERO_PATTERN);
    216:   for (i=0;i<nt;i++) FNEvaluateFunction(ctx->fn[i],nep->eigr[idx],coeffs+i);
    217:   if (coeffs[0]!=1.0) MatScale(M,coeffs[0]);
    218:   for (i=1;i<nt;i++) MatAXPY(M,coeffs[i],A[i],(ini)?nep->mstr:SUBSET_NONZERO_PATTERN);
    219:   for (i=0;i<nt;i++) 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:   MatMult(A[st],v,w);
    223:   if (coeffs2[st]!=1.0) VecScale(w,coeffs2[st]);
    224:   for (i=st+1;i<nt;i++) {
    225:     MatMult(A[i],v,t);
    226:     VecAXPY(w,coeffs2[i],t);
    227:   }

    229:   switch (nep->scheme) {
    230:   case NEP_REFINE_SCHEME_EXPLICIT:
    231:     comm = PetscObjectComm((PetscObject)A[0]);
    232:     MPI_Comm_rank(comm,&rank);
    233:     MPI_Comm_size(comm,&size);
    234:     MatGetSize(M,&mg,NULL);
    235:     MatGetOwnershipRange(M,&m0,&m1);
    236:     if (ini) {
    237:       MatCreate(comm,T);
    238:       MatGetLocalSize(M,&ml,NULL);
    239:       if (rank==size-1) ml++;
    240:       MatSetSizes(*T,ml,ml,mg+1,mg+1);
    241:       MatSetFromOptions(*T);
    242:       MatSetUp(*T);
    243:       /* Preallocate M */
    244:       if (size>1) {
    245:         ierr = MatPreallocateInitialize(comm,ml,ml,dnz,onz);
    246:         for (i=m0;i<m1;i++) {
    247:           MatGetRow(M,i,&ncols,&cols,NULL);
    248:           MatPreallocateSet(i,ncols,cols,dnz,onz);
    249:           MatPreallocateSet(i,1,&mg,dnz,onz);
    250:           MatRestoreRow(M,i,&ncols,&cols,NULL);
    251:         }
    252:         if (rank==size-1) {
    253:           PetscCalloc1(mg+1,&cols2);
    254:           for (i=0;i<mg+1;i++) cols2[i]=i;
    255:           MatPreallocateSet(m1,mg+1,cols2,dnz,onz);
    256:           PetscFree(cols2);
    257:         }
    258:         MatMPIAIJSetPreallocation(*T,0,dnz,0,onz);
    259:         ierr = MatPreallocateFinalize(dnz,onz);
    260:       } else {
    261:         PetscCalloc1(mg+1,&nnz);
    262:         for (i=0;i<mg;i++) {
    263:           MatGetRow(M,i,&ncols,NULL,NULL);
    264:           nnz[i] = ncols+1;
    265:           MatRestoreRow(M,i,&ncols,NULL,NULL);
    266:         }
    267:         nnz[mg] = mg+1;
    268:         MatSeqAIJSetPreallocation(*T,0,nnz);
    269:         PetscFree(nnz);
    270:       }
    271:       *Mt = M;
    272:       *P  = *T;
    273:     }

    275:     /* Set values */
    276:     VecGetArrayRead(w,&array);
    277:     for (i=m0;i<m1;i++) {
    278:       MatGetRow(M,i,&ncols,&cols,&vals);
    279:       MatSetValues(*T,1,&i,ncols,cols,vals,INSERT_VALUES);
    280:       MatRestoreRow(M,i,&ncols,&cols,&vals);
    281:       MatSetValues(*T,1,&i,1,&mg,array+i-m0,INSERT_VALUES);
    282:     }
    283:     VecRestoreArrayRead(w,&array);
    284:     VecConjugate(v);
    285:     MPI_Comm_size(PetscObjectComm((PetscObject)A[0]),&size);
    286:     MPI_Comm_rank(PetscObjectComm((PetscObject)A[0]),&rank);
    287:     if (size>1) {
    288:       if (rank==size-1) {
    289:         PetscMalloc1(nep->n,&cols2);
    290:         for (i=0;i<nep->n;i++) cols2[i]=i;
    291:       }
    292:       VecScatterBegin(ctx->nst,v,ctx->nv,INSERT_VALUES,SCATTER_FORWARD);
    293:       VecScatterEnd(ctx->nst,v,ctx->nv,INSERT_VALUES,SCATTER_FORWARD);
    294:       VecGetArrayRead(ctx->nv,&array);
    295:       if (rank==size-1) {
    296:         MatSetValues(*T,1,&mg,nep->n,cols2,array,INSERT_VALUES);
    297:         MatSetValues(*T,1,&mg,1,&mg,&zero,INSERT_VALUES);
    298:       }
    299:       VecRestoreArrayRead(ctx->nv,&array);
    300:     } else {
    301:       PetscMalloc1(m1-m0,&cols2);
    302:       for (i=0;i<m1-m0;i++) cols2[i]=m0+i;
    303:       VecGetArrayRead(v,&array);
    304:       MatSetValues(*T,1,&mg,m1-m0,cols2,array,INSERT_VALUES);
    305:       MatSetValues(*T,1,&mg,1,&mg,&zero,INSERT_VALUES);
    306:       VecRestoreArrayRead(v,&array);
    307:     }
    308:     VecConjugate(v);
    309:     MatAssemblyBegin(*T,MAT_FINAL_ASSEMBLY);
    310:     MatAssemblyEnd(*T,MAT_FINAL_ASSEMBLY);
    311:     PetscFree(cols2);
    312:     break;
    313:   case NEP_REFINE_SCHEME_SCHUR:
    314:     fctx->M2 = ctx->w;
    315:     fctx->M3 = v;
    316:     fctx->m3 = 1.0+PetscConj(nep->eigr[idx])*nep->eigr[idx];
    317:     fctx->M4 = PetscConj(nep->eigr[idx]);
    318:     fctx->M1 = M;
    319:     if (ini) MatDuplicate(M,MAT_COPY_VALUES,P);
    320:     else MatCopy(M,*P,SAME_NONZERO_PATTERN);
    321:     if (fctx->M4!=0.0) {
    322:       VecConjugate(v);
    323:       VecPointwiseMult(t,v,w);
    324:       VecConjugate(v);
    325:       VecScale(t,-fctx->m3/fctx->M4);
    326:       MatDiagonalSet(*P,t,ADD_VALUES);
    327:     }
    328:     break;
    329:   case NEP_REFINE_SCHEME_MBE:
    330:     *T = M;
    331:     *P = M;
    332:     break;
    333:   }
    334:   PetscFree2(coeffs,coeffs2);
    335:   PetscFunctionReturn(0);
    336: }

    338: PetscErrorCode NEPNewtonRefinementSimple(NEP nep,PetscInt *maxits,PetscReal tol,PetscInt k)
    339: {
    340:   PetscInt            i,n,its,idx=0,*idx_sc,*its_sc,color,*fail_sc;
    341:   PetscMPIInt         rank,size;
    342:   Mat                 Mt=NULL,T=NULL,P=NULL;
    343:   MPI_Comm            comm;
    344:   Vec                 r,v,dv,rr=NULL,dvv=NULL,t[2];
    345:   const PetscScalar   *array;
    346:   PetscScalar         *array2,deig=0.0,tt[2],ttt;
    347:   PetscReal           norm,error;
    348:   PetscBool           ini=PETSC_TRUE,sc_pend,solved=PETSC_FALSE;
    349:   NEPSimpNRefctx      *ctx;
    350:   NEP_REFINE_MATSHELL *fctx=NULL;
    351:   KSPConvergedReason  reason;

    353:   PetscLogEventBegin(NEP_Refine,nep,0,0,0);
    354:   NEPSimpleNRefSetUp(nep,&ctx);
    355:   its = (maxits)?*maxits:NREF_MAXIT;
    356:   if (!nep->refineksp) NEPRefineGetKSP(nep,&nep->refineksp);
    357:   if (nep->npart==1) BVGetColumn(nep->V,0,&v);
    358:   else v = ctx->v;
    359:   VecDuplicate(v,&ctx->w);
    360:   VecDuplicate(v,&r);
    361:   VecDuplicate(v,&dv);
    362:   VecDuplicate(v,&t[0]);
    363:   VecDuplicate(v,&t[1]);
    364:   if (nep->npart==1) {
    365:     BVRestoreColumn(nep->V,0,&v);
    366:     PetscObjectGetComm((PetscObject)nep,&comm);
    367:   } else PetscSubcommGetChild(nep->refinesubc,&comm);
    368:   MPI_Comm_size(comm,&size);
    369:   MPI_Comm_rank(comm,&rank);
    370:   VecGetLocalSize(r,&n);
    371:   PetscMalloc3(nep->npart,&idx_sc,nep->npart,&its_sc,nep->npart,&fail_sc);
    372:   for (i=0;i<nep->npart;i++) fail_sc[i] = 0;
    373:   for (i=0;i<nep->npart;i++) its_sc[i] = 0;
    374:   color = (nep->npart==1)?0:nep->refinesubc->color;

    376:   /* Loop performing iterative refinements */
    377:   while (!solved) {
    378:     for (i=0;i<nep->npart;i++) {
    379:       sc_pend = PETSC_TRUE;
    380:       if (its_sc[i]==0) {
    381:         idx_sc[i] = idx++;
    382:         if (idx_sc[i]>=k) {
    383:           sc_pend = PETSC_FALSE;
    384:         } else NEPSimpleNRefScatterEigenvector(nep,ctx,i,idx_sc[i]);
    385:       }  else { /* Gather Eigenpair from subcommunicator i */
    386:         NEPSimpleNRefGatherEigenpair(nep,ctx,i,idx_sc[i],&fail_sc[i]);
    387:       }
    388:       while (sc_pend) {
    389:         if (!fail_sc[i]) NEPComputeError(nep,idx_sc[i],NEP_ERROR_RELATIVE,&error);
    390:         if (error<=tol || its_sc[i]>=its || fail_sc[i]) {
    391:           idx_sc[i] = idx++;
    392:           its_sc[i] = 0;
    393:           fail_sc[i] = 0;
    394:           if (idx_sc[i]<k) NEPSimpleNRefScatterEigenvector(nep,ctx,i,idx_sc[i]);
    395:         } else {
    396:           sc_pend = PETSC_FALSE;
    397:           its_sc[i]++;
    398:         }
    399:         if (idx_sc[i]>=k) sc_pend = PETSC_FALSE;
    400:       }
    401:     }
    402:     solved = PETSC_TRUE;
    403:     for (i=0;i<nep->npart&&solved;i++) solved = PetscNot(idx_sc[i]<k);
    404:     if (idx_sc[color]<k) {
    405: #if !defined(PETSC_USE_COMPLEX)
    407: #endif
    408:       if (nep->npart==1) BVGetColumn(nep->V,idx_sc[color],&v);
    409:       else v = ctx->v;
    410:       NEPSimpleNRefSetUpSystem(nep,ctx,ctx->A,idx_sc[color],&Mt,&T,&P,ini,t[0],v);
    411:       NEP_KSPSetOperators(nep->refineksp,T,P);
    412:       if (ini) {
    413:         KSPSetFromOptions(nep->refineksp);
    414:         if (nep->scheme==NEP_REFINE_SCHEME_EXPLICIT) {
    415:           MatCreateVecs(T,&dvv,NULL);
    416:           VecDuplicate(dvv,&rr);
    417:         }
    418:         ini = PETSC_FALSE;
    419:       }
    420:       switch (nep->scheme) {
    421:       case NEP_REFINE_SCHEME_EXPLICIT:
    422:         MatMult(Mt,v,r);
    423:         VecGetArrayRead(r,&array);
    424:         if (rank==size-1) {
    425:           VecGetArray(rr,&array2);
    426:           PetscArraycpy(array2,array,n);
    427:           array2[n] = 0.0;
    428:           VecRestoreArray(rr,&array2);
    429:         } else VecPlaceArray(rr,array);
    430:         KSPSolve(nep->refineksp,rr,dvv);
    431:         KSPGetConvergedReason(nep->refineksp,&reason);
    432:         if (reason>0) {
    433:           if (rank != size-1) VecResetArray(rr);
    434:           VecRestoreArrayRead(r,&array);
    435:           VecGetArrayRead(dvv,&array);
    436:           VecPlaceArray(dv,array);
    437:           VecAXPY(v,-1.0,dv);
    438:           VecNorm(v,NORM_2,&norm);
    439:           VecScale(v,1.0/norm);
    440:           VecResetArray(dv);
    441:           if (rank==size-1) nep->eigr[idx_sc[color]] -= array[n];
    442:           VecRestoreArrayRead(dvv,&array);
    443:         } else fail_sc[color] = 1;
    444:         break;
    445:       case NEP_REFINE_SCHEME_MBE:
    446:         MatMult(T,v,r);
    447:         /* Mixed block elimination */
    448:         VecConjugate(v);
    449:         KSPSolveTranspose(nep->refineksp,v,t[0]);
    450:         KSPGetConvergedReason(nep->refineksp,&reason);
    451:         if (reason>0) {
    452:           VecConjugate(t[0]);
    453:           VecDot(ctx->w,t[0],&tt[0]);
    454:           KSPSolve(nep->refineksp,ctx->w,t[1]);
    455:           KSPGetConvergedReason(nep->refineksp,&reason);
    456:           if (reason>0) {
    457:             VecDot(t[1],v,&tt[1]);
    458:             VecDot(r,t[0],&ttt);
    459:             tt[0] = ttt/tt[0];
    460:             VecAXPY(r,-tt[0],ctx->w);
    461:             KSPSolve(nep->refineksp,r,dv);
    462:             KSPGetConvergedReason(nep->refineksp,&reason);
    463:             if (reason>0) {
    464:               VecDot(dv,v,&ttt);
    465:               tt[1] = ttt/tt[1];
    466:               VecAXPY(dv,-tt[1],t[1]);
    467:               deig = tt[0]+tt[1];
    468:             }
    469:           }
    470:           VecConjugate(v);
    471:           VecAXPY(v,-1.0,dv);
    472:           VecNorm(v,NORM_2,&norm);
    473:           VecScale(v,1.0/norm);
    474:           nep->eigr[idx_sc[color]] -= deig;
    475:           fail_sc[color] = 0;
    476:         } else {
    477:           VecConjugate(v);
    478:           fail_sc[color] = 1;
    479:         }
    480:         break;
    481:       case NEP_REFINE_SCHEME_SCHUR:
    482:         fail_sc[color] = 1;
    483:         MatShellGetContext(T,&fctx);
    484:         if (fctx->M4!=0.0) {
    485:           MatMult(fctx->M1,v,r);
    486:           KSPSolve(nep->refineksp,r,dv);
    487:           KSPGetConvergedReason(nep->refineksp,&reason);
    488:           if (reason>0) {
    489:             VecDot(dv,v,&deig);
    490:             deig *= -fctx->m3/fctx->M4;
    491:             VecAXPY(v,-1.0,dv);
    492:             VecNorm(v,NORM_2,&norm);
    493:             VecScale(v,1.0/norm);
    494:             nep->eigr[idx_sc[color]] -= deig;
    495:             fail_sc[color] = 0;
    496:           }
    497:         }
    498:         break;
    499:       }
    500:       if (nep->npart==1) BVRestoreColumn(nep->V,idx_sc[color],&v);
    501:     }
    502:   }
    503:   VecDestroy(&t[0]);
    504:   VecDestroy(&t[1]);
    505:   VecDestroy(&dv);
    506:   VecDestroy(&ctx->w);
    507:   VecDestroy(&r);
    508:   PetscFree3(idx_sc,its_sc,fail_sc);
    509:   VecScatterDestroy(&ctx->nst);
    510:   if (nep->npart>1) {
    511:     VecDestroy(&ctx->vg);
    512:     VecDestroy(&ctx->v);
    513:     for (i=0;i<nep->nt;i++) MatDestroy(&ctx->A[i]);
    514:     for (i=0;i<nep->npart;i++) VecScatterDestroy(&ctx->scatter_id[i]);
    515:     PetscFree2(ctx->A,ctx->scatter_id);
    516:   }
    517:   if (fctx && nep->scheme==NEP_REFINE_SCHEME_SCHUR) {
    518:     MatDestroy(&P);
    519:     MatDestroy(&fctx->M1);
    520:     PetscFree(fctx);
    521:   }
    522:   if (nep->scheme==NEP_REFINE_SCHEME_EXPLICIT) {
    523:     MatDestroy(&Mt);
    524:     VecDestroy(&dvv);
    525:     VecDestroy(&rr);
    526:     VecDestroy(&ctx->nv);
    527:     if (nep->npart>1) {
    528:       for (i=0;i<nep->nt;i++) FNDestroy(&ctx->fn[i]);
    529:       PetscFree(ctx->fn);
    530:     }
    531:   }
    532:   if (nep->scheme==NEP_REFINE_SCHEME_MBE) {
    533:     if (nep->npart>1) {
    534:       for (i=0;i<nep->nt;i++) FNDestroy(&ctx->fn[i]);
    535:       PetscFree(ctx->fn);
    536:     }
    537:   }
    538:   MatDestroy(&T);
    539:   PetscFree(ctx);
    540:   PetscLogEventEnd(NEP_Refine,nep,0,0,0);
    541:   PetscFunctionReturn(0);
    542: }