Date: 2016-09-29T11:12:55+00:00

Actual source code: neprefine.c
slepc-3.7.3 2016-09-29
Report Typos and Errors

      1: /*
      2:    Newton refinement for NEP, simple version.

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

      8:    This file is part of SLEPc.

     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/nepimpl.h>
     25: #include <slepcblaslapack.h>

     27: #define NREF_MAXIT 10

     29: typedef struct {
     30:   PetscSubcomm  subc;
     31:   VecScatter    *scatter_id,nst;
     32:   Mat           *A;
     33:   Vec           nv,vg,v,w;
     34:   FN            *fn;
     35: } NEPSimpNRefctx;

     37: typedef struct {
     38:   Mat          M1;
     39:   Vec          M2,M3;
     40:   PetscScalar  M4,m3;
     41: } FSubctx;

     45: static PetscErrorCode MatFSMult(Mat M ,Vec x,Vec y)
     46: {
     48:   FSubctx        *ctx;
     49:   PetscScalar    t;
     50:
     52:   MatShellGetContext(M,&ctx);
     53:   VecDot(x,ctx->M3,&t);
     54:   t *= ctx->m3/ctx->M4;
     55:   MatMult(ctx->M1,x,y);
     56:   VecAXPY(y,-t,ctx->M2);
     57:   return(0);
     58: }

     62: static PetscErrorCode NEPSimpleNRefSetUp(NEP nep,NEPSimpNRefctx **ctx_)
     63: {
     65:   PetscInt       i,si,j,n0,m0,nloc,*idx1,*idx2,ne;
     66:   IS             is1,is2;
     67:   NEPSimpNRefctx *ctx;
     68:   Vec            v;
     69:   PetscMPIInt    rank,size;

     72:   PetscCalloc1(1,ctx_);
     73:   ctx = *ctx_;
     74:   if (nep->npart==1) {
     75:     ctx->A  = nep->A;
     76:     ctx->fn = nep->f;
     77:   } else {
     78:     PetscMalloc2(nep->nt,&ctx->A,nep->npart,&ctx->scatter_id);

     80:     /* Duplicate matrices */
     81:     for (i=0;i<nep->nt;i++) {
     82:       MatCreateRedundantMatrix(nep->A[i],0,PetscSubcommChild(ctx->subc),MAT_INITIAL_MATRIX,&ctx->A[i]);
     83:     }
     84:     MatCreateVecs(ctx->A[0],&ctx->v,NULL);

     86:     /* Duplicate FNs */
     87:     PetscMalloc1(nep->nt,&ctx->fn);
     88:     for (i=0;i<nep->nt;i++) {
     89:       FNDuplicate(nep->f[i],PetscSubcommChild(ctx->subc),&ctx->fn[i]);
     90:     }

     92:     /* Create scatters for sending vectors to each subcommucator */
     93:     BVGetColumn(nep->V,0,&v);
     94:     VecGetOwnershipRange(v,&n0,&m0);
     95:     BVRestoreColumn(nep->V,0,&v);
     96:     VecGetLocalSize(ctx->v,&nloc);
     97:     PetscMalloc2(m0-n0,&idx1,m0-n0,&idx2);
     98:     VecCreateMPI(PetscObjectComm((PetscObject)nep),nloc,PETSC_DECIDE,&ctx->vg);
     99:     for (si=0;si<nep->npart;si++) {
    100:       j = 0;
    101:       for (i=n0;i<m0;i++) {
    102:         idx1[j]   = i;
    103:         idx2[j++] = i+nep->n*si;
    104:       }
    105:       ISCreateGeneral(PetscObjectComm((PetscObject)nep),(m0-n0),idx1,PETSC_COPY_VALUES,&is1);
    106:       ISCreateGeneral(PetscObjectComm((PetscObject)nep),(m0-n0),idx2,PETSC_COPY_VALUES,&is2);
    107:       BVGetColumn(nep->V,0,&v);
    108:       VecScatterCreate(v,is1,ctx->vg,is2,&ctx->scatter_id[si]);
    109:       BVRestoreColumn(nep->V,0,&v);
    110:       ISDestroy(&is1);
    111:       ISDestroy(&is2);
    112:     }
    113:     PetscFree2(idx1,idx2);
    114:   }
    115:   if (nep->scheme==NEP_REFINE_SCHEME_EXPLICIT) {
    116:     MPI_Comm_rank(PetscObjectComm((PetscObject)ctx->A[0]),&rank);
    117:     MPI_Comm_size(PetscObjectComm((PetscObject)ctx->A[0]),&size);
    118:     if (size>1) {
    119:       if (nep->npart==1) {
    120:         BVGetColumn(nep->V,0,&v);
    121:       } else v = ctx->v;
    122:       VecGetOwnershipRange(v,&n0,&m0);
    123:       ne = (rank == size-1)?nep->n:0;
    124:       VecCreateMPI(PetscObjectComm((PetscObject)ctx->A[0]),ne,PETSC_DECIDE,&ctx->nv);
    125:       PetscMalloc1(m0-n0,&idx1);
    126:       for (i=n0;i<m0;i++) {
    127:         idx1[i-n0] = i;
    128:       }
    129:       ISCreateGeneral(PetscObjectComm((PetscObject)nep),(m0-n0),idx1,PETSC_COPY_VALUES,&is1);
    130:       VecScatterCreate(v,is1,ctx->nv,is1,&ctx->nst);
    131:       if (nep->npart==1) {
    132:         BVRestoreColumn(nep->V,0,&v);
    133:       }
    134:       PetscFree(idx1);
    135:       ISDestroy(&is1);
    136:     }
    137:   }  return(0);
    138: }

    140: /*
    141:   Gather Eigenpair idx from subcommunicator with color sc
    142: */
    145: static PetscErrorCode NEPSimpleNRefGatherEigenpair(NEP nep,NEPSimpNRefctx *ctx,PetscInt sc,PetscInt idx,PetscInt *fail)
    146: {
    148:   PetscMPIInt    nproc,p;
    149:   MPI_Comm       comm=((PetscObject)nep)->comm;
    150:   Vec            v;
    151:   PetscScalar    *array;

    154:   if (nep->npart>1) {
    155:     MPI_Comm_size(comm,&nproc);
    156:     p = (nproc/nep->npart)*sc+PetscMin(sc,nproc%nep->npart);
    157:     /* Communicate convergence successful */
    158:     MPI_Bcast(fail,1,MPIU_INT,p,comm);
    159:     if (!(*fail)) {
    160:       /* Process 0 of subcommunicator sc broadcasts the eigenvalue */
    161:       MPI_Bcast(&nep->eigr[idx],1,MPIU_SCALAR,p,comm);
    162:       /* Gather nep->V[idx] from the subcommuniator sc */
    163:       BVGetColumn(nep->V,idx,&v);
    164:       if (ctx->subc->color==sc) {
    165:         VecGetArray(ctx->v,&array);
    166:         VecPlaceArray(ctx->vg,array);
    167:       }
    168:       VecScatterBegin(ctx->scatter_id[sc],ctx->vg,v,INSERT_VALUES,SCATTER_REVERSE);
    169:       VecScatterEnd(ctx->scatter_id[sc],ctx->vg,v,INSERT_VALUES,SCATTER_REVERSE);
    170:       if (ctx->subc->color==sc) {
    171:         VecResetArray(ctx->vg);
    172:         VecRestoreArray(ctx->v,&array);
    173:       }
    174:       BVRestoreColumn(nep->V,idx,&v);
    175:     }
    176:   } else {
    177:     if (nep->scheme==NEP_REFINE_SCHEME_EXPLICIT && !(*fail)) {
    178:       MPI_Comm_size(comm,&nproc);
    179:       p = (nproc/nep->npart)*sc+PetscMin(sc,nproc%nep->npart);
    180:       MPI_Bcast(&nep->eigr[idx],1,MPIU_SCALAR,p,comm);
    181:     }
    182:   }
    183:   return(0);
    184: }

    188: static PetscErrorCode NEPSimpleNRefScatterEigenvector(NEP nep,NEPSimpNRefctx *ctx,PetscInt sc,PetscInt idx)
    189: {
    191:   Vec            v;
    192:   PetscScalar    *array;
    193:
    195:   if (nep->npart>1) {
    196:     BVGetColumn(nep->V,idx,&v);
    197:     if (ctx->subc->color==sc) {
    198:       VecGetArray(ctx->v,&array);
    199:       VecPlaceArray(ctx->vg,array);
    200:     }
    201:     VecScatterBegin(ctx->scatter_id[sc],v,ctx->vg,INSERT_VALUES,SCATTER_FORWARD);
    202:     VecScatterEnd(ctx->scatter_id[sc],v,ctx->vg,INSERT_VALUES,SCATTER_FORWARD);
    203:     if (ctx->subc->color==sc) {
    204:       VecResetArray(ctx->vg);
    205:       VecRestoreArray(ctx->v,&array);
    206:     }
    207:     BVRestoreColumn(nep->V,idx,&v);
    208:   }
    209:   return(0);
    210: }

    214: static PetscErrorCode NEPSimpleNRefSetUpSystem(NEP nep,NEPSimpNRefctx *ctx,Mat *A,PetscInt idx,Mat *Mt,Mat *T,Mat *P,PetscBool ini,Vec t,Vec v)
    215: {
    216:   PetscErrorCode    ierr;
    217:   PetscInt          i,st,ml,m0,n0,m1,mg;
    218:   PetscInt          *dnz,*onz,ncols,*cols2,*nnz,nt=nep->nt;
    219:   PetscScalar       zero=0.0,*coeffs,*coeffs2;
    220:   PetscMPIInt       rank,size;
    221:   MPI_Comm          comm;
    222:   const PetscInt    *cols;
    223:   const PetscScalar *vals,*array;
    224:   FSubctx           *fctx;
    225:   Vec               w=ctx->w;
    226:   Mat               M;

    229:   PetscMalloc2(nt,&coeffs,nt,&coeffs2);
    230:   switch (nep->scheme) {
    231:   case NEP_REFINE_SCHEME_SCHUR:
    232:     if (ini) {
    233:       PetscCalloc1(1,&fctx);
    234:       MatGetSize(A[0],&m0,&n0);
    235:       MatCreateShell(PetscObjectComm((PetscObject)A[0]),PETSC_DECIDE,PETSC_DECIDE,m0,n0,fctx,T);
    236:       MatShellSetOperation(*T,MATOP_MULT,(void(*)(void))MatFSMult);
    237:     } else {
    238:       MatShellGetContext(*T,&fctx);
    239:     }
    240:     M=fctx->M1;
    241:     break;
    242:   case NEP_REFINE_SCHEME_MBE:
    243:     M=*T;
    244:     break;
    245:   case NEP_REFINE_SCHEME_EXPLICIT:
    246:     M=*Mt;
    247:     break;
    248:   }
    249:   if (ini) {
    250:     MatDuplicate(A[0],MAT_COPY_VALUES,&M);
    251:   } else {
    252:     MatCopy(A[0],M,DIFFERENT_NONZERO_PATTERN);
    253:   }
    254:   for (i=0;i<nt;i++) {
    255:     FNEvaluateFunction(ctx->fn[i],nep->eigr[idx],coeffs+i);
    256:   }
    257:   if (coeffs[0]!=1.0) {
    258:     MatScale(M,coeffs[0]);
    259:   }
    260:   for (i=1;i<nt;i++) {
    261:     MatAXPY(M,coeffs[i],A[i],(ini)?nep->mstr:SUBSET_NONZERO_PATTERN);
    262:   }
    263:   for (i=0;i<nt;i++) {
    264:     FNEvaluateDerivative(ctx->fn[i],nep->eigr[idx],coeffs2+i);
    265:   }
    266:   st = 0;
    267:   for (i=0;i<nt && PetscAbsScalar(coeffs2[i])==0.0;i++) st++;
    268:   MatMult(A[st],v,w);
    269:   if (coeffs2[st]!=1.0) {
    270:     VecScale(w,coeffs2[st]);
    271:   }
    272:   for (i=st+1;i<nt;i++) {
    273:     MatMult(A[i],v,t);
    274:     VecAXPY(w,coeffs2[i],t);
    275:   }

    277:   switch (nep->scheme) {
    278:   case NEP_REFINE_SCHEME_EXPLICIT:
    279:     comm = PetscObjectComm((PetscObject)A[0]);
    280:     MPI_Comm_rank(comm,&rank);
    281:     MPI_Comm_size(comm,&size);
    282:     MatGetSize(M,&mg,NULL);
    283:     MatGetOwnershipRange(M,&m0,&m1);
    284:     if (ini) {
    285:       MatCreate(comm,T);
    286:       MatGetLocalSize(M,&ml,NULL);
    287:       if (rank==size-1) ml++;
    288:       MatSetSizes(*T,ml,ml,mg+1,mg+1);
    289:       MatSetFromOptions(*T);
    290:       MatSetUp(*T);
    291:       /* Preallocate M */
    292:       if (size>1) {
    293:         MatPreallocateInitialize(comm,ml,ml,dnz,onz);
    294:         for (i=m0;i<m1;i++) {
    295:           MatGetRow(M,i,&ncols,&cols,NULL);
    296:           MatPreallocateSet(i,ncols,cols,dnz,onz);
    297:           MatPreallocateSet(i,1,&mg,dnz,onz);
    298:           MatRestoreRow(M,i,&ncols,&cols,NULL);
    299:         }
    300:         if (rank==size-1) {
    301:           PetscCalloc1(mg+1,&cols2);
    302:           for (i=0;i<mg+1;i++) cols2[i]=i;
    303:           MatPreallocateSet(m1,mg+1,cols2,dnz,onz);
    304:           PetscFree(cols2);
    305:         }
    306:         MatMPIAIJSetPreallocation(*T,0,dnz,0,onz);
    307:         MatPreallocateFinalize(dnz,onz);
    308:       } else {
    309:         PetscCalloc1(mg+1,&nnz);
    310:         for (i=0;i<mg;i++) {
    311:           MatGetRow(M,i,&ncols,NULL,NULL);
    312:           nnz[i] = ncols+1;
    313:           MatRestoreRow(M,i,&ncols,NULL,NULL);
    314:         }
    315:         nnz[mg] = mg+1;
    316:         MatSeqAIJSetPreallocation(*T,0,nnz);
    317:         PetscFree(nnz);
    318:       }
    319:       *Mt = M;
    320:       *P  = *T;
    321:     }
    322:
    323:     /* Set values */
    324:     VecGetArrayRead(w,&array);
    325:     for (i=m0;i<m1;i++) {
    326:       MatGetRow(M,i,&ncols,&cols,&vals);
    327:       MatSetValues(*T,1,&i,ncols,cols,vals,INSERT_VALUES);
    328:       MatRestoreRow(M,i,&ncols,&cols,&vals);
    329:       MatSetValues(*T,1,&i,1,&mg,array+i-m0,INSERT_VALUES);
    330:     }
    331:     VecRestoreArrayRead(w,&array);
    332:     VecConjugate(v);
    333:     MPI_Comm_size(PetscObjectComm((PetscObject)A[0]),&size);
    334:     MPI_Comm_rank(PetscObjectComm((PetscObject)A[0]),&rank);
    335:     if (size>1) {
    336:       if (rank==size-1) {
    337:         PetscMalloc1(nep->n,&cols2);
    338:         for (i=0;i<nep->n;i++) cols2[i]=i;
    339:       }
    340:       VecScatterBegin(ctx->nst,v,ctx->nv,INSERT_VALUES,SCATTER_FORWARD);
    341:       VecScatterEnd(ctx->nst,v,ctx->nv,INSERT_VALUES,SCATTER_FORWARD);
    342:       VecGetArrayRead(ctx->nv,&array);
    343:       if (rank==size-1) {
    344:         MatSetValues(*T,1,&mg,nep->n,cols2,array,INSERT_VALUES);
    345:         MatSetValues(*T,1,&mg,1,&mg,&zero,INSERT_VALUES);
    346:       }
    347:       VecRestoreArrayRead(ctx->nv,&array);
    348:     } else {
    349:       PetscMalloc1(m1-m0,&cols2);
    350:       for (i=0;i<m1-m0;i++) cols2[i]=m0+i;
    351:       VecGetArrayRead(v,&array);
    352:       MatSetValues(*T,1,&mg,m1-m0,cols2,array,INSERT_VALUES);
    353:       MatSetValues(*T,1,&mg,1,&mg,&zero,INSERT_VALUES);
    354:       VecRestoreArrayRead(v,&array);
    355:     }
    356:     VecConjugate(v);
    357:     MatAssemblyBegin(*T,MAT_FINAL_ASSEMBLY);
    358:     MatAssemblyEnd(*T,MAT_FINAL_ASSEMBLY);
    359:     PetscFree(cols2);
    360:     break;
    361:   case NEP_REFINE_SCHEME_SCHUR:
    362:     fctx->M2 = ctx->w;
    363:     fctx->M3 = v;
    364:     fctx->m3 = 0.0;
    365:     for (i=1;i<nt-1;i++) fctx->m3 += PetscConj(coeffs[i])*coeffs[i];
    366:     fctx->M4 = 0.0;
    367:     for (i=1;i<nt-1;i++) fctx->M4 += PetscConj(coeffs[i])*coeffs2[i];
    368:     fctx->M1 = M;
    369:     if (ini) {
    370:       MatDuplicate(M,MAT_COPY_VALUES,P);
    371:     } else {
    372:       MatCopy(M,*P,SAME_NONZERO_PATTERN);
    373:     }
    374:     VecConjugate(v);
    375:     VecPointwiseMult(t,v,w);
    376:     VecConjugate(v);
    377:     VecScale(t,-fctx->m3/fctx->M4);
    378:     MatDiagonalSet(*P,t,ADD_VALUES);
    379:     break;
    380:   case NEP_REFINE_SCHEME_MBE:
    381:     *T = M;
    382:     *P = M;
    383:     break;
    384:   }
    385:   PetscFree2(coeffs,coeffs2);
    386:   return(0);
    387: }

    391: PetscErrorCode NEPNewtonRefinementSimple(NEP nep,PetscInt *maxits,PetscReal tol,PetscInt k)
    392: {
    393:   PetscErrorCode    ierr;
    394:   PetscInt          i,n,its,idx=0,*idx_sc,*its_sc,color,*fail_sc;
    395:   PetscMPIInt       rank,size;
    396:   Mat               Mt=NULL,T=NULL,P=NULL;
    397:   MPI_Comm          comm;
    398:   Vec               r,v,dv,rr=NULL,dvv=NULL,t[2];
    399:   const PetscScalar *array;
    400:   PetscScalar       *array2,deig=0.0,tt[2],ttt;
    401:   PetscReal         norm,error;
    402:   PetscBool         ini=PETSC_TRUE,sc_pend,solved=PETSC_FALSE;
    403:   NEPSimpNRefctx    *ctx;
    404:   FSubctx            *fctx=NULL;
    405:   KSPConvergedReason reason;

    408:   PetscLogEventBegin(NEP_Refine,nep,0,0,0);
    409:   NEPSimpleNRefSetUp(nep,&ctx);
    410:   its = (maxits)?*maxits:NREF_MAXIT;
    411:   comm = (nep->npart==1)?PetscObjectComm((PetscObject)nep):PetscSubcommChild(ctx->subc);
    412:   if (!nep->refineksp) { NEPRefineGetKSP(nep,&nep->refineksp); }
    413:   if (nep->npart==1) {
    414:     BVGetColumn(nep->V,0,&v);
    415:   } else v = ctx->v;
    416:   VecDuplicate(v,&ctx->w);
    417:   VecDuplicate(v,&r);
    418:   VecDuplicate(v,&dv);
    419:   VecDuplicate(v,&t[0]);
    420:   VecDuplicate(v,&t[1]);
    421:   if (nep->npart==1) { BVRestoreColumn(nep->V,0,&v); }
    422:   MPI_Comm_size(comm,&size);
    423:   MPI_Comm_rank(comm,&rank);
    424:   VecGetLocalSize(r,&n);
    425:   PetscMalloc3(nep->npart,&idx_sc,nep->npart,&its_sc,nep->npart,&fail_sc);
    426:   for (i=0;i<nep->npart;i++) fail_sc[i] = 0;
    427:   for (i=0;i<nep->npart;i++) its_sc[i] = 0;
    428:   color = (nep->npart==1)?0:ctx->subc->color;
    429:
    430:   /* Loop performing iterative refinements */
    431:   while (!solved) {
    432:     for (i=0;i<nep->npart;i++) {
    433:       sc_pend = PETSC_TRUE;
    434:       if (its_sc[i]==0) {
    435:         idx_sc[i] = idx++;
    436:         if (idx_sc[i]>=k) {
    437:           sc_pend = PETSC_FALSE;
    438:         } else {
    439:           NEPSimpleNRefScatterEigenvector(nep,ctx,i,idx_sc[i]);
    440:         }
    441:       }  else { /* Gather Eigenpair from subcommunicator i */
    442:         NEPSimpleNRefGatherEigenpair(nep,ctx,i,idx_sc[i],&fail_sc[i]);
    443:       }
    444:       while (sc_pend) {
    445:         if (!fail_sc[i]) {
    446:           NEPComputeError(nep,idx_sc[i],NEP_ERROR_RELATIVE,&error);
    447:         }
    448:         if (error<=tol || its_sc[i]>=its || fail_sc[i]) {
    449:           idx_sc[i] = idx++;
    450:           its_sc[i] = 0;
    451:           if (idx_sc[i]<k) { NEPSimpleNRefScatterEigenvector(nep,ctx,i,idx_sc[i]); }
    452:         } else {
    453:           sc_pend = PETSC_FALSE;
    454:           its_sc[i]++;
    455:         }
    456:         if (idx_sc[i]>=k) sc_pend = PETSC_FALSE;
    457:       }
    458:     }
    459:     solved = PETSC_TRUE;
    460:     for (i=0;i<nep->npart&&solved;i++) solved = PetscNot(idx_sc[i]<k);
    461:     if (idx_sc[color]<k) {
    462: #if !defined(PETSC_USE_COMPLEX)
    463:       if (nep->eigi[idx_sc[color]]!=0.0) SETERRQ(PetscObjectComm((PetscObject)nep),1,"Simple Refinement not implemented in real scalar for complex eigenvalues");
    464: #endif
    465:       if (nep->npart==1) {
    466:         BVGetColumn(nep->V,idx_sc[color],&v);
    467:       } else v = ctx->v;
    468:       NEPSimpleNRefSetUpSystem(nep,ctx,ctx->A,idx_sc[color],&Mt,&T,&P,ini,t[0],v);
    469:       KSPSetOperators(nep->refineksp,T,P);
    470:       if (ini) {
    471:         KSPSetFromOptions(nep->refineksp);
    472:         if (nep->scheme==NEP_REFINE_SCHEME_EXPLICIT) {
    473:           MatCreateVecs(T,&dvv,NULL);
    474:           VecDuplicate(dvv,&rr);
    475:         }
    476:         ini = PETSC_FALSE;
    477:       }
    478:       switch (nep->scheme) {
    479:       case NEP_REFINE_SCHEME_EXPLICIT:
    480:         MatMult(Mt,v,r);
    481:         VecGetArrayRead(r,&array);
    482:         if (rank==size-1) {
    483:           VecGetArray(rr,&array2);
    484:           PetscMemcpy(array2,array,n*sizeof(PetscScalar));
    485:           array2[n] = 0.0;
    486:           VecRestoreArray(rr,&array2);
    487:         } else {
    488:           VecPlaceArray(rr,array);
    489:         }
    490:         KSPSolve(nep->refineksp,rr,dvv);
    491:         KSPGetConvergedReason(nep->refineksp,&reason);
    492:         if (reason>0) {
    493:           if (rank != size-1) {
    494:             VecResetArray(rr);
    495:           }
    496:           VecRestoreArrayRead(r,&array);
    497:           VecGetArrayRead(dvv,&array);
    498:           VecPlaceArray(dv,array);
    499:           VecAXPY(v,-1.0,dv);
    500:           VecNorm(v,NORM_2,&norm);
    501:           VecScale(v,1.0/norm);
    502:           VecResetArray(dv);
    503:           if (rank==size-1) nep->eigr[idx_sc[color]] -= array[n];
    504:           VecRestoreArrayRead(dvv,&array);
    505:         } else fail_sc[color] = 1;
    506:         break;
    507:       case NEP_REFINE_SCHEME_MBE:
    508:         MatMult(T,v,r);
    509:         /* Mixed block elimination */
    510:         VecConjugate(v);
    511:         KSPSolveTranspose(nep->refineksp,v,t[0]);
    512:         KSPGetConvergedReason(nep->refineksp,&reason);
    513:         if (reason>0) {
    514:           VecConjugate(t[0]);
    515:           VecDot(ctx->w,t[0],&tt[0]);
    516:           KSPSolve(nep->refineksp,ctx->w,t[1]);
    517:           KSPGetConvergedReason(nep->refineksp,&reason);
    518:           if (reason>0) {
    519:             VecDot(t[1],v,&tt[1]);
    520:             VecDot(r,t[0],&ttt);
    521:             tt[0] = ttt/tt[0];
    522:             VecAXPY(r,-tt[0],ctx->w);
    523:             KSPSolve(nep->refineksp,r,dv);
    524:             KSPGetConvergedReason(nep->refineksp,&reason);
    525:             if (reason>0) {
    526:               VecDot(dv,v,&ttt);
    527:               tt[1] = ttt/tt[1];
    528:               VecAXPY(dv,-tt[1],t[1]);
    529:               deig = tt[0]+tt[1];
    530:             }
    531:           }
    532:           VecConjugate(v);
    533:           VecAXPY(v,-1.0,dv);
    534:           VecNorm(v,NORM_2,&norm);
    535:           VecScale(v,1.0/norm);
    536:           nep->eigr[idx_sc[color]] -= deig;
    537:           fail_sc[color] = 0;
    538:         } else {
    539:           VecConjugate(v);
    540:           fail_sc[color] = 1;
    541:         }
    542:         break;
    543:       case NEP_REFINE_SCHEME_SCHUR:
    544:         MatShellGetContext(T,&fctx);
    545:         MatMult(fctx->M1,v,r);
    546:         KSPSolve(nep->refineksp,r,dv);
    547:         KSPGetConvergedReason(nep->refineksp,&reason);
    548:         if (reason>0) {
    549:           VecDot(dv,v,&deig);
    550:           deig *= -fctx->m3/fctx->M4;
    551:           VecAXPY(v,-1.0,dv);
    552:           VecNorm(v,NORM_2,&norm);
    553:           VecScale(v,1.0/norm);
    554:           nep->eigr[idx_sc[color]] -= deig;
    555:           fail_sc[color] = 0;
    556:         } else fail_sc[color] = 1;
    557:         break;
    558:       }
    559:       if (nep->npart==1) { BVRestoreColumn(nep->V,idx_sc[color],&v); }
    560:     }
    561:   }
    562:   VecDestroy(&t[0]);
    563:   VecDestroy(&t[1]);
    564:   VecDestroy(&dv);
    565:   VecDestroy(&ctx->w);
    566:   VecDestroy(&r);
    567:   PetscFree3(idx_sc,its_sc,fail_sc);
    568:   VecScatterDestroy(&ctx->nst);
    569:   if (nep->npart>1) {
    570:     VecDestroy(&ctx->vg);
    571:     VecDestroy(&ctx->v);
    572:     for (i=0;i<nep->nt;i++) {
    573:       MatDestroy(&ctx->A[i]);
    574:     }
    575:     for (i=0;i<nep->npart;i++) {
    576:       VecScatterDestroy(&ctx->scatter_id[i]);
    577:     }
    578:     PetscFree2(ctx->A,ctx->scatter_id);
    579:   }
    580:   if (fctx && nep->scheme==NEP_REFINE_SCHEME_SCHUR) {
    581:     MatDestroy(&P);
    582:     MatDestroy(&fctx->M1);
    583:     PetscFree(fctx);
    584:   }
    585:   if (nep->scheme==NEP_REFINE_SCHEME_EXPLICIT) {
    586:     MatDestroy(&Mt);
    587:     VecDestroy(&dvv);
    588:     VecDestroy(&rr);
    589:     VecDestroy(&ctx->nv);
    590:     if (nep->npart>1) {
    591:       for (i=0;i<nep->nt;i++) { FNDestroy(&ctx->fn[i]); }
    592:       PetscFree(ctx->fn);
    593:     }
    594:   }
    595:   MatDestroy(&T);
    596:   PetscFree(ctx);
    597:   PetscLogEventEnd(NEP_Refine,nep,0,0,0);
    598:   return(0);
    599: }