LCOV - code coverage report
Current view: top level - pep/interface - pepsolve.c (source / functions) Hit Total Coverage
Test: SLEPc Lines: 182 188 96.8 %
Date: 2024-11-21 00:34:55 Functions: 10 10 100.0 %
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             :    PEP routines related to the solution process
      12             : 
      13             :    References:
      14             : 
      15             :        [1] C. Campos and J.E. Roman, "Parallel iterative refinement in
      16             :            polynomial eigenvalue problems", Numer. Linear Algebra Appl.
      17             :            23(4):730-745, 2016.
      18             : */
      19             : 
      20             : #include <slepc/private/pepimpl.h>       /*I "slepcpep.h" I*/
      21             : #include <slepc/private/bvimpl.h>
      22             : #include <petscdraw.h>
      23             : 
      24             : static PetscBool  cited = PETSC_FALSE;
      25             : static const char citation[] =
      26             :   "@Article{slepc-pep-refine,\n"
      27             :   "   author = \"C. Campos and J. E. Roman\",\n"
      28             :   "   title = \"Parallel iterative refinement in polynomial eigenvalue problems\",\n"
      29             :   "   journal = \"Numer. Linear Algebra Appl.\",\n"
      30             :   "   volume = \"23\",\n"
      31             :   "   number = \"4\",\n"
      32             :   "   pages = \"730--745\",\n"
      33             :   "   year = \"2016,\"\n"
      34             :   "   doi = \"https://doi.org/10.1002/nla.2052\"\n"
      35             :   "}\n";
      36             : 
      37        1554 : PetscErrorCode PEPComputeVectors(PEP pep)
      38             : {
      39        1554 :   PetscFunctionBegin;
      40        1554 :   PEPCheckSolved(pep,1);
      41        1554 :   if (pep->state==PEP_STATE_SOLVED) PetscTryTypeMethod(pep,computevectors);
      42        1554 :   pep->state = PEP_STATE_EIGENVECTORS;
      43        1554 :   PetscFunctionReturn(PETSC_SUCCESS);
      44             : }
      45             : 
      46         160 : PetscErrorCode PEPExtractVectors(PEP pep)
      47             : {
      48         160 :   PetscFunctionBegin;
      49         160 :   PEPCheckSolved(pep,1);
      50         160 :   if (pep->state==PEP_STATE_SOLVED) PetscTryTypeMethod(pep,extractvectors);
      51         160 :   PetscFunctionReturn(PETSC_SUCCESS);
      52             : }
      53             : 
      54             : /*@
      55             :    PEPSolve - Solves the polynomial eigensystem.
      56             : 
      57             :    Collective
      58             : 
      59             :    Input Parameter:
      60             : .  pep - eigensolver context obtained from PEPCreate()
      61             : 
      62             :    Options Database Keys:
      63             : +  -pep_view - print information about the solver used
      64             : .  -pep_view_matk - view the coefficient matrix Ak (replace k by an integer from 0 to nmat-1)
      65             : .  -pep_view_vectors - view the computed eigenvectors
      66             : .  -pep_view_values - view the computed eigenvalues
      67             : .  -pep_converged_reason - print reason for convergence, and number of iterations
      68             : .  -pep_error_absolute - print absolute errors of each eigenpair
      69             : .  -pep_error_relative - print relative errors of each eigenpair
      70             : -  -pep_error_backward - print backward errors of each eigenpair
      71             : 
      72             :    Notes:
      73             :    All the command-line options listed above admit an optional argument specifying
      74             :    the viewer type and options. For instance, use '-pep_view_mat0 binary:amatrix.bin'
      75             :    to save the A matrix to a binary file, '-pep_view_values draw' to draw the computed
      76             :    eigenvalues graphically, or '-pep_error_relative :myerr.m:ascii_matlab' to save
      77             :    the errors in a file that can be executed in Matlab.
      78             : 
      79             :    Level: beginner
      80             : 
      81             : .seealso: PEPCreate(), PEPSetUp(), PEPDestroy(), PEPSetTolerances()
      82             : @*/
      83         173 : PetscErrorCode PEPSolve(PEP pep)
      84             : {
      85         173 :   PetscInt       i,k;
      86         173 :   PetscBool      flg,islinear;
      87         173 :   char           str[16];
      88             : 
      89         173 :   PetscFunctionBegin;
      90         173 :   PetscValidHeaderSpecific(pep,PEP_CLASSID,1);
      91         173 :   if (pep->state>=PEP_STATE_SOLVED) PetscFunctionReturn(PETSC_SUCCESS);
      92         173 :   PetscCall(PetscLogEventBegin(PEP_Solve,pep,0,0,0));
      93             : 
      94             :   /* call setup */
      95         173 :   PetscCall(PEPSetUp(pep));
      96         173 :   pep->nconv = 0;
      97         173 :   pep->its   = 0;
      98         173 :   k = pep->lineariz? pep->ncv: pep->ncv*(pep->nmat-1);
      99        3939 :   for (i=0;i<k;i++) {
     100        3766 :     pep->eigr[i]   = 0.0;
     101        3766 :     pep->eigi[i]   = 0.0;
     102        3766 :     pep->errest[i] = 0.0;
     103        3766 :     pep->perm[i]   = i;
     104             :   }
     105         173 :   PetscCall(PEPViewFromOptions(pep,NULL,"-pep_view_pre"));
     106         173 :   PetscCall(RGViewFromOptions(pep->rg,NULL,"-rg_view"));
     107             : 
     108             :   /* Call solver */
     109         173 :   PetscUseTypeMethod(pep,solve);
     110         173 :   PetscCheck(pep->reason,PetscObjectComm((PetscObject)pep),PETSC_ERR_PLIB,"Internal error, solver returned without setting converged reason");
     111         173 :   pep->state = PEP_STATE_SOLVED;
     112             : 
     113             :   /* Only the first nconv columns contain useful information */
     114         173 :   PetscCall(BVSetActiveColumns(pep->V,0,pep->nconv));
     115             : 
     116         173 :   PetscCall(PetscObjectTypeCompare((PetscObject)pep,PEPLINEAR,&islinear));
     117         173 :   if (!islinear) {
     118         139 :     PetscCall(STPostSolve(pep->st));
     119             :     /* Map eigenvalues back to the original problem */
     120         139 :     PetscCall(STGetTransform(pep->st,&flg));
     121         139 :     if (flg) PetscTryTypeMethod(pep,backtransform);
     122             :   }
     123             : 
     124             : #if !defined(PETSC_USE_COMPLEX)
     125             :   /* reorder conjugate eigenvalues (positive imaginary first) */
     126        1035 :   for (i=0;i<pep->nconv-1;i++) {
     127         862 :     if (pep->eigi[i] != 0) {
     128         116 :       if (pep->eigi[i] < 0) {
     129          35 :         pep->eigi[i] = -pep->eigi[i];
     130          35 :         pep->eigi[i+1] = -pep->eigi[i+1];
     131             :         /* the next correction only works with eigenvectors */
     132          35 :         PetscCall(PEPComputeVectors(pep));
     133          35 :         PetscCall(BVScaleColumn(pep->V,i+1,-1.0));
     134             :       }
     135         116 :       i++;
     136             :     }
     137             :   }
     138             : #endif
     139             : 
     140         173 :   if (pep->refine!=PEP_REFINE_NONE) PetscCall(PetscCitationsRegister(citation,&cited));
     141             : 
     142         173 :   if (pep->refine==PEP_REFINE_SIMPLE && pep->rits>0 && pep->nconv>0) {
     143          15 :     PetscCall(PEPComputeVectors(pep));
     144          15 :     PetscCall(PEPNewtonRefinementSimple(pep,&pep->rits,pep->rtol,pep->nconv));
     145             :   }
     146             : 
     147             :   /* sort eigenvalues according to pep->which parameter */
     148         173 :   PetscCall(SlepcSortEigenvalues(pep->sc,pep->nconv,pep->eigr,pep->eigi,pep->perm));
     149         173 :   PetscCall(PetscLogEventEnd(PEP_Solve,pep,0,0,0));
     150             : 
     151             :   /* various viewers */
     152         173 :   PetscCall(PEPViewFromOptions(pep,NULL,"-pep_view"));
     153         173 :   PetscCall(PEPConvergedReasonViewFromOptions(pep));
     154         173 :   PetscCall(PEPErrorViewFromOptions(pep));
     155         173 :   PetscCall(PEPValuesViewFromOptions(pep));
     156         173 :   PetscCall(PEPVectorsViewFromOptions(pep));
     157         831 :   for (i=0;i<pep->nmat;i++) {
     158         658 :     PetscCall(PetscSNPrintf(str,sizeof(str),"-pep_view_mat%" PetscInt_FMT,i));
     159         658 :     PetscCall(MatViewFromOptions(pep->A[i],(PetscObject)pep,str));
     160             :   }
     161             : 
     162             :   /* Remove the initial subspace */
     163         173 :   pep->nini = 0;
     164         173 :   PetscFunctionReturn(PETSC_SUCCESS);
     165             : }
     166             : 
     167             : /*@
     168             :    PEPGetIterationNumber - Gets the current iteration number. If the
     169             :    call to PEPSolve() is complete, then it returns the number of iterations
     170             :    carried out by the solution method.
     171             : 
     172             :    Not Collective
     173             : 
     174             :    Input Parameter:
     175             : .  pep - the polynomial eigensolver context
     176             : 
     177             :    Output Parameter:
     178             : .  its - number of iterations
     179             : 
     180             :    Note:
     181             :    During the i-th iteration this call returns i-1. If PEPSolve() is
     182             :    complete, then parameter "its" contains either the iteration number at
     183             :    which convergence was successfully reached, or failure was detected.
     184             :    Call PEPGetConvergedReason() to determine if the solver converged or
     185             :    failed and why.
     186             : 
     187             :    Level: intermediate
     188             : 
     189             : .seealso: PEPGetConvergedReason(), PEPSetTolerances()
     190             : @*/
     191          30 : PetscErrorCode PEPGetIterationNumber(PEP pep,PetscInt *its)
     192             : {
     193          30 :   PetscFunctionBegin;
     194          30 :   PetscValidHeaderSpecific(pep,PEP_CLASSID,1);
     195          30 :   PetscAssertPointer(its,2);
     196          30 :   *its = pep->its;
     197          30 :   PetscFunctionReturn(PETSC_SUCCESS);
     198             : }
     199             : 
     200             : /*@
     201             :    PEPGetConverged - Gets the number of converged eigenpairs.
     202             : 
     203             :    Not Collective
     204             : 
     205             :    Input Parameter:
     206             : .  pep - the polynomial eigensolver context
     207             : 
     208             :    Output Parameter:
     209             : .  nconv - number of converged eigenpairs
     210             : 
     211             :    Note:
     212             :    This function should be called after PEPSolve() has finished.
     213             : 
     214             :    Level: beginner
     215             : 
     216             : .seealso: PEPSetDimensions(), PEPSolve(), PEPGetEigenpair()
     217             : @*/
     218          85 : PetscErrorCode PEPGetConverged(PEP pep,PetscInt *nconv)
     219             : {
     220          85 :   PetscFunctionBegin;
     221          85 :   PetscValidHeaderSpecific(pep,PEP_CLASSID,1);
     222          85 :   PetscAssertPointer(nconv,2);
     223          85 :   PEPCheckSolved(pep,1);
     224          85 :   *nconv = pep->nconv;
     225          85 :   PetscFunctionReturn(PETSC_SUCCESS);
     226             : }
     227             : 
     228             : /*@
     229             :    PEPGetConvergedReason - Gets the reason why the PEPSolve() iteration was
     230             :    stopped.
     231             : 
     232             :    Not Collective
     233             : 
     234             :    Input Parameter:
     235             : .  pep - the polynomial eigensolver context
     236             : 
     237             :    Output Parameter:
     238             : .  reason - negative value indicates diverged, positive value converged
     239             : 
     240             :    Options Database Key:
     241             : .  -pep_converged_reason - print the reason to a viewer
     242             : 
     243             :    Notes:
     244             :    Possible values for reason are
     245             : +  PEP_CONVERGED_TOL - converged up to tolerance
     246             : .  PEP_CONVERGED_USER - converged due to a user-defined condition
     247             : .  PEP_DIVERGED_ITS - required more than max_it iterations to reach convergence
     248             : .  PEP_DIVERGED_BREAKDOWN - generic breakdown in method
     249             : -  PEP_DIVERGED_SYMMETRY_LOST - pseudo-Lanczos was not able to keep symmetry
     250             : 
     251             :    Can only be called after the call to PEPSolve() is complete.
     252             : 
     253             :    Level: intermediate
     254             : 
     255             : .seealso: PEPSetTolerances(), PEPSolve(), PEPConvergedReason
     256             : @*/
     257          24 : PetscErrorCode PEPGetConvergedReason(PEP pep,PEPConvergedReason *reason)
     258             : {
     259          24 :   PetscFunctionBegin;
     260          24 :   PetscValidHeaderSpecific(pep,PEP_CLASSID,1);
     261          24 :   PetscAssertPointer(reason,2);
     262          24 :   PEPCheckSolved(pep,1);
     263          24 :   *reason = pep->reason;
     264          24 :   PetscFunctionReturn(PETSC_SUCCESS);
     265             : }
     266             : 
     267             : /*@
     268             :    PEPGetEigenpair - Gets the i-th solution of the eigenproblem as computed by
     269             :    PEPSolve(). The solution consists in both the eigenvalue and the eigenvector.
     270             : 
     271             :    Collective
     272             : 
     273             :    Input Parameters:
     274             : +  pep - polynomial eigensolver context
     275             : -  i   - index of the solution
     276             : 
     277             :    Output Parameters:
     278             : +  eigr - real part of eigenvalue
     279             : .  eigi - imaginary part of eigenvalue
     280             : .  Vr   - real part of eigenvector
     281             : -  Vi   - imaginary part of eigenvector
     282             : 
     283             :    Notes:
     284             :    It is allowed to pass NULL for Vr and Vi, if the eigenvector is not
     285             :    required. Otherwise, the caller must provide valid Vec objects, i.e.,
     286             :    they must be created by the calling program with e.g. MatCreateVecs().
     287             : 
     288             :    If the eigenvalue is real, then eigi and Vi are set to zero. If PETSc is
     289             :    configured with complex scalars the eigenvalue is stored
     290             :    directly in eigr (eigi is set to zero) and the eigenvector in Vr (Vi is
     291             :    set to zero). In any case, the user can pass NULL in Vr or Vi if one of
     292             :    them is not required.
     293             : 
     294             :    The index i should be a value between 0 and nconv-1 (see PEPGetConverged()).
     295             :    Eigenpairs are indexed according to the ordering criterion established
     296             :    with PEPSetWhichEigenpairs().
     297             : 
     298             :    Level: beginner
     299             : 
     300             : .seealso: PEPSolve(), PEPGetConverged(), PEPSetWhichEigenpairs()
     301             : @*/
     302        1503 : PetscErrorCode PEPGetEigenpair(PEP pep,PetscInt i,PetscScalar *eigr,PetscScalar *eigi,Vec Vr,Vec Vi)
     303             : {
     304        1503 :   PetscInt       k;
     305             : 
     306        1503 :   PetscFunctionBegin;
     307        1503 :   PetscValidHeaderSpecific(pep,PEP_CLASSID,1);
     308        4509 :   PetscValidLogicalCollectiveInt(pep,i,2);
     309        1503 :   if (Vr) { PetscValidHeaderSpecific(Vr,VEC_CLASSID,5); PetscCheckSameComm(pep,1,Vr,5); }
     310        1503 :   if (Vi) { PetscValidHeaderSpecific(Vi,VEC_CLASSID,6); PetscCheckSameComm(pep,1,Vi,6); }
     311        1503 :   PEPCheckSolved(pep,1);
     312        1503 :   PetscCheck(i>=0,PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_OUTOFRANGE,"The index cannot be negative");
     313        1503 :   PetscCheck(i<pep->nconv,PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_OUTOFRANGE,"The index can be nconv-1 at most, see PEPGetConverged()");
     314             : 
     315        1503 :   PetscCall(PEPComputeVectors(pep));
     316        1503 :   k = pep->perm[i];
     317             : 
     318             :   /* eigenvalue */
     319             : #if defined(PETSC_USE_COMPLEX)
     320             :   if (eigr) *eigr = pep->eigr[k];
     321             :   if (eigi) *eigi = 0;
     322             : #else
     323        1503 :   if (eigr) *eigr = pep->eigr[k];
     324        1503 :   if (eigi) *eigi = pep->eigi[k];
     325             : #endif
     326             : 
     327             :   /* eigenvector */
     328        1503 :   PetscCall(BV_GetEigenvector(pep->V,k,pep->eigi[k],Vr,Vi));
     329        1503 :   PetscFunctionReturn(PETSC_SUCCESS);
     330             : }
     331             : 
     332             : /*@
     333             :    PEPGetErrorEstimate - Returns the error estimate associated to the i-th
     334             :    computed eigenpair.
     335             : 
     336             :    Not Collective
     337             : 
     338             :    Input Parameters:
     339             : +  pep - polynomial eigensolver context
     340             : -  i   - index of eigenpair
     341             : 
     342             :    Output Parameter:
     343             : .  errest - the error estimate
     344             : 
     345             :    Notes:
     346             :    This is the error estimate used internally by the eigensolver. The actual
     347             :    error bound can be computed with PEPComputeError(). See also the users
     348             :    manual for details.
     349             : 
     350             :    Level: advanced
     351             : 
     352             : .seealso: PEPComputeError()
     353             : @*/
     354           4 : PetscErrorCode PEPGetErrorEstimate(PEP pep,PetscInt i,PetscReal *errest)
     355             : {
     356           4 :   PetscFunctionBegin;
     357           4 :   PetscValidHeaderSpecific(pep,PEP_CLASSID,1);
     358           4 :   PetscAssertPointer(errest,3);
     359           4 :   PEPCheckSolved(pep,1);
     360           4 :   PetscCheck(i>=0,PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_OUTOFRANGE,"The index cannot be negative");
     361           4 :   PetscCheck(i<pep->nconv,PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_OUTOFRANGE,"The index can be nconv-1 at most, see PEPGetConverged()");
     362           4 :   *errest = pep->errest[pep->perm[i]];
     363           4 :   PetscFunctionReturn(PETSC_SUCCESS);
     364             : }
     365             : 
     366             : /*
     367             :    PEPComputeResidualNorm_Private - Computes the norm of the residual vector
     368             :    associated with an eigenpair.
     369             : 
     370             :    Input Parameters:
     371             :      kr,ki - eigenvalue
     372             :      xr,xi - eigenvector
     373             :      z     - array of 4 work vectors (z[2],z[3] not referenced in complex scalars)
     374             : */
     375        1027 : PetscErrorCode PEPComputeResidualNorm_Private(PEP pep,PetscScalar kr,PetscScalar ki,Vec xr,Vec xi,Vec *z,PetscReal *norm)
     376             : {
     377        1027 :   Mat            *A=pep->A;
     378        1027 :   PetscInt       i,nmat=pep->nmat;
     379        1027 :   PetscScalar    t[20],*vals=t,*ivals=NULL;
     380        1027 :   Vec            u,w;
     381             : #if !defined(PETSC_USE_COMPLEX)
     382        1027 :   Vec            ui,wi;
     383        1027 :   PetscReal      ni;
     384        1027 :   PetscBool      imag;
     385        1027 :   PetscScalar    it[20];
     386             : #endif
     387             : 
     388        1027 :   PetscFunctionBegin;
     389        1027 :   u = z[0]; w = z[1];
     390        1027 :   PetscCall(VecSet(u,0.0));
     391             : #if !defined(PETSC_USE_COMPLEX)
     392        1027 :   ui = z[2]; wi = z[3];
     393        1027 :   ivals = it;
     394             : #endif
     395        1027 :   if (nmat>20) {
     396           0 :     PetscCall(PetscMalloc1(nmat,&vals));
     397             : #if !defined(PETSC_USE_COMPLEX)
     398           0 :     PetscCall(PetscMalloc1(nmat,&ivals));
     399             : #endif
     400             :   }
     401        1027 :   PetscCall(PEPEvaluateBasis(pep,kr,ki,vals,ivals));
     402             : #if !defined(PETSC_USE_COMPLEX)
     403        1027 :   if (ki == 0 || PetscAbsScalar(ki) < PetscAbsScalar(kr*PETSC_MACHINE_EPSILON))
     404             :     imag = PETSC_FALSE;
     405             :   else {
     406         201 :     imag = PETSC_TRUE;
     407         201 :     PetscCall(VecSet(ui,0.0));
     408             :   }
     409             : #endif
     410        4173 :   for (i=0;i<nmat;i++) {
     411        3146 :     if (vals[i]!=0.0) {
     412        3146 :       PetscCall(MatMult(A[i],xr,w));
     413        3146 :       PetscCall(VecAXPY(u,vals[i],w));
     414             :     }
     415             : #if !defined(PETSC_USE_COMPLEX)
     416        3146 :     if (imag) {
     417         659 :       if (ivals[i]!=0 || vals[i]!=0) {
     418         659 :         PetscCall(MatMult(A[i],xi,wi));
     419         659 :         if (vals[i]==0) PetscCall(MatMult(A[i],xr,w));
     420             :       }
     421         659 :       if (ivals[i]!=0) {
     422         458 :         PetscCall(VecAXPY(u,-ivals[i],wi));
     423         458 :         PetscCall(VecAXPY(ui,ivals[i],w));
     424             :       }
     425        3146 :       if (vals[i]!=0) PetscCall(VecAXPY(ui,vals[i],wi));
     426             :     }
     427             : #endif
     428             :   }
     429        1027 :   PetscCall(VecNorm(u,NORM_2,norm));
     430             : #if !defined(PETSC_USE_COMPLEX)
     431        1027 :   if (imag) {
     432         201 :     PetscCall(VecNorm(ui,NORM_2,&ni));
     433         201 :     *norm = SlepcAbsEigenvalue(*norm,ni);
     434             :   }
     435             : #endif
     436        1027 :   if (nmat>20) {
     437           0 :     PetscCall(PetscFree(vals));
     438             : #if !defined(PETSC_USE_COMPLEX)
     439           0 :     PetscCall(PetscFree(ivals));
     440             : #endif
     441             :   }
     442        1027 :   PetscFunctionReturn(PETSC_SUCCESS);
     443             : }
     444             : 
     445             : /*@
     446             :    PEPComputeError - Computes the error (based on the residual norm) associated
     447             :    with the i-th computed eigenpair.
     448             : 
     449             :    Collective
     450             : 
     451             :    Input Parameters:
     452             : +  pep  - the polynomial eigensolver context
     453             : .  i    - the solution index
     454             : -  type - the type of error to compute
     455             : 
     456             :    Output Parameter:
     457             : .  error - the error
     458             : 
     459             :    Notes:
     460             :    The error can be computed in various ways, all of them based on the residual
     461             :    norm ||P(l)x||_2 where l is the eigenvalue and x is the eigenvector.
     462             :    See the users guide for additional details.
     463             : 
     464             :    Level: beginner
     465             : 
     466             : .seealso: PEPErrorType, PEPSolve(), PEPGetErrorEstimate()
     467             : @*/
     468         952 : PetscErrorCode PEPComputeError(PEP pep,PetscInt i,PEPErrorType type,PetscReal *error)
     469             : {
     470         952 :   Vec            xr,xi,w[4];
     471         952 :   PetscScalar    kr,ki;
     472         952 :   PetscReal      t,z=0.0;
     473         952 :   PetscInt       j;
     474         952 :   PetscBool      flg;
     475             : 
     476         952 :   PetscFunctionBegin;
     477         952 :   PetscValidHeaderSpecific(pep,PEP_CLASSID,1);
     478        2856 :   PetscValidLogicalCollectiveInt(pep,i,2);
     479        2856 :   PetscValidLogicalCollectiveEnum(pep,type,3);
     480         952 :   PetscAssertPointer(error,4);
     481         952 :   PEPCheckSolved(pep,1);
     482             : 
     483             :   /* allocate work vectors */
     484             : #if defined(PETSC_USE_COMPLEX)
     485             :   PetscCall(PEPSetWorkVecs(pep,3));
     486             :   xi   = NULL;
     487             :   w[2] = NULL;
     488             :   w[3] = NULL;
     489             : #else
     490         952 :   PetscCall(PEPSetWorkVecs(pep,6));
     491         952 :   xi   = pep->work[3];
     492         952 :   w[2] = pep->work[4];
     493         952 :   w[3] = pep->work[5];
     494             : #endif
     495         952 :   xr   = pep->work[0];
     496         952 :   w[0] = pep->work[1];
     497         952 :   w[1] = pep->work[2];
     498             : 
     499             :   /* compute residual norms */
     500         952 :   PetscCall(PEPGetEigenpair(pep,i,&kr,&ki,xr,xi));
     501         952 :   PetscCall(PEPComputeResidualNorm_Private(pep,kr,ki,xr,xi,w,error));
     502             : 
     503             :   /* compute error */
     504         952 :   switch (type) {
     505             :     case PEP_ERROR_ABSOLUTE:
     506             :       break;
     507          34 :     case PEP_ERROR_RELATIVE:
     508          34 :       *error /= SlepcAbsEigenvalue(kr,ki);
     509          34 :       break;
     510         906 :     case PEP_ERROR_BACKWARD:
     511             :       /* initialization of matrix norms */
     512         906 :       if (!pep->nrma[pep->nmat-1]) {
     513         554 :         for (j=0;j<pep->nmat;j++) {
     514         419 :           PetscCall(MatHasOperation(pep->A[j],MATOP_NORM,&flg));
     515         419 :           PetscCheck(flg,PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_WRONG,"The computation of backward errors requires a matrix norm operation");
     516         419 :           PetscCall(MatNorm(pep->A[j],NORM_INFINITY,&pep->nrma[j]));
     517             :         }
     518             :       }
     519         906 :       t = SlepcAbsEigenvalue(kr,ki);
     520        3680 :       for (j=pep->nmat-1;j>=0;j--) {
     521        2774 :         z = z*t+pep->nrma[j];
     522             :       }
     523         906 :       *error /= z;
     524         906 :       break;
     525           0 :     default:
     526           0 :       SETERRQ(PetscObjectComm((PetscObject)pep),PETSC_ERR_ARG_OUTOFRANGE,"Invalid error type");
     527             :   }
     528         952 :   PetscFunctionReturn(PETSC_SUCCESS);
     529             : }

Generated by: LCOV version 1.14