Date: 2021-09-20T09:43:51+00:00

Actual source code: ks-indef.c
slepc-3.15.2 2021-09-20
Report Typos and Errors

      1: /*
      2:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      3:    SLEPc - Scalable Library for Eigenvalue Problem Computations
      4:    Copyright (c) 2002-2021, 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:    SLEPc eigensolver: "krylovschur"

     13:    Method: Krylov-Schur for symmetric-indefinite eigenproblems
     14: */
     15: #include <slepc/private/epsimpl.h>
     16: #include "krylovschur.h"

     18: PetscErrorCode EPSSolve_KrylovSchur_Indefinite(EPS eps)
     19: {
     20:   PetscErrorCode  ierr;
     21:   EPS_KRYLOVSCHUR *ctx = (EPS_KRYLOVSCHUR*)eps->data;
     22:   PetscInt        i,k,l,ld,nv,t,nconv=0;
     23:   Mat             U;
     24:   Vec             vomega,w=eps->work[0];
     25:   PetscScalar     *aux;
     26:   PetscReal       *a,*b,beta,beta1=1.0,*omega;
     27:   PetscBool       breakdown=PETSC_FALSE,symmlost=PETSC_FALSE;

     30:   DSGetLeadingDimension(eps->ds,&ld);

     32:   /* Get the starting Lanczos vector */
     33:   EPSGetStartVector(eps,0,NULL);

     35:   /* Extract sigma[0] from BV, computed during normalization */
     36:   BVSetActiveColumns(eps->V,0,1);
     37:   VecCreateSeq(PETSC_COMM_SELF,1,&vomega);
     38:   BVGetSignature(eps->V,vomega);
     39:   VecGetArray(vomega,&aux);
     40:   DSGetArrayReal(eps->ds,DS_MAT_D,&omega);
     41:   omega[0] = PetscRealPart(aux[0]);
     42:   DSRestoreArrayReal(eps->ds,DS_MAT_D,&omega);
     43:   VecRestoreArray(vomega,&aux);
     44:   VecDestroy(&vomega);
     45:   l = 0;

     47:   /* Restart loop */
     48:   while (eps->reason == EPS_CONVERGED_ITERATING) {
     49:     eps->its++;

     51:     /* Compute an nv-step Lanczos factorization */
     52:     nv = PetscMin(eps->nconv+eps->mpd,eps->ncv);
     53:     DSGetArrayReal(eps->ds,DS_MAT_T,&a);
     54:     b = a + ld;
     55:     DSGetArrayReal(eps->ds,DS_MAT_D,&omega);
     56:     EPSPseudoLanczos(eps,a,b,omega,eps->nconv+l,&nv,&breakdown,&symmlost,NULL,w);
     57:     if (symmlost) {
     58:       eps->reason = EPS_DIVERGED_SYMMETRY_LOST;
     59:       if (nv==eps->nconv+l+1) { eps->nconv = nconv; break; }
     60:     }
     61:     beta = b[nv-1];
     62:     DSRestoreArrayReal(eps->ds,DS_MAT_T,&a);
     63:     DSRestoreArrayReal(eps->ds,DS_MAT_D,&omega);
     64:     DSSetDimensions(eps->ds,nv,0,eps->nconv,eps->nconv+l);
     65:     if (l==0) {
     66:       DSSetState(eps->ds,DS_STATE_INTERMEDIATE);
     67:     } else {
     68:       DSSetState(eps->ds,DS_STATE_RAW);
     69:     }
     70:     BVSetActiveColumns(eps->V,eps->nconv,nv);

     72:     /* Solve projected problem */
     73:     DSSolve(eps->ds,eps->eigr,eps->eigi);
     74:     DSSort(eps->ds,eps->eigr,eps->eigi,NULL,NULL,NULL);
     75:     DSUpdateExtraRow(eps->ds);
     76:     DSSynchronize(eps->ds,eps->eigr,eps->eigi);

     78:     /* Check convergence */
     79:     DSGetDimensions(eps->ds,NULL,NULL,NULL,NULL,&t);
     80: #if 0
     81:     /* take into account also left residual */
     82:     BVGetColumn(eps->V,nv,&u);
     83:     VecNorm(u,NORM_2,&beta1);
     84:     BVRestoreColumn(eps->V,nv,&u);
     85:     VecNorm(w,NORM_2,&beta2);  /* w contains B*V[nv] */
     86:     beta1 = PetscMax(beta1,beta2);
     87: #endif
     88:     EPSKrylovConvergence(eps,PETSC_FALSE,eps->nconv,t-eps->nconv,beta*beta1,0.0,1.0,&k);
     89:     (*eps->stopping)(eps,eps->its,eps->max_it,k,eps->nev,&eps->reason,eps->stoppingctx);
     90:     nconv = k;

     92:     /* Update l */
     93:     if (eps->reason != EPS_CONVERGED_ITERATING || breakdown) l = 0;
     94:     else {
     95:       l = PetscMax(1,(PetscInt)((nv-k)*ctx->keep));
     96:       l = PetscMin(l,t);
     97:       DSGetTruncateSize(eps->ds,k,t,&l);
     98:     }
     99:     if (!ctx->lock && l>0) { l += k; k = 0; } /* non-locking variant: reset no. of converged pairs */
    100:     if (l) { PetscInfo1(eps,"Preparing to restart keeping l=%D vectors\n",l); }

    102:     if (eps->reason == EPS_CONVERGED_ITERATING) {
    103:       if (breakdown) SETERRQ1(PetscObjectComm((PetscObject)eps),PETSC_ERR_CONV_FAILED,"Breakdown in Indefinite Krylov-Schur (beta=%g)",beta);
    104:       else {
    105:         /* Prepare the Rayleigh quotient for restart */
    106:         DSTruncate(eps->ds,k+l,PETSC_FALSE);
    107:       }
    108:     }
    109:     /* Update the corresponding vectors V(:,idx) = V*Q(:,idx) */
    110:     DSGetMat(eps->ds,DS_MAT_Q,&U);
    111:     BVMultInPlace(eps->V,U,eps->nconv,k+l);
    112:     MatDestroy(&U);

    114:     /* Move restart vector and update signature */
    115:     if (eps->reason == EPS_CONVERGED_ITERATING && !breakdown) {
    116:       BVCopyColumn(eps->V,nv,k+l);
    117:       DSGetArrayReal(eps->ds,DS_MAT_D,&omega);
    118:       VecCreateSeq(PETSC_COMM_SELF,k+l,&vomega);
    119:       VecGetArray(vomega,&aux);
    120:       for (i=0;i<k+l;i++) aux[i] = omega[i];
    121:       VecRestoreArray(vomega,&aux);
    122:       BVSetActiveColumns(eps->V,0,k+l);
    123:       BVSetSignature(eps->V,vomega);
    124:       VecDestroy(&vomega);
    125:       DSRestoreArrayReal(eps->ds,DS_MAT_D,&omega);
    126:     }

    128:     eps->nconv = k;
    129:     EPSMonitor(eps,eps->its,nconv,eps->eigr,eps->eigi,eps->errest,nv);
    130:   }
    131:   DSTruncate(eps->ds,eps->nconv,PETSC_TRUE);
    132:   return(0);
    133: }