LCOV - code coverage report
Current view: top level - pep/impls/krylov/qarnoldi - qarnoldi.c (source / functions) Hit Total Coverage
Test: SLEPc Lines: 265 276 96.0 %
Date: 2024-11-21 00:34:55 Functions: 16 17 94.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       3             :    SLEPc - Scalable Library for Eigenvalue Problem Computations
       4             :    Copyright (c) 2002-, Universitat Politecnica de Valencia, Spain
       5             : 
       6             :    This file is part of SLEPc.
       7             :    SLEPc is distributed under a 2-clause BSD license (see LICENSE).
       8             :    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       9             : */
      10             : /*
      11             :    SLEPc quadratic eigensolver: "qarnoldi"
      12             : 
      13             :    Method: Q-Arnoldi
      14             : 
      15             :    Algorithm:
      16             : 
      17             :        Quadratic Arnoldi with Krylov-Schur type restart.
      18             : 
      19             :    References:
      20             : 
      21             :        [1] K. Meerbergen, "The Quadratic Arnoldi method for the solution
      22             :            of the quadratic eigenvalue problem", SIAM J. Matrix Anal.
      23             :            Appl. 30(4):1462-1482, 2008.
      24             : */
      25             : 
      26             : #include <slepc/private/pepimpl.h>    /*I "slepcpep.h" I*/
      27             : #include <petscblaslapack.h>
      28             : 
      29             : typedef struct {
      30             :   PetscReal keep;         /* restart parameter */
      31             :   PetscBool lock;         /* locking/non-locking variant */
      32             : } PEP_QARNOLDI;
      33             : 
      34          16 : static PetscErrorCode PEPSetUp_QArnoldi(PEP pep)
      35             : {
      36          16 :   PEP_QARNOLDI   *ctx = (PEP_QARNOLDI*)pep->data;
      37          16 :   PetscBool      flg;
      38             : 
      39          16 :   PetscFunctionBegin;
      40          16 :   PEPCheckQuadratic(pep);
      41          16 :   PEPCheckShiftSinvert(pep);
      42          16 :   PetscCall(PEPSetDimensions_Default(pep,pep->nev,&pep->ncv,&pep->mpd));
      43          16 :   PetscCheck(ctx->lock || pep->mpd>=pep->ncv,PetscObjectComm((PetscObject)pep),PETSC_ERR_SUP,"Should not use mpd parameter in non-locking variant");
      44          16 :   if (pep->max_it==PETSC_DETERMINE) pep->max_it = PetscMax(100,4*pep->n/pep->ncv);
      45          16 :   if (!pep->which) PetscCall(PEPSetWhichEigenpairs_Default(pep));
      46          16 :   PetscCheck(pep->which!=PEP_ALL,PetscObjectComm((PetscObject)pep),PETSC_ERR_SUP,"This solver does not support computing all eigenvalues");
      47             : 
      48          16 :   PetscCall(STGetTransform(pep->st,&flg));
      49          16 :   PetscCheck(flg,PetscObjectComm((PetscObject)pep),PETSC_ERR_SUP,"Solver requires the ST transformation flag set, see STSetTransform()");
      50             : 
      51             :   /* set default extraction */
      52          16 :   if (!pep->extract) pep->extract = PEP_EXTRACT_NONE;
      53          16 :   PEPCheckUnsupported(pep,PEP_FEATURE_NONMONOMIAL | PEP_FEATURE_EXTRACT);
      54             : 
      55          16 :   if (!ctx->keep) ctx->keep = 0.5;
      56             : 
      57          16 :   PetscCall(PEPAllocateSolution(pep,0));
      58          16 :   PetscCall(PEPSetWorkVecs(pep,4));
      59             : 
      60          16 :   PetscCall(DSSetType(pep->ds,DSNHEP));
      61          16 :   PetscCall(DSSetExtraRow(pep->ds,PETSC_TRUE));
      62          16 :   PetscCall(DSAllocate(pep->ds,pep->ncv+1));
      63          16 :   PetscFunctionReturn(PETSC_SUCCESS);
      64             : }
      65             : 
      66          16 : static PetscErrorCode PEPExtractVectors_QArnoldi(PEP pep)
      67             : {
      68          16 :   PetscInt       k=pep->nconv;
      69          16 :   Mat            X,X0;
      70             : 
      71          16 :   PetscFunctionBegin;
      72          16 :   if (pep->nconv==0) PetscFunctionReturn(PETSC_SUCCESS);
      73          16 :   PetscCall(DSVectors(pep->ds,DS_MAT_X,NULL,NULL));
      74             : 
      75             :   /* update vectors V = V*X */
      76          16 :   PetscCall(DSGetMat(pep->ds,DS_MAT_X,&X));
      77          16 :   PetscCall(MatDenseGetSubMatrix(X,0,k,0,k,&X0));
      78          16 :   PetscCall(BVMultInPlace(pep->V,X0,0,k));
      79          16 :   PetscCall(MatDenseRestoreSubMatrix(X,&X0));
      80          16 :   PetscCall(DSRestoreMat(pep->ds,DS_MAT_X,&X));
      81          16 :   PetscFunctionReturn(PETSC_SUCCESS);
      82             : }
      83             : 
      84             : /*
      85             :   Compute a step of Classical Gram-Schmidt orthogonalization
      86             : */
      87        2695 : static PetscErrorCode PEPQArnoldiCGS(PEP pep,PetscScalar *H,PetscBLASInt ldh,PetscScalar *h,PetscBLASInt j,BV V,Vec t,Vec v,Vec w,PetscReal *onorm,PetscReal *norm,PetscScalar *work)
      88             : {
      89        2695 :   PetscBLASInt   ione = 1,j_1 = j+1;
      90        2695 :   PetscReal      x,y;
      91        2695 :   PetscScalar    dot,one = 1.0,zero = 0.0;
      92             : 
      93        2695 :   PetscFunctionBegin;
      94             :   /* compute norm of v and w */
      95        2695 :   if (onorm) {
      96        1362 :     PetscCall(VecNorm(v,NORM_2,&x));
      97        1362 :     PetscCall(VecNorm(w,NORM_2,&y));
      98        1362 :     *onorm = SlepcAbs(x,y);
      99             :   }
     100             : 
     101             :   /* orthogonalize: compute h */
     102        2695 :   PetscCall(BVDotVec(V,v,h));
     103        2695 :   PetscCall(BVDotVec(V,w,work));
     104        2695 :   if (j>0) PetscCallBLAS("BLASgemv",BLASgemv_("C",&j_1,&j,&one,H,&ldh,work,&ione,&one,h,&ione));
     105        2695 :   PetscCall(VecDot(w,t,&dot));
     106        2695 :   h[j] += dot;
     107             : 
     108             :   /* orthogonalize: update v and w */
     109        2695 :   PetscCall(BVMultVec(V,-1.0,1.0,v,h));
     110        2695 :   if (j>0) {
     111        2677 :     PetscCallBLAS("BLASgemv",BLASgemv_("N",&j_1,&j,&one,H,&ldh,h,&ione,&zero,work,&ione));
     112        2677 :     PetscCall(BVMultVec(V,-1.0,1.0,w,work));
     113             :   }
     114        2695 :   PetscCall(VecAXPY(w,-h[j],t));
     115             : 
     116             :   /* compute norm of v and w */
     117        2695 :   if (norm) {
     118        2566 :     PetscCall(VecNorm(v,NORM_2,&x));
     119        2566 :     PetscCall(VecNorm(w,NORM_2,&y));
     120        2566 :     *norm = SlepcAbs(x,y);
     121             :   }
     122        2695 :   PetscFunctionReturn(PETSC_SUCCESS);
     123             : }
     124             : 
     125             : /*
     126             :   Compute a run of Q-Arnoldi iterations
     127             : */
     128         118 : static PetscErrorCode PEPQArnoldi(PEP pep,Mat A,PetscInt k,PetscInt *M,Vec v,Vec w,PetscReal *beta,PetscBool *breakdown,PetscScalar *work)
     129             : {
     130         118 :   PetscInt           i,j,l,m = *M,ldh;
     131         118 :   PetscBLASInt       jj,ldhh;
     132         118 :   Vec                t = pep->work[2],u = pep->work[3];
     133         118 :   BVOrthogRefineType refinement;
     134         118 :   PetscReal          norm=0.0,onorm,eta;
     135         118 :   PetscScalar        *H,*c = work + m;
     136             : 
     137         118 :   PetscFunctionBegin;
     138         118 :   *beta = 0.0;
     139         118 :   PetscCall(MatDenseGetArray(A,&H));
     140         118 :   PetscCall(MatDenseGetLDA(A,&ldh));
     141         118 :   PetscCall(BVGetOrthogonalization(pep->V,NULL,&refinement,&eta,NULL));
     142         118 :   PetscCall(BVInsertVec(pep->V,k,v));
     143        1539 :   for (j=k;j<m;j++) {
     144             :     /* apply operator */
     145        1421 :     PetscCall(VecCopy(w,t));
     146        1421 :     if (pep->Dr) PetscCall(VecPointwiseMult(v,v,pep->Dr));
     147        1421 :     PetscCall(STMatMult(pep->st,0,v,u));
     148        1421 :     PetscCall(VecCopy(t,v));
     149        1421 :     if (pep->Dr) PetscCall(VecPointwiseMult(t,t,pep->Dr));
     150        1421 :     PetscCall(STMatMult(pep->st,1,t,w));
     151        1421 :     PetscCall(VecAXPY(u,pep->sfactor,w));
     152        1421 :     PetscCall(STMatSolve(pep->st,u,w));
     153        1421 :     PetscCall(VecScale(w,-1.0/(pep->sfactor*pep->sfactor)));
     154        1421 :     if (pep->Dr) PetscCall(VecPointwiseDivide(w,w,pep->Dr));
     155        1421 :     PetscCall(VecCopy(v,t));
     156        1421 :     PetscCall(BVSetActiveColumns(pep->V,0,j+1));
     157             : 
     158             :     /* orthogonalize */
     159        1421 :     PetscCall(PetscBLASIntCast(j,&jj));
     160        1421 :     PetscCall(PetscBLASIntCast(ldh,&ldhh));
     161        1421 :     switch (refinement) {
     162          59 :       case BV_ORTHOG_REFINE_NEVER:
     163          59 :         PetscCall(PEPQArnoldiCGS(pep,H,ldhh,H+ldh*j,jj,pep->V,t,v,w,NULL,&norm,work));
     164          59 :         *breakdown = PETSC_FALSE;
     165          59 :         break;
     166         129 :       case BV_ORTHOG_REFINE_ALWAYS:
     167         129 :         PetscCall(PEPQArnoldiCGS(pep,H,ldhh,H+ldh*j,jj,pep->V,t,v,w,NULL,NULL,work));
     168         129 :         PetscCall(PEPQArnoldiCGS(pep,H,ldhh,c,jj,pep->V,t,v,w,&onorm,&norm,work));
     169        2033 :         for (i=0;i<=j;i++) H[ldh*j+i] += c[i];
     170         129 :         if (norm < eta * onorm) *breakdown = PETSC_TRUE;
     171         129 :         else *breakdown = PETSC_FALSE;
     172             :         break;
     173        1233 :       case BV_ORTHOG_REFINE_IFNEEDED:
     174        1233 :         PetscCall(PEPQArnoldiCGS(pep,H,ldhh,H+ldh*j,jj,pep->V,t,v,w,&onorm,&norm,work));
     175             :         /* ||q|| < eta ||h|| */
     176             :         l = 1;
     177        2378 :         while (l<3 && norm < eta * onorm) {
     178        1145 :           l++;
     179        1145 :           onorm = norm;
     180        1145 :           PetscCall(PEPQArnoldiCGS(pep,H,ldhh,c,jj,pep->V,t,v,w,NULL,&norm,work));
     181       20803 :           for (i=0;i<=j;i++) H[ldh*j+i] += c[i];
     182             :         }
     183        1233 :         if (norm < eta * onorm) *breakdown = PETSC_TRUE;
     184        1233 :         else *breakdown = PETSC_FALSE;
     185             :         break;
     186             :     }
     187        1421 :     PetscCall(VecScale(v,1.0/norm));
     188        1421 :     PetscCall(VecScale(w,1.0/norm));
     189             : 
     190        1421 :     H[j+1+ldh*j] = norm;
     191        1421 :     if (j<m-1) PetscCall(BVInsertVec(pep->V,j+1,v));
     192             :   }
     193         118 :   *beta = norm;
     194         118 :   PetscCall(MatDenseRestoreArray(A,&H));
     195         118 :   PetscFunctionReturn(PETSC_SUCCESS);
     196             : }
     197             : 
     198          16 : static PetscErrorCode PEPSolve_QArnoldi(PEP pep)
     199             : {
     200          16 :   PEP_QARNOLDI   *ctx = (PEP_QARNOLDI*)pep->data;
     201          16 :   PetscInt       j,k,l,lwork,nv,nconv;
     202          16 :   Vec            v=pep->work[0],w=pep->work[1];
     203          16 :   Mat            Q,S;
     204          16 :   PetscScalar    *work;
     205          16 :   PetscReal      beta,norm,x,y;
     206          16 :   PetscBool      breakdown=PETSC_FALSE,sinv;
     207             : 
     208          16 :   PetscFunctionBegin;
     209          16 :   lwork = 7*pep->ncv;
     210          16 :   PetscCall(PetscMalloc1(lwork,&work));
     211          16 :   PetscCall(PetscObjectTypeCompare((PetscObject)pep->st,STSINVERT,&sinv));
     212          16 :   PetscCall(RGPushScale(pep->rg,sinv?pep->sfactor:1.0/pep->sfactor));
     213          16 :   PetscCall(STScaleShift(pep->st,sinv?pep->sfactor:1.0/pep->sfactor));
     214             : 
     215             :   /* Get the starting Arnoldi vector */
     216          48 :   for (j=0;j<2;j++) {
     217          32 :     if (j>=pep->nini) PetscCall(BVSetRandomColumn(pep->V,j));
     218             :   }
     219          16 :   PetscCall(BVCopyVec(pep->V,0,v));
     220          16 :   PetscCall(BVCopyVec(pep->V,1,w));
     221          16 :   PetscCall(VecNorm(v,NORM_2,&x));
     222          16 :   PetscCall(VecNorm(w,NORM_2,&y));
     223          16 :   norm = SlepcAbs(x,y);
     224          16 :   PetscCall(VecScale(v,1.0/norm));
     225          16 :   PetscCall(VecScale(w,1.0/norm));
     226             : 
     227             :   /* clean projected matrix (including the extra-arrow) */
     228          16 :   PetscCall(DSSetDimensions(pep->ds,PETSC_DETERMINE,PETSC_DETERMINE,PETSC_DETERMINE));
     229          16 :   PetscCall(DSGetMat(pep->ds,DS_MAT_A,&S));
     230          16 :   PetscCall(MatZeroEntries(S));
     231          16 :   PetscCall(DSRestoreMat(pep->ds,DS_MAT_A,&S));
     232             : 
     233             :    /* Restart loop */
     234          16 :   l = 0;
     235          16 :   while (pep->reason == PEP_CONVERGED_ITERATING) {
     236         118 :     pep->its++;
     237             : 
     238             :     /* Compute an nv-step Arnoldi factorization */
     239         118 :     nv = PetscMin(pep->nconv+pep->mpd,pep->ncv);
     240         118 :     PetscCall(DSGetMat(pep->ds,DS_MAT_A,&S));
     241         118 :     PetscCall(PEPQArnoldi(pep,S,pep->nconv+l,&nv,v,w,&beta,&breakdown,work));
     242         118 :     PetscCall(DSRestoreMat(pep->ds,DS_MAT_A,&S));
     243         118 :     PetscCall(DSSetDimensions(pep->ds,nv,pep->nconv,pep->nconv+l));
     244         118 :     PetscCall(DSSetState(pep->ds,l?DS_STATE_RAW:DS_STATE_INTERMEDIATE));
     245         118 :     PetscCall(BVSetActiveColumns(pep->V,pep->nconv,nv));
     246             : 
     247             :     /* Solve projected problem */
     248         118 :     PetscCall(DSSolve(pep->ds,pep->eigr,pep->eigi));
     249         118 :     PetscCall(DSSort(pep->ds,pep->eigr,pep->eigi,NULL,NULL,NULL));
     250         118 :     PetscCall(DSUpdateExtraRow(pep->ds));
     251         118 :     PetscCall(DSSynchronize(pep->ds,pep->eigr,pep->eigi));
     252             : 
     253             :     /* Check convergence */
     254         118 :     PetscCall(PEPKrylovConvergence(pep,PETSC_FALSE,pep->nconv,nv-pep->nconv,beta,&k));
     255         118 :     PetscCall((*pep->stopping)(pep,pep->its,pep->max_it,k,pep->nev,&pep->reason,pep->stoppingctx));
     256         118 :     nconv = k;
     257             : 
     258             :     /* Update l */
     259         118 :     if (pep->reason != PEP_CONVERGED_ITERATING || breakdown) l = 0;
     260             :     else {
     261         102 :       l = PetscMax(1,(PetscInt)((nv-k)*ctx->keep));
     262         102 :       PetscCall(DSGetTruncateSize(pep->ds,k,nv,&l));
     263             :     }
     264         118 :     if (!ctx->lock && l>0) { l += k; k = 0; } /* non-locking variant: reset no. of converged pairs */
     265         118 :     if (l) PetscCall(PetscInfo(pep,"Preparing to restart keeping l=%" PetscInt_FMT " vectors\n",l));
     266             : 
     267         118 :     if (pep->reason == PEP_CONVERGED_ITERATING) {
     268         102 :       if (PetscUnlikely(breakdown)) {
     269             :         /* Stop if breakdown */
     270           0 :         PetscCall(PetscInfo(pep,"Breakdown Quadratic Arnoldi method (it=%" PetscInt_FMT " norm=%g)\n",pep->its,(double)beta));
     271           0 :         pep->reason = PEP_DIVERGED_BREAKDOWN;
     272             :       } else {
     273             :         /* Prepare the Rayleigh quotient for restart */
     274         102 :         PetscCall(DSTruncate(pep->ds,k+l,PETSC_FALSE));
     275             :       }
     276             :     }
     277             :     /* Update the corresponding vectors V(:,idx) = V*Q(:,idx) */
     278         118 :     PetscCall(DSGetMat(pep->ds,DS_MAT_Q,&Q));
     279         118 :     PetscCall(BVMultInPlace(pep->V,Q,pep->nconv,k+l));
     280         118 :     PetscCall(DSRestoreMat(pep->ds,DS_MAT_Q,&Q));
     281             : 
     282         118 :     pep->nconv = k;
     283         134 :     PetscCall(PEPMonitor(pep,pep->its,nconv,pep->eigr,pep->eigi,pep->errest,nv));
     284             :   }
     285          16 :   PetscCall(BVSetActiveColumns(pep->V,0,pep->nconv));
     286         107 :   for (j=0;j<pep->nconv;j++) {
     287          91 :     pep->eigr[j] *= pep->sfactor;
     288          91 :     pep->eigi[j] *= pep->sfactor;
     289             :   }
     290             : 
     291          16 :   PetscCall(STScaleShift(pep->st,sinv?1.0/pep->sfactor:pep->sfactor));
     292          16 :   PetscCall(RGPopScale(pep->rg));
     293             : 
     294          16 :   PetscCall(DSTruncate(pep->ds,pep->nconv,PETSC_TRUE));
     295          16 :   PetscCall(PetscFree(work));
     296          16 :   PetscFunctionReturn(PETSC_SUCCESS);
     297             : }
     298             : 
     299           1 : static PetscErrorCode PEPQArnoldiSetRestart_QArnoldi(PEP pep,PetscReal keep)
     300             : {
     301           1 :   PEP_QARNOLDI *ctx = (PEP_QARNOLDI*)pep->data;
     302             : 
     303           1 :   PetscFunctionBegin;
     304           1 :   if (keep==(PetscReal)PETSC_DEFAULT || keep==(PetscReal)PETSC_DECIDE) ctx->keep = 0.5;
     305             :   else {
     306           1 :     PetscCheck(keep>=0.1 && keep<=0.9,PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_OUTOFRANGE,"The keep argument must be in the range [0.1,0.9]");
     307           1 :     ctx->keep = keep;
     308             :   }
     309           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     310             : }
     311             : 
     312             : /*@
     313             :    PEPQArnoldiSetRestart - Sets the restart parameter for the Q-Arnoldi
     314             :    method, in particular the proportion of basis vectors that must be kept
     315             :    after restart.
     316             : 
     317             :    Logically Collective
     318             : 
     319             :    Input Parameters:
     320             : +  pep  - the eigenproblem solver context
     321             : -  keep - the number of vectors to be kept at restart
     322             : 
     323             :    Options Database Key:
     324             : .  -pep_qarnoldi_restart - Sets the restart parameter
     325             : 
     326             :    Notes:
     327             :    Allowed values are in the range [0.1,0.9]. The default is 0.5.
     328             : 
     329             :    Level: advanced
     330             : 
     331             : .seealso: PEPQArnoldiGetRestart()
     332             : @*/
     333           1 : PetscErrorCode PEPQArnoldiSetRestart(PEP pep,PetscReal keep)
     334             : {
     335           1 :   PetscFunctionBegin;
     336           1 :   PetscValidHeaderSpecific(pep,PEP_CLASSID,1);
     337           3 :   PetscValidLogicalCollectiveReal(pep,keep,2);
     338           1 :   PetscTryMethod(pep,"PEPQArnoldiSetRestart_C",(PEP,PetscReal),(pep,keep));
     339           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     340             : }
     341             : 
     342           1 : static PetscErrorCode PEPQArnoldiGetRestart_QArnoldi(PEP pep,PetscReal *keep)
     343             : {
     344           1 :   PEP_QARNOLDI *ctx = (PEP_QARNOLDI*)pep->data;
     345             : 
     346           1 :   PetscFunctionBegin;
     347           1 :   *keep = ctx->keep;
     348           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     349             : }
     350             : 
     351             : /*@
     352             :    PEPQArnoldiGetRestart - Gets the restart parameter used in the Q-Arnoldi method.
     353             : 
     354             :    Not Collective
     355             : 
     356             :    Input Parameter:
     357             : .  pep - the eigenproblem solver context
     358             : 
     359             :    Output Parameter:
     360             : .  keep - the restart parameter
     361             : 
     362             :    Level: advanced
     363             : 
     364             : .seealso: PEPQArnoldiSetRestart()
     365             : @*/
     366           1 : PetscErrorCode PEPQArnoldiGetRestart(PEP pep,PetscReal *keep)
     367             : {
     368           1 :   PetscFunctionBegin;
     369           1 :   PetscValidHeaderSpecific(pep,PEP_CLASSID,1);
     370           1 :   PetscAssertPointer(keep,2);
     371           1 :   PetscUseMethod(pep,"PEPQArnoldiGetRestart_C",(PEP,PetscReal*),(pep,keep));
     372           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     373             : }
     374             : 
     375           1 : static PetscErrorCode PEPQArnoldiSetLocking_QArnoldi(PEP pep,PetscBool lock)
     376             : {
     377           1 :   PEP_QARNOLDI *ctx = (PEP_QARNOLDI*)pep->data;
     378             : 
     379           1 :   PetscFunctionBegin;
     380           1 :   ctx->lock = lock;
     381           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     382             : }
     383             : 
     384             : /*@
     385             :    PEPQArnoldiSetLocking - Choose between locking and non-locking variants of
     386             :    the Q-Arnoldi method.
     387             : 
     388             :    Logically Collective
     389             : 
     390             :    Input Parameters:
     391             : +  pep  - the eigenproblem solver context
     392             : -  lock - true if the locking variant must be selected
     393             : 
     394             :    Options Database Key:
     395             : .  -pep_qarnoldi_locking - Sets the locking flag
     396             : 
     397             :    Notes:
     398             :    The default is to lock converged eigenpairs when the method restarts.
     399             :    This behaviour can be changed so that all directions are kept in the
     400             :    working subspace even if already converged to working accuracy (the
     401             :    non-locking variant).
     402             : 
     403             :    Level: advanced
     404             : 
     405             : .seealso: PEPQArnoldiGetLocking()
     406             : @*/
     407           1 : PetscErrorCode PEPQArnoldiSetLocking(PEP pep,PetscBool lock)
     408             : {
     409           1 :   PetscFunctionBegin;
     410           1 :   PetscValidHeaderSpecific(pep,PEP_CLASSID,1);
     411           3 :   PetscValidLogicalCollectiveBool(pep,lock,2);
     412           1 :   PetscTryMethod(pep,"PEPQArnoldiSetLocking_C",(PEP,PetscBool),(pep,lock));
     413           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     414             : }
     415             : 
     416           1 : static PetscErrorCode PEPQArnoldiGetLocking_QArnoldi(PEP pep,PetscBool *lock)
     417             : {
     418           1 :   PEP_QARNOLDI *ctx = (PEP_QARNOLDI*)pep->data;
     419             : 
     420           1 :   PetscFunctionBegin;
     421           1 :   *lock = ctx->lock;
     422           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     423             : }
     424             : 
     425             : /*@
     426             :    PEPQArnoldiGetLocking - Gets the locking flag used in the Q-Arnoldi method.
     427             : 
     428             :    Not Collective
     429             : 
     430             :    Input Parameter:
     431             : .  pep - the eigenproblem solver context
     432             : 
     433             :    Output Parameter:
     434             : .  lock - the locking flag
     435             : 
     436             :    Level: advanced
     437             : 
     438             : .seealso: PEPQArnoldiSetLocking()
     439             : @*/
     440           1 : PetscErrorCode PEPQArnoldiGetLocking(PEP pep,PetscBool *lock)
     441             : {
     442           1 :   PetscFunctionBegin;
     443           1 :   PetscValidHeaderSpecific(pep,PEP_CLASSID,1);
     444           1 :   PetscAssertPointer(lock,2);
     445           1 :   PetscUseMethod(pep,"PEPQArnoldiGetLocking_C",(PEP,PetscBool*),(pep,lock));
     446           1 :   PetscFunctionReturn(PETSC_SUCCESS);
     447             : }
     448             : 
     449          14 : static PetscErrorCode PEPSetFromOptions_QArnoldi(PEP pep,PetscOptionItems *PetscOptionsObject)
     450             : {
     451          14 :   PetscBool      flg,lock;
     452          14 :   PetscReal      keep;
     453             : 
     454          14 :   PetscFunctionBegin;
     455          14 :   PetscOptionsHeadBegin(PetscOptionsObject,"PEP Q-Arnoldi Options");
     456             : 
     457          14 :     PetscCall(PetscOptionsReal("-pep_qarnoldi_restart","Proportion of vectors kept after restart","PEPQArnoldiSetRestart",0.5,&keep,&flg));
     458          14 :     if (flg) PetscCall(PEPQArnoldiSetRestart(pep,keep));
     459             : 
     460          14 :     PetscCall(PetscOptionsBool("-pep_qarnoldi_locking","Choose between locking and non-locking variants","PEPQArnoldiSetLocking",PETSC_FALSE,&lock,&flg));
     461          14 :     if (flg) PetscCall(PEPQArnoldiSetLocking(pep,lock));
     462             : 
     463          14 :   PetscOptionsHeadEnd();
     464          14 :   PetscFunctionReturn(PETSC_SUCCESS);
     465             : }
     466             : 
     467           0 : static PetscErrorCode PEPView_QArnoldi(PEP pep,PetscViewer viewer)
     468             : {
     469           0 :   PEP_QARNOLDI   *ctx = (PEP_QARNOLDI*)pep->data;
     470           0 :   PetscBool      isascii;
     471             : 
     472           0 :   PetscFunctionBegin;
     473           0 :   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
     474           0 :   if (isascii) {
     475           0 :     PetscCall(PetscViewerASCIIPrintf(viewer,"  %d%% of basis vectors kept after restart\n",(int)(100*ctx->keep)));
     476           0 :     PetscCall(PetscViewerASCIIPrintf(viewer,"  using the %slocking variant\n",ctx->lock?"":"non-"));
     477             :   }
     478           0 :   PetscFunctionReturn(PETSC_SUCCESS);
     479             : }
     480             : 
     481          15 : static PetscErrorCode PEPDestroy_QArnoldi(PEP pep)
     482             : {
     483          15 :   PetscFunctionBegin;
     484          15 :   PetscCall(PetscFree(pep->data));
     485          15 :   PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPQArnoldiSetRestart_C",NULL));
     486          15 :   PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPQArnoldiGetRestart_C",NULL));
     487          15 :   PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPQArnoldiSetLocking_C",NULL));
     488          15 :   PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPQArnoldiGetLocking_C",NULL));
     489          15 :   PetscFunctionReturn(PETSC_SUCCESS);
     490             : }
     491             : 
     492          15 : SLEPC_EXTERN PetscErrorCode PEPCreate_QArnoldi(PEP pep)
     493             : {
     494          15 :   PEP_QARNOLDI   *ctx;
     495             : 
     496          15 :   PetscFunctionBegin;
     497          15 :   PetscCall(PetscNew(&ctx));
     498          15 :   pep->data = (void*)ctx;
     499             : 
     500          15 :   pep->lineariz = PETSC_TRUE;
     501          15 :   ctx->lock     = PETSC_TRUE;
     502             : 
     503          15 :   pep->ops->solve          = PEPSolve_QArnoldi;
     504          15 :   pep->ops->setup          = PEPSetUp_QArnoldi;
     505          15 :   pep->ops->setfromoptions = PEPSetFromOptions_QArnoldi;
     506          15 :   pep->ops->destroy        = PEPDestroy_QArnoldi;
     507          15 :   pep->ops->view           = PEPView_QArnoldi;
     508          15 :   pep->ops->backtransform  = PEPBackTransform_Default;
     509          15 :   pep->ops->computevectors = PEPComputeVectors_Default;
     510          15 :   pep->ops->extractvectors = PEPExtractVectors_QArnoldi;
     511          15 :   pep->ops->setdefaultst   = PEPSetDefaultST_Transform;
     512             : 
     513          15 :   PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPQArnoldiSetRestart_C",PEPQArnoldiSetRestart_QArnoldi));
     514          15 :   PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPQArnoldiGetRestart_C",PEPQArnoldiGetRestart_QArnoldi));
     515          15 :   PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPQArnoldiSetLocking_C",PEPQArnoldiSetLocking_QArnoldi));
     516          15 :   PetscCall(PetscObjectComposeFunction((PetscObject)pep,"PEPQArnoldiGetLocking_C",PEPQArnoldiGetLocking_QArnoldi));
     517          15 :   PetscFunctionReturn(PETSC_SUCCESS);
     518             : }

Generated by: LCOV version 1.14