Date: 2024-12-02T08:56:57+00:00

Actual source code: epsview.c
slepc-3.22.2 2024-12-02
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:    EPS routines related to various viewers
     12: */

     14: #include <slepc/private/epsimpl.h>
     15: #include <slepc/private/bvimpl.h>
     16: #include <petscdraw.h>

     18: /*@
     19:    EPSView - Prints the EPS data structure.

     21:    Collective

     23:    Input Parameters:
     24: +  eps - the eigenproblem solver context
     25: -  viewer - optional visualization context

     27:    Options Database Key:
     28: .  -eps_view -  Calls EPSView() at end of EPSSolve()

     30:    Note:
     31:    The available visualization contexts include
     32: +     PETSC_VIEWER_STDOUT_SELF - standard output (default)
     33: -     PETSC_VIEWER_STDOUT_WORLD - synchronized standard
     34:          output where only the first processor opens
     35:          the file.  All other processors send their
     36:          data to the first processor to print.

     38:    The user can open an alternative visualization context with
     39:    PetscViewerASCIIOpen() - output to a specified file.

     41:    Level: beginner

     43: .seealso: STView()
     44: @*/
     45: PetscErrorCode EPSView(EPS eps,PetscViewer viewer)
     46: {
     47:   const char     *type=NULL,*extr=NULL,*bal=NULL;
     48:   char           str[50];
     49:   PetscBool      isascii,isexternal,istrivial,isstruct=PETSC_FALSE,flg;
     50:   Mat            A;

     52:   PetscFunctionBegin;
     54:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)eps),&viewer));
     56:   PetscCheckSameComm(eps,1,viewer,2);

     58:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
     59:   if (isascii) {
     60:     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)eps,viewer));
     61:     PetscCall(PetscViewerASCIIPushTab(viewer));
     62:     PetscTryTypeMethod(eps,view,viewer);
     63:     PetscCall(PetscViewerASCIIPopTab(viewer));
     64:     if (eps->problem_type) {
     65:       switch (eps->problem_type) {
     66:         case EPS_HEP:    type = SLEPC_STRING_HERMITIAN " eigenvalue problem"; break;
     67:         case EPS_GHEP:   type = "generalized " SLEPC_STRING_HERMITIAN " eigenvalue problem"; break;
     68:         case EPS_NHEP:   type = "non-" SLEPC_STRING_HERMITIAN " eigenvalue problem"; break;
     69:         case EPS_GNHEP:  type = "generalized non-" SLEPC_STRING_HERMITIAN " eigenvalue problem"; break;
     70:         case EPS_PGNHEP: type = "generalized non-" SLEPC_STRING_HERMITIAN " eigenvalue problem with " SLEPC_STRING_HERMITIAN " positive definite B"; break;
     71:         case EPS_GHIEP:  type = "generalized " SLEPC_STRING_HERMITIAN "-indefinite eigenvalue problem"; break;
     72:         case EPS_BSE:    type = "structured Bethe-Salpeter eigenvalue problem"; break;
     73:       }
     74:     } else type = "not yet set";
     75:     PetscCall(PetscViewerASCIIPrintf(viewer,"  problem type: %s\n",type));
     76:     PetscCall(EPSGetOperators(eps,&A,NULL));
     77:     if (A) PetscCall(SlepcCheckMatStruct(A,0,&isstruct));
     78:     if (isstruct) {
     79:       PetscCall(SlepcCheckMatStruct(A,SLEPC_MAT_STRUCT_BSE,&flg));
     80:       if (flg) PetscCall(PetscViewerASCIIPrintf(viewer,"  matrix A has a Bethe-Salpeter structure\n"));
     81:     }
     82:     if (eps->extraction) {
     83:       switch (eps->extraction) {
     84:         case EPS_RITZ:              extr = "Rayleigh-Ritz"; break;
     85:         case EPS_HARMONIC:          extr = "harmonic Ritz"; break;
     86:         case EPS_HARMONIC_RELATIVE: extr = "relative harmonic Ritz"; break;
     87:         case EPS_HARMONIC_RIGHT:    extr = "right harmonic Ritz"; break;
     88:         case EPS_HARMONIC_LARGEST:  extr = "largest harmonic Ritz"; break;
     89:         case EPS_REFINED:           extr = "refined Ritz"; break;
     90:         case EPS_REFINED_HARMONIC:  extr = "refined harmonic Ritz"; break;
     91:       }
     92:       PetscCall(PetscViewerASCIIPrintf(viewer,"  extraction type: %s\n",extr));
     93:     }
     94:     if (!eps->ishermitian && eps->balance!=EPS_BALANCE_NONE) {
     95:       switch (eps->balance) {
     96:         case EPS_BALANCE_NONE:    break;
     97:         case EPS_BALANCE_ONESIDE: bal = "one-sided Krylov"; break;
     98:         case EPS_BALANCE_TWOSIDE: bal = "two-sided Krylov"; break;
     99:         case EPS_BALANCE_USER:    bal = "user-defined matrix"; break;
    100:       }
    101:       PetscCall(PetscViewerASCIIPrintf(viewer,"  balancing enabled: %s",bal));
    102:       PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
    103:       if (eps->balance==EPS_BALANCE_ONESIDE || eps->balance==EPS_BALANCE_TWOSIDE) PetscCall(PetscViewerASCIIPrintf(viewer,", with its=%" PetscInt_FMT,eps->balance_its));
    104:       if (eps->balance==EPS_BALANCE_TWOSIDE && eps->balance_cutoff!=0.0) PetscCall(PetscViewerASCIIPrintf(viewer," and cutoff=%g",(double)eps->balance_cutoff));
    105:       PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
    106:       PetscCall(PetscViewerASCIIPrintf(viewer,"\n"));
    107:     }
    108:     PetscCall(PetscViewerASCIIPrintf(viewer,"  selected portion of the spectrum: "));
    109:     PetscCall(SlepcSNPrintfScalar(str,sizeof(str),eps->target,PETSC_FALSE));
    110:     PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
    111:     if (!eps->which) PetscCall(PetscViewerASCIIPrintf(viewer,"not yet set\n"));
    112:     else switch (eps->which) {
    113:       case EPS_WHICH_USER:
    114:         PetscCall(PetscViewerASCIIPrintf(viewer,"user defined\n"));
    115:         break;
    116:       case EPS_TARGET_MAGNITUDE:
    117:         PetscCall(PetscViewerASCIIPrintf(viewer,"closest to target: %s (in magnitude)\n",str));
    118:         break;
    119:       case EPS_TARGET_REAL:
    120:         PetscCall(PetscViewerASCIIPrintf(viewer,"closest to target: %s (along the real axis)\n",str));
    121:         break;
    122:       case EPS_TARGET_IMAGINARY:
    123:         PetscCall(PetscViewerASCIIPrintf(viewer,"closest to target: %s (along the imaginary axis)\n",str));
    124:         break;
    125:       case EPS_LARGEST_MAGNITUDE:
    126:         PetscCall(PetscViewerASCIIPrintf(viewer,"largest eigenvalues in magnitude\n"));
    127:         break;
    128:       case EPS_SMALLEST_MAGNITUDE:
    129:         PetscCall(PetscViewerASCIIPrintf(viewer,"smallest eigenvalues in magnitude\n"));
    130:         break;
    131:       case EPS_LARGEST_REAL:
    132:         PetscCall(PetscViewerASCIIPrintf(viewer,"largest real parts\n"));
    133:         break;
    134:       case EPS_SMALLEST_REAL:
    135:         PetscCall(PetscViewerASCIIPrintf(viewer,"smallest real parts\n"));
    136:         break;
    137:       case EPS_LARGEST_IMAGINARY:
    138:         PetscCall(PetscViewerASCIIPrintf(viewer,"largest imaginary parts\n"));
    139:         break;
    140:       case EPS_SMALLEST_IMAGINARY:
    141:         PetscCall(PetscViewerASCIIPrintf(viewer,"smallest imaginary parts\n"));
    142:         break;
    143:       case EPS_ALL:
    144:         if (eps->inta || eps->intb) PetscCall(PetscViewerASCIIPrintf(viewer,"all eigenvalues in interval [%g,%g]\n",(double)eps->inta,(double)eps->intb));
    145:         else PetscCall(PetscViewerASCIIPrintf(viewer,"all eigenvalues in the region\n"));
    146:         break;
    147:     }
    148:     PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
    149:     if (eps->twosided && eps->problem_type!=EPS_HEP && eps->problem_type!=EPS_GHEP) PetscCall(PetscViewerASCIIPrintf(viewer,"  using two-sided variant (for left eigenvectors)\n"));
    150:     if (eps->purify) PetscCall(PetscViewerASCIIPrintf(viewer,"  postprocessing eigenvectors with purification\n"));
    151:     if (eps->trueres) PetscCall(PetscViewerASCIIPrintf(viewer,"  computing true residuals explicitly\n"));
    152:     if (eps->trackall) PetscCall(PetscViewerASCIIPrintf(viewer,"  computing all residuals (for tracking convergence)\n"));
    153:     PetscCall(PetscViewerASCIIPrintf(viewer,"  number of eigenvalues (nev): %" PetscInt_FMT "\n",eps->nev));
    154:     PetscCall(PetscViewerASCIIPrintf(viewer,"  number of column vectors (ncv): %" PetscInt_FMT "\n",eps->ncv));
    155:     PetscCall(PetscViewerASCIIPrintf(viewer,"  maximum dimension of projected problem (mpd): %" PetscInt_FMT "\n",eps->mpd));
    156:     PetscCall(PetscViewerASCIIPrintf(viewer,"  maximum number of iterations: %" PetscInt_FMT "\n",eps->max_it));
    157:     PetscCall(PetscViewerASCIIPrintf(viewer,"  tolerance: %g\n",(double)eps->tol));
    158:     PetscCall(PetscViewerASCIIPrintf(viewer,"  convergence test: "));
    159:     PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
    160:     switch (eps->conv) {
    161:     case EPS_CONV_ABS:
    162:       PetscCall(PetscViewerASCIIPrintf(viewer,"absolute\n"));break;
    163:     case EPS_CONV_REL:
    164:       PetscCall(PetscViewerASCIIPrintf(viewer,"relative to the eigenvalue\n"));break;
    165:     case EPS_CONV_NORM:
    166:       PetscCall(PetscViewerASCIIPrintf(viewer,"relative to the eigenvalue and matrix norms\n"));
    167:       PetscCall(PetscViewerASCIIPrintf(viewer,"  computed matrix norms: norm(A)=%g",(double)eps->nrma));
    168:       if (eps->isgeneralized) PetscCall(PetscViewerASCIIPrintf(viewer,", norm(B)=%g",(double)eps->nrmb));
    169:       PetscCall(PetscViewerASCIIPrintf(viewer,"\n"));
    170:       break;
    171:     case EPS_CONV_USER:
    172:       PetscCall(PetscViewerASCIIPrintf(viewer,"user-defined\n"));break;
    173:     }
    174:     PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
    175:     if (eps->nini) PetscCall(PetscViewerASCIIPrintf(viewer,"  dimension of user-provided initial space: %" PetscInt_FMT "\n",PetscAbs(eps->nini)));
    176:     if (eps->ninil) PetscCall(PetscViewerASCIIPrintf(viewer,"  dimension of user-provided left initial space: %" PetscInt_FMT "\n",PetscAbs(eps->ninil)));
    177:     if (eps->nds) PetscCall(PetscViewerASCIIPrintf(viewer,"  dimension of user-provided deflation space: %" PetscInt_FMT "\n",PetscAbs(eps->nds)));
    178:   } else PetscTryTypeMethod(eps,view,viewer);
    179:   PetscCall(PetscObjectTypeCompareAny((PetscObject)eps,&isexternal,EPSARPACK,EPSBLOPEX,EPSELEMENTAL,EPSFEAST,EPSPRIMME,EPSSCALAPACK,EPSELPA,EPSEVSL,EPSTRLAN,""));
    180:   if (!isexternal) {
    181:     PetscCall(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO));
    182:     if (!eps->V) PetscCall(EPSGetBV(eps,&eps->V));
    183:     PetscCall(BVView(eps->V,viewer));
    184:     if (eps->rg) {
    185:       PetscCall(RGIsTrivial(eps->rg,&istrivial));
    186:       if (!istrivial) PetscCall(RGView(eps->rg,viewer));
    187:     }
    188:     if (eps->useds) {
    189:       if (!eps->ds) PetscCall(EPSGetDS(eps,&eps->ds));
    190:       PetscCall(DSView(eps->ds,viewer));
    191:     }
    192:     PetscCall(PetscViewerPopFormat(viewer));
    193:   }
    194:   if (!eps->st) PetscCall(EPSGetST(eps,&eps->st));
    195:   PetscCall(STView(eps->st,viewer));
    196:   PetscFunctionReturn(PETSC_SUCCESS);
    197: }

    199: /*@
    200:    EPSViewFromOptions - View from options

    202:    Collective

    204:    Input Parameters:
    205: +  eps  - the eigensolver context
    206: .  obj  - optional object
    207: -  name - command line option

    209:    Level: intermediate

    211: .seealso: EPSView(), EPSCreate()
    212: @*/
    213: PetscErrorCode EPSViewFromOptions(EPS eps,PetscObject obj,const char name[])
    214: {
    215:   PetscFunctionBegin;
    217:   PetscCall(PetscObjectViewFromOptions((PetscObject)eps,obj,name));
    218:   PetscFunctionReturn(PETSC_SUCCESS);
    219: }

    221: /*@
    222:    EPSConvergedReasonView - Displays the reason an EPS solve converged or diverged.

    224:    Collective

    226:    Input Parameters:
    227: +  eps - the eigensolver context
    228: -  viewer - the viewer to display the reason

    230:    Options Database Keys:
    231: .  -eps_converged_reason - print reason for convergence, and number of iterations

    233:    Note:
    234:    To change the format of the output call PetscViewerPushFormat(viewer,format) before
    235:    this call. Use PETSC_VIEWER_DEFAULT for the default, use PETSC_VIEWER_FAILED to only
    236:    display a reason if it fails. The latter can be set in the command line with
    237:    -eps_converged_reason ::failed

    239:    Level: intermediate

    241: .seealso: EPSSetConvergenceTest(), EPSSetTolerances(), EPSGetIterationNumber(), EPSConvergedReasonViewFromOptions()
    242: @*/
    243: PetscErrorCode EPSConvergedReasonView(EPS eps,PetscViewer viewer)
    244: {
    245:   PetscBool         isAscii;
    246:   PetscViewerFormat format;
    247:   PetscInt          nconv;

    249:   PetscFunctionBegin;
    250:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)eps));
    251:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isAscii));
    252:   if (isAscii) {
    253:     PetscCall(PetscViewerGetFormat(viewer,&format));
    254:     PetscCall(PetscViewerASCIIAddTab(viewer,((PetscObject)eps)->tablevel));
    255:     PetscCall(EPS_GetActualConverged(eps,&nconv));
    256:     if (eps->reason > 0 && format != PETSC_VIEWER_FAILED) PetscCall(PetscViewerASCIIPrintf(viewer,"%s Linear eigensolve converged (%" PetscInt_FMT " eigenpair%s) due to %s; iterations %" PetscInt_FMT "\n",((PetscObject)eps)->prefix?((PetscObject)eps)->prefix:"",nconv,(nconv>1)?"s":"",EPSConvergedReasons[eps->reason],eps->its));
    257:     else if (eps->reason <= 0) PetscCall(PetscViewerASCIIPrintf(viewer,"%s Linear eigensolve did not converge due to %s; iterations %" PetscInt_FMT "\n",((PetscObject)eps)->prefix?((PetscObject)eps)->prefix:"",EPSConvergedReasons[eps->reason],eps->its));
    258:     PetscCall(PetscViewerASCIISubtractTab(viewer,((PetscObject)eps)->tablevel));
    259:   }
    260:   PetscFunctionReturn(PETSC_SUCCESS);
    261: }

    263: /*@
    264:    EPSConvergedReasonViewFromOptions - Processes command line options to determine if/how
    265:    the EPS converged reason is to be viewed.

    267:    Collective

    269:    Input Parameter:
    270: .  eps - the eigensolver context

    272:    Level: developer

    274: .seealso: EPSConvergedReasonView()
    275: @*/
    276: PetscErrorCode EPSConvergedReasonViewFromOptions(EPS eps)
    277: {
    278:   PetscViewer       viewer;
    279:   PetscBool         flg;
    280:   static PetscBool  incall = PETSC_FALSE;
    281:   PetscViewerFormat format;

    283:   PetscFunctionBegin;
    284:   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
    285:   incall = PETSC_TRUE;
    286:   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)eps),((PetscObject)eps)->options,((PetscObject)eps)->prefix,"-eps_converged_reason",&viewer,&format,&flg));
    287:   if (flg) {
    288:     PetscCall(PetscViewerPushFormat(viewer,format));
    289:     PetscCall(EPSConvergedReasonView(eps,viewer));
    290:     PetscCall(PetscViewerPopFormat(viewer));
    291:     PetscCall(PetscViewerDestroy(&viewer));
    292:   }
    293:   incall = PETSC_FALSE;
    294:   PetscFunctionReturn(PETSC_SUCCESS);
    295: }

    297: static PetscErrorCode EPSErrorView_ASCII(EPS eps,EPSErrorType etype,PetscViewer viewer)
    298: {
    299:   PetscReal      error;
    300:   PetscScalar    kr,ki;
    301:   PetscInt       i,j,nvals,nconv;

    303:   PetscFunctionBegin;
    304:   PetscCall(EPS_GetActualConverged(eps,&nconv));
    305:   nvals = (eps->which==EPS_ALL)? eps->nconv: eps->nev;
    306:   if (eps->which!=EPS_ALL && nconv<nvals) {
    307:     PetscCall(PetscViewerASCIIPrintf(viewer," Problem: less than %" PetscInt_FMT " eigenvalues converged\n\n",eps->nev));
    308:     PetscFunctionReturn(PETSC_SUCCESS);
    309:   }
    310:   if (eps->which==EPS_ALL && !nvals) {
    311:     PetscCall(PetscViewerASCIIPrintf(viewer," No eigenvalues have been found\n\n"));
    312:     PetscFunctionReturn(PETSC_SUCCESS);
    313:   }
    314:   for (i=0;i<nvals;i++) {
    315:     PetscCall(EPSComputeError(eps,i,etype,&error));
    316:     if (error>=5.0*eps->tol) {
    317:       PetscCall(PetscViewerASCIIPrintf(viewer," Problem: some of the first %" PetscInt_FMT " relative errors are higher than the tolerance\n\n",nvals));
    318:       PetscFunctionReturn(PETSC_SUCCESS);
    319:     }
    320:   }
    321:   if (eps->which==EPS_ALL) PetscCall(PetscViewerASCIIPrintf(viewer," Found %" PetscInt_FMT " eigenvalues, all of them computed up to the required tolerance:",nvals));
    322:   else PetscCall(PetscViewerASCIIPrintf(viewer," All requested eigenvalues computed up to the required tolerance:"));
    323:   for (i=0;i<=(nvals-1)/8;i++) {
    324:     PetscCall(PetscViewerASCIIPrintf(viewer,"\n     "));
    325:     for (j=0;j<PetscMin(8,nvals-8*i);j++) {
    326:       PetscCall(EPSGetEigenvalue(eps,8*i+j,&kr,&ki));
    327:       PetscCall(SlepcPrintEigenvalueASCII(viewer,kr,ki));
    328:       if (8*i+j+1<nvals) PetscCall(PetscViewerASCIIPrintf(viewer,", "));
    329:     }
    330:   }
    331:   PetscCall(PetscViewerASCIIPrintf(viewer,"\n\n"));
    332:   PetscFunctionReturn(PETSC_SUCCESS);
    333: }

    335: static PetscErrorCode EPSErrorView_DETAIL(EPS eps,EPSErrorType etype,PetscViewer viewer)
    336: {
    337:   PetscReal      error,re,im;
    338:   PetscScalar    kr,ki;
    339:   PetscInt       i,nconv;
    340:   char           ex[30],sep[]=" ---------------------- --------------------\n";

    342:   PetscFunctionBegin;
    343:   if (!eps->nconv) PetscFunctionReturn(PETSC_SUCCESS);
    344:   switch (etype) {
    345:     case EPS_ERROR_ABSOLUTE:
    346:       PetscCall(PetscSNPrintf(ex,sizeof(ex),"   ||Ax-k%sx||",eps->isgeneralized?"B":""));
    347:       break;
    348:     case EPS_ERROR_RELATIVE:
    349:       PetscCall(PetscSNPrintf(ex,sizeof(ex),"||Ax-k%sx||/||kx||",eps->isgeneralized?"B":""));
    350:       break;
    351:     case EPS_ERROR_BACKWARD:
    352:       PetscCall(PetscSNPrintf(ex,sizeof(ex),"    eta(x,k)"));
    353:       break;
    354:   }
    355:   PetscCall(PetscViewerASCIIPrintf(viewer,"%s            k             %s\n%s",sep,ex,sep));
    356:   PetscCall(EPS_GetActualConverged(eps,&nconv));
    357:   for (i=0;i<nconv;i++) {
    358:     PetscCall(EPSGetEigenvalue(eps,i,&kr,&ki));
    359:     PetscCall(EPSComputeError(eps,i,etype,&error));
    360: #if defined(PETSC_USE_COMPLEX)
    361:     re = PetscRealPart(kr);
    362:     im = PetscImaginaryPart(kr);
    363: #else
    364:     re = kr;
    365:     im = ki;
    366: #endif
    367:     if (im!=0.0) PetscCall(PetscViewerASCIIPrintf(viewer,"  % 9f%+9fi      %12g\n",(double)re,(double)im,(double)error));
    368:     else PetscCall(PetscViewerASCIIPrintf(viewer,"    % 12f           %12g\n",(double)re,(double)error));
    369:   }
    370:   PetscCall(PetscViewerASCIIPrintf(viewer,"%s",sep));
    371:   PetscFunctionReturn(PETSC_SUCCESS);
    372: }

    374: static PetscErrorCode EPSErrorView_MATLAB(EPS eps,EPSErrorType etype,PetscViewer viewer)
    375: {
    376:   PetscReal      error;
    377:   PetscInt       i,nconv;
    378:   const char     *name;

    380:   PetscFunctionBegin;
    381:   PetscCall(PetscObjectGetName((PetscObject)eps,&name));
    382:   PetscCall(PetscViewerASCIIPrintf(viewer,"Error_%s = [\n",name));
    383:   PetscCall(EPS_GetActualConverged(eps,&nconv));
    384:   for (i=0;i<nconv;i++) {
    385:     PetscCall(EPSComputeError(eps,i,etype,&error));
    386:     PetscCall(PetscViewerASCIIPrintf(viewer,"%18.16e\n",(double)error));
    387:   }
    388:   PetscCall(PetscViewerASCIIPrintf(viewer,"];\n"));
    389:   PetscFunctionReturn(PETSC_SUCCESS);
    390: }

    392: /*@
    393:    EPSErrorView - Displays the errors associated with the computed solution
    394:    (as well as the eigenvalues).

    396:    Collective

    398:    Input Parameters:
    399: +  eps    - the eigensolver context
    400: .  etype  - error type
    401: -  viewer - optional visualization context

    403:    Options Database Keys:
    404: +  -eps_error_absolute - print absolute errors of each eigenpair
    405: .  -eps_error_relative - print relative errors of each eigenpair
    406: -  -eps_error_backward - print backward errors of each eigenpair

    408:    Notes:
    409:    By default, this function checks the error of all eigenpairs and prints
    410:    the eigenvalues if all of them are below the requested tolerance.
    411:    If the viewer has format=PETSC_VIEWER_ASCII_INFO_DETAIL then a table with
    412:    eigenvalues and corresponding errors is printed.

    414:    Level: intermediate

    416: .seealso: EPSSolve(), EPSValuesView(), EPSVectorsView()
    417: @*/
    418: PetscErrorCode EPSErrorView(EPS eps,EPSErrorType etype,PetscViewer viewer)
    419: {
    420:   PetscBool         isascii;
    421:   PetscViewerFormat format;

    423:   PetscFunctionBegin;
    425:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)eps),&viewer));
    427:   PetscCheckSameComm(eps,1,viewer,3);
    428:   EPSCheckSolved(eps,1);
    429:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
    430:   if (!isascii) PetscFunctionReturn(PETSC_SUCCESS);

    432:   PetscCall(PetscViewerGetFormat(viewer,&format));
    433:   switch (format) {
    434:     case PETSC_VIEWER_DEFAULT:
    435:     case PETSC_VIEWER_ASCII_INFO:
    436:       PetscCall(EPSErrorView_ASCII(eps,etype,viewer));
    437:       break;
    438:     case PETSC_VIEWER_ASCII_INFO_DETAIL:
    439:       PetscCall(EPSErrorView_DETAIL(eps,etype,viewer));
    440:       break;
    441:     case PETSC_VIEWER_ASCII_MATLAB:
    442:       PetscCall(EPSErrorView_MATLAB(eps,etype,viewer));
    443:       break;
    444:     default:
    445:       PetscCall(PetscInfo(eps,"Unsupported viewer format %s\n",PetscViewerFormats[format]));
    446:   }
    447:   PetscFunctionReturn(PETSC_SUCCESS);
    448: }

    450: /*@
    451:    EPSErrorViewFromOptions - Processes command line options to determine if/how
    452:    the errors of the computed solution are to be viewed.

    454:    Collective

    456:    Input Parameter:
    457: .  eps - the eigensolver context

    459:    Level: developer

    461: .seealso: EPSErrorView()
    462: @*/
    463: PetscErrorCode EPSErrorViewFromOptions(EPS eps)
    464: {
    465:   PetscViewer       viewer;
    466:   PetscBool         flg;
    467:   static PetscBool  incall = PETSC_FALSE;
    468:   PetscViewerFormat format;

    470:   PetscFunctionBegin;
    471:   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
    472:   incall = PETSC_TRUE;
    473:   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)eps),((PetscObject)eps)->options,((PetscObject)eps)->prefix,"-eps_error_absolute",&viewer,&format,&flg));
    474:   if (flg) {
    475:     PetscCall(PetscViewerPushFormat(viewer,format));
    476:     PetscCall(EPSErrorView(eps,EPS_ERROR_ABSOLUTE,viewer));
    477:     PetscCall(PetscViewerPopFormat(viewer));
    478:     PetscCall(PetscViewerDestroy(&viewer));
    479:   }
    480:   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)eps),((PetscObject)eps)->options,((PetscObject)eps)->prefix,"-eps_error_relative",&viewer,&format,&flg));
    481:   if (flg) {
    482:     PetscCall(PetscViewerPushFormat(viewer,format));
    483:     PetscCall(EPSErrorView(eps,EPS_ERROR_RELATIVE,viewer));
    484:     PetscCall(PetscViewerPopFormat(viewer));
    485:     PetscCall(PetscViewerDestroy(&viewer));
    486:   }
    487:   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)eps),((PetscObject)eps)->options,((PetscObject)eps)->prefix,"-eps_error_backward",&viewer,&format,&flg));
    488:   if (flg) {
    489:     PetscCall(PetscViewerPushFormat(viewer,format));
    490:     PetscCall(EPSErrorView(eps,EPS_ERROR_BACKWARD,viewer));
    491:     PetscCall(PetscViewerPopFormat(viewer));
    492:     PetscCall(PetscViewerDestroy(&viewer));
    493:   }
    494:   incall = PETSC_FALSE;
    495:   PetscFunctionReturn(PETSC_SUCCESS);
    496: }

    498: static PetscErrorCode EPSValuesView_DRAW(EPS eps,PetscViewer viewer)
    499: {
    500:   PetscDraw      draw;
    501:   PetscDrawSP    drawsp;
    502:   PetscReal      re,im;
    503:   PetscScalar    kr,ki;
    504:   PetscInt       i,nconv;

    506:   PetscFunctionBegin;
    507:   if (!eps->nconv) PetscFunctionReturn(PETSC_SUCCESS);
    508:   PetscCall(PetscViewerDrawGetDraw(viewer,0,&draw));
    509:   PetscCall(PetscDrawSetTitle(draw,"Computed Eigenvalues"));
    510:   PetscCall(PetscDrawSPCreate(draw,1,&drawsp));
    511:   PetscCall(EPS_GetActualConverged(eps,&nconv));
    512:   for (i=0;i<nconv;i++) {
    513:     PetscCall(EPSGetEigenvalue(eps,i,&kr,&ki));
    514: #if defined(PETSC_USE_COMPLEX)
    515:     re = PetscRealPart(kr);
    516:     im = PetscImaginaryPart(kr);
    517: #else
    518:     re = kr;
    519:     im = ki;
    520: #endif
    521:     PetscCall(PetscDrawSPAddPoint(drawsp,&re,&im));
    522:   }
    523:   PetscCall(PetscDrawSPDraw(drawsp,PETSC_TRUE));
    524:   PetscCall(PetscDrawSPSave(drawsp));
    525:   PetscCall(PetscDrawSPDestroy(&drawsp));
    526:   PetscFunctionReturn(PETSC_SUCCESS);
    527: }

    529: static PetscErrorCode EPSValuesView_BINARY(EPS eps,PetscViewer viewer)
    530: {
    531:   PetscScalar    kr,ki;
    532: #if defined(PETSC_HAVE_COMPLEX)
    533:   PetscInt       i,nconv;
    534:   PetscComplex   *ev;
    535: #endif

    537:   PetscFunctionBegin;
    538: #if defined(PETSC_HAVE_COMPLEX)
    539:   PetscCall(EPS_GetActualConverged(eps,&nconv));
    540:   PetscCall(PetscMalloc1(nconv,&ev));
    541:   for (i=0;i<nconv;i++) {
    542:     PetscCall(EPSGetEigenvalue(eps,i,&kr,&ki));
    543: #if defined(PETSC_USE_COMPLEX)
    544:     ev[i] = kr;
    545: #else
    546:     ev[i] = PetscCMPLX(kr,ki);
    547: #endif
    548:   }
    549:   PetscCall(PetscViewerBinaryWrite(viewer,ev,nconv,PETSC_COMPLEX));
    550:   PetscCall(PetscFree(ev));
    551: #endif
    552:   PetscFunctionReturn(PETSC_SUCCESS);
    553: }

    555: #if defined(PETSC_HAVE_HDF5)
    556: static PetscErrorCode EPSValuesView_HDF5(EPS eps,PetscViewer viewer)
    557: {
    558:   PetscInt       i,n,N,nconv;
    559:   PetscScalar    eig;
    560:   PetscMPIInt    rank;
    561:   Vec            v;
    562:   char           vname[30];
    563:   const char     *ename;

    565:   PetscFunctionBegin;
    566:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)eps),&rank));
    567:   PetscCall(EPS_GetActualConverged(eps,&nconv));
    568:   N = nconv;
    569:   n = rank? 0: N;
    570:   /* create a vector containing the eigenvalues */
    571:   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)eps),n,N,&v));
    572:   PetscCall(PetscObjectGetName((PetscObject)eps,&ename));
    573:   PetscCall(PetscSNPrintf(vname,sizeof(vname),"eigr_%s",ename));
    574:   PetscCall(PetscObjectSetName((PetscObject)v,vname));
    575:   if (!rank) {
    576:     for (i=0;i<nconv;i++) {
    577:       PetscCall(EPSGetEigenvalue(eps,i,&eig,NULL));
    578:       PetscCall(VecSetValue(v,i,eig,INSERT_VALUES));
    579:     }
    580:   }
    581:   PetscCall(VecAssemblyBegin(v));
    582:   PetscCall(VecAssemblyEnd(v));
    583:   PetscCall(VecView(v,viewer));
    584: #if !defined(PETSC_USE_COMPLEX)
    585:   /* in real scalars write the imaginary part as a separate vector */
    586:   PetscCall(PetscSNPrintf(vname,sizeof(vname),"eigi_%s",ename));
    587:   PetscCall(PetscObjectSetName((PetscObject)v,vname));
    588:   if (!rank) {
    589:     for (i=0;i<nconv;i++) {
    590:       PetscCall(EPSGetEigenvalue(eps,i,NULL,&eig));
    591:       PetscCall(VecSetValue(v,i,eig,INSERT_VALUES));
    592:     }
    593:   }
    594:   PetscCall(VecAssemblyBegin(v));
    595:   PetscCall(VecAssemblyEnd(v));
    596:   PetscCall(VecView(v,viewer));
    597: #endif
    598:   PetscCall(VecDestroy(&v));
    599:   PetscFunctionReturn(PETSC_SUCCESS);
    600: }
    601: #endif

    603: static PetscErrorCode EPSValuesView_ASCII(EPS eps,PetscViewer viewer)
    604: {
    605:   PetscInt       i,nconv;
    606:   PetscScalar    kr,ki;

    608:   PetscFunctionBegin;
    609:   PetscCall(PetscViewerASCIIPrintf(viewer,"Eigenvalues = \n"));
    610:   PetscCall(EPS_GetActualConverged(eps,&nconv));
    611:   for (i=0;i<nconv;i++) {
    612:     PetscCall(EPSGetEigenvalue(eps,i,&kr,&ki));
    613:     PetscCall(PetscViewerASCIIPrintf(viewer,"   "));
    614:     PetscCall(SlepcPrintEigenvalueASCII(viewer,kr,ki));
    615:     PetscCall(PetscViewerASCIIPrintf(viewer,"\n"));
    616:   }
    617:   PetscCall(PetscViewerASCIIPrintf(viewer,"\n"));
    618:   PetscFunctionReturn(PETSC_SUCCESS);
    619: }

    621: static PetscErrorCode EPSValuesView_MATLAB(EPS eps,PetscViewer viewer)
    622: {
    623:   PetscInt       i,nconv;
    624:   PetscReal      re,im;
    625:   PetscScalar    kr,ki;
    626:   const char     *name;

    628:   PetscFunctionBegin;
    629:   PetscCall(PetscObjectGetName((PetscObject)eps,&name));
    630:   PetscCall(PetscViewerASCIIPrintf(viewer,"Lambda_%s = [\n",name));
    631:   PetscCall(EPS_GetActualConverged(eps,&nconv));
    632:   for (i=0;i<nconv;i++) {
    633:     PetscCall(EPSGetEigenvalue(eps,i,&kr,&ki));
    634: #if defined(PETSC_USE_COMPLEX)
    635:     re = PetscRealPart(kr);
    636:     im = PetscImaginaryPart(kr);
    637: #else
    638:     re = kr;
    639:     im = ki;
    640: #endif
    641:     if (im!=0.0) PetscCall(PetscViewerASCIIPrintf(viewer,"%18.16e%+18.16ei\n",(double)re,(double)im));
    642:     else PetscCall(PetscViewerASCIIPrintf(viewer,"%18.16e\n",(double)re));
    643:   }
    644:   PetscCall(PetscViewerASCIIPrintf(viewer,"];\n"));
    645:   PetscFunctionReturn(PETSC_SUCCESS);
    646: }

    648: /*@
    649:    EPSValuesView - Displays the computed eigenvalues in a viewer.

    651:    Collective

    653:    Input Parameters:
    654: +  eps    - the eigensolver context
    655: -  viewer - the viewer

    657:    Options Database Key:
    658: .  -eps_view_values - print computed eigenvalues

    660:    Level: intermediate

    662: .seealso: EPSSolve(), EPSVectorsView(), EPSErrorView()
    663: @*/
    664: PetscErrorCode EPSValuesView(EPS eps,PetscViewer viewer)
    665: {
    666:   PetscBool         isascii,isdraw,isbinary;
    667:   PetscViewerFormat format;
    668: #if defined(PETSC_HAVE_HDF5)
    669:   PetscBool         ishdf5;
    670: #endif

    672:   PetscFunctionBegin;
    674:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)eps),&viewer));
    676:   PetscCheckSameComm(eps,1,viewer,2);
    677:   EPSCheckSolved(eps,1);
    678:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw));
    679:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary));
    680: #if defined(PETSC_HAVE_HDF5)
    681:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5));
    682: #endif
    683:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
    684:   if (isdraw) PetscCall(EPSValuesView_DRAW(eps,viewer));
    685:   else if (isbinary) PetscCall(EPSValuesView_BINARY(eps,viewer));
    686: #if defined(PETSC_HAVE_HDF5)
    687:   else if (ishdf5) PetscCall(EPSValuesView_HDF5(eps,viewer));
    688: #endif
    689:   else if (isascii) {
    690:     PetscCall(PetscViewerGetFormat(viewer,&format));
    691:     switch (format) {
    692:       case PETSC_VIEWER_DEFAULT:
    693:       case PETSC_VIEWER_ASCII_INFO:
    694:       case PETSC_VIEWER_ASCII_INFO_DETAIL:
    695:         PetscCall(EPSValuesView_ASCII(eps,viewer));
    696:         break;
    697:       case PETSC_VIEWER_ASCII_MATLAB:
    698:         PetscCall(EPSValuesView_MATLAB(eps,viewer));
    699:         break;
    700:       default:
    701:         PetscCall(PetscInfo(eps,"Unsupported viewer format %s\n",PetscViewerFormats[format]));
    702:     }
    703:   }
    704:   PetscFunctionReturn(PETSC_SUCCESS);
    705: }

    707: /*@
    708:    EPSValuesViewFromOptions - Processes command line options to determine if/how
    709:    the computed eigenvalues are to be viewed.

    711:    Collective

    713:    Input Parameters:
    714: .  eps - the eigensolver context

    716:    Level: developer

    718: .seealso: EPSValuesView()
    719: @*/
    720: PetscErrorCode EPSValuesViewFromOptions(EPS eps)
    721: {
    722:   PetscViewer       viewer;
    723:   PetscBool         flg;
    724:   static PetscBool  incall = PETSC_FALSE;
    725:   PetscViewerFormat format;

    727:   PetscFunctionBegin;
    728:   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
    729:   incall = PETSC_TRUE;
    730:   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)eps),((PetscObject)eps)->options,((PetscObject)eps)->prefix,"-eps_view_values",&viewer,&format,&flg));
    731:   if (flg) {
    732:     PetscCall(PetscViewerPushFormat(viewer,format));
    733:     PetscCall(EPSValuesView(eps,viewer));
    734:     PetscCall(PetscViewerPopFormat(viewer));
    735:     PetscCall(PetscViewerDestroy(&viewer));
    736:   }
    737:   incall = PETSC_FALSE;
    738:   PetscFunctionReturn(PETSC_SUCCESS);
    739: }

    741: /*@
    742:    EPSVectorsView - Outputs computed eigenvectors to a viewer.

    744:    Collective

    746:    Input Parameters:
    747: +  eps    - the eigensolver context
    748: -  viewer - the viewer

    750:    Options Database Key:
    751: .  -eps_view_vectors - output eigenvectors.

    753:    Notes:
    754:    If PETSc was configured with real scalars, complex conjugate eigenvectors
    755:    will be viewed as two separate real vectors, one containing the real part
    756:    and another one containing the imaginary part.

    758:    If left eigenvectors were computed with a two-sided eigensolver, the right
    759:    and left eigenvectors are interleaved, that is, the vectors are output in
    760:    the following order X0, Y0, X1, Y1, X2, Y2, ...

    762:    Level: intermediate

    764: .seealso: EPSSolve(), EPSValuesView(), EPSErrorView()
    765: @*/
    766: PetscErrorCode EPSVectorsView(EPS eps,PetscViewer viewer)
    767: {
    768:   PetscInt       i,nconv;
    769:   Vec            xr,xi=NULL;

    771:   PetscFunctionBegin;
    773:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)eps),&viewer));
    775:   PetscCheckSameComm(eps,1,viewer,2);
    776:   EPSCheckSolved(eps,1);
    777:   PetscCall(EPS_GetActualConverged(eps,&nconv));
    778:   if (nconv) {
    779:     PetscCall(BVCreateVec(eps->V,&xr));
    780: #if !defined(PETSC_USE_COMPLEX)
    781:     PetscCall(BVCreateVec(eps->V,&xi));
    782: #endif
    783:     for (i=0;i<nconv;i++) {
    784:       PetscCall(EPSGetEigenvector(eps,i,xr,xi));
    785:       PetscCall(SlepcViewEigenvector(viewer,xr,xi,"X",i,(PetscObject)eps));
    786:       if (eps->twosided || eps->problem_type==EPS_BSE) {
    787:         PetscCall(EPSGetLeftEigenvector(eps,i,xr,xi));
    788:         PetscCall(SlepcViewEigenvector(viewer,xr,xi,"Y",i,(PetscObject)eps));
    789:       }
    790:     }
    791:     PetscCall(VecDestroy(&xr));
    792: #if !defined(PETSC_USE_COMPLEX)
    793:     PetscCall(VecDestroy(&xi));
    794: #endif
    795:   }
    796:   PetscFunctionReturn(PETSC_SUCCESS);
    797: }

    799: /*@
    800:    EPSVectorsViewFromOptions - Processes command line options to determine if/how
    801:    the computed eigenvectors are to be viewed.

    803:    Collective

    805:    Input Parameter:
    806: .  eps - the eigensolver context

    808:    Level: developer

    810: .seealso: EPSVectorsView()
    811: @*/
    812: PetscErrorCode EPSVectorsViewFromOptions(EPS eps)
    813: {
    814:   PetscViewer       viewer;
    815:   PetscBool         flg = PETSC_FALSE;
    816:   static PetscBool  incall = PETSC_FALSE;
    817:   PetscViewerFormat format;

    819:   PetscFunctionBegin;
    820:   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
    821:   incall = PETSC_TRUE;
    822:   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)eps),((PetscObject)eps)->options,((PetscObject)eps)->prefix,"-eps_view_vectors",&viewer,&format,&flg));
    823:   if (flg) {
    824:     PetscCall(PetscViewerPushFormat(viewer,format));
    825:     PetscCall(EPSVectorsView(eps,viewer));
    826:     PetscCall(PetscViewerPopFormat(viewer));
    827:     PetscCall(PetscViewerDestroy(&viewer));
    828:   }
    829:   incall = PETSC_FALSE;
    830:   PetscFunctionReturn(PETSC_SUCCESS);
    831: }