Date: 2026-05-01T10:02:03+00:00

Actual source code: pepview.c

      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:    The PEP routines related to various viewers
     12: */

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

     18: /*@
     19:    PEPView - Prints the `PEP` data structure.

     21:    Collective

     23:    Input Parameters:
     24: +  pep - the polynomial eigensolver context
     25: -  viewer - optional visualization context

     27:    Options Database Key:
     28: .  -pep_view - calls `PEPView()` at end of `PEPSolve()`

     30:    Notes:
     31:    The available visualization contexts include
     32: +     `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
     33: -     `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard output where only the
     34:          first process opens the file; all other processes send their data to the
     35:          first one to print

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

     40:    Level: beginner

     42: .seealso: [](ch:pep), `PEPCreate()`, `PEPViewFromOptions()`, `STView()`
     43: @*/
     44: PetscErrorCode PEPView(PEP pep,PetscViewer viewer)
     45: {
     46:   const char     *type=NULL;
     47:   char           str[50];
     48:   PetscBool      isascii,islinear,istrivial;
     49:   PetscInt       i;
     50:   PetscViewer    sviewer;
     51:   MPI_Comm       child;

     53:   PetscFunctionBegin;
     55:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pep),&viewer));
     57:   PetscCheckSameComm(pep,1,viewer,2);

     59:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
     60:   if (isascii) {
     61:     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)pep,viewer));
     62:     PetscCall(PetscViewerASCIIPushTab(viewer));
     63:     PetscTryTypeMethod(pep,view,viewer);
     64:     PetscCall(PetscViewerASCIIPopTab(viewer));
     65:     if (pep->problem_type) {
     66:       switch (pep->problem_type) {
     67:         case PEP_GENERAL:    type = "general polynomial eigenvalue problem"; break;
     68:         case PEP_HERMITIAN:  type = SLEPC_STRING_HERMITIAN " polynomial eigenvalue problem"; break;
     69:         case PEP_HYPERBOLIC: type = "hyperbolic polynomial eigenvalue problem"; break;
     70:         case PEP_GYROSCOPIC: type = "gyroscopic polynomial eigenvalue problem"; break;
     71:       }
     72:     } else type = "not yet set";
     73:     PetscCall(PetscViewerASCIIPrintf(viewer,"  problem type: %s\n",type));
     74:     PetscCall(PetscViewerASCIIPrintf(viewer,"  polynomial represented in %s basis\n",PEPBasisTypes[pep->basis]));
     75:     switch (pep->scale) {
     76:       case PEP_SCALE_NONE:
     77:         break;
     78:       case PEP_SCALE_SCALAR:
     79:         PetscCall(PetscViewerASCIIPrintf(viewer,"  parameter scaling enabled, with scaling factor=%g\n",(double)pep->sfactor));
     80:         break;
     81:       case PEP_SCALE_DIAGONAL:
     82:         PetscCall(PetscViewerASCIIPrintf(viewer,"  diagonal balancing enabled, with its=%" PetscInt_FMT " and lambda=%g\n",pep->sits,(double)pep->slambda));
     83:         break;
     84:       case PEP_SCALE_BOTH:
     85:         PetscCall(PetscViewerASCIIPrintf(viewer,"  parameter scaling & diagonal balancing enabled, with scaling factor=%g, its=%" PetscInt_FMT " and lambda=%g\n",(double)pep->sfactor,pep->sits,(double)pep->slambda));
     86:         break;
     87:     }
     88:     PetscCall(PetscViewerASCIIPrintf(viewer,"  selected portion of the spectrum: "));
     89:     PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
     90:     PetscCall(SlepcSNPrintfScalar(str,sizeof(str),pep->target,PETSC_FALSE));
     91:     if (!pep->which) PetscCall(PetscViewerASCIIPrintf(viewer,"not yet set\n"));
     92:     else switch (pep->which) {
     93:       case PEP_WHICH_USER:
     94:         PetscCall(PetscViewerASCIIPrintf(viewer,"user defined\n"));
     95:         break;
     96:       case PEP_TARGET_MAGNITUDE:
     97:         PetscCall(PetscViewerASCIIPrintf(viewer,"closest to target: %s (in magnitude)\n",str));
     98:         break;
     99:       case PEP_TARGET_REAL:
    100:         PetscCall(PetscViewerASCIIPrintf(viewer,"closest to target: %s (along the real axis)\n",str));
    101:         break;
    102:       case PEP_TARGET_IMAGINARY:
    103:         PetscCall(PetscViewerASCIIPrintf(viewer,"closest to target: %s (along the imaginary axis)\n",str));
    104:         break;
    105:       case PEP_LARGEST_MAGNITUDE:
    106:         PetscCall(PetscViewerASCIIPrintf(viewer,"largest eigenvalues in magnitude\n"));
    107:         break;
    108:       case PEP_SMALLEST_MAGNITUDE:
    109:         PetscCall(PetscViewerASCIIPrintf(viewer,"smallest eigenvalues in magnitude\n"));
    110:         break;
    111:       case PEP_LARGEST_REAL:
    112:         PetscCall(PetscViewerASCIIPrintf(viewer,"largest real parts\n"));
    113:         break;
    114:       case PEP_SMALLEST_REAL:
    115:         PetscCall(PetscViewerASCIIPrintf(viewer,"smallest real parts\n"));
    116:         break;
    117:       case PEP_LARGEST_IMAGINARY:
    118:         PetscCall(PetscViewerASCIIPrintf(viewer,"largest imaginary parts\n"));
    119:         break;
    120:       case PEP_SMALLEST_IMAGINARY:
    121:         PetscCall(PetscViewerASCIIPrintf(viewer,"smallest imaginary parts\n"));
    122:         break;
    123:       case PEP_ALL:
    124:         if (pep->inta || pep->intb) PetscCall(PetscViewerASCIIPrintf(viewer,"all eigenvalues in interval [%g,%g]\n",(double)pep->inta,(double)pep->intb));
    125:         else PetscCall(PetscViewerASCIIPrintf(viewer,"all eigenvalues in the region\n"));
    126:         break;
    127:     }
    128:     PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
    129:     PetscCall(PetscViewerASCIIPrintf(viewer,"  number of eigenvalues (nev): %" PetscInt_FMT "\n",pep->nev));
    130:     PetscCall(PetscViewerASCIIPrintf(viewer,"  number of column vectors (ncv): %" PetscInt_FMT "\n",pep->ncv));
    131:     PetscCall(PetscViewerASCIIPrintf(viewer,"  maximum dimension of projected problem (mpd): %" PetscInt_FMT "\n",pep->mpd));
    132:     PetscCall(PetscViewerASCIIPrintf(viewer,"  maximum number of iterations: %" PetscInt_FMT "\n",pep->max_it));
    133:     PetscCall(PetscViewerASCIIPrintf(viewer,"  tolerance: %g\n",(double)pep->tol));
    134:     PetscCall(PetscViewerASCIIPrintf(viewer,"  convergence test: "));
    135:     PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_FALSE));
    136:     switch (pep->conv) {
    137:     case PEP_CONV_ABS:
    138:       PetscCall(PetscViewerASCIIPrintf(viewer,"absolute\n"));break;
    139:     case PEP_CONV_REL:
    140:       PetscCall(PetscViewerASCIIPrintf(viewer,"relative to the eigenvalue\n"));break;
    141:     case PEP_CONV_NORM:
    142:       PetscCall(PetscViewerASCIIPrintf(viewer,"relative to the matrix norms\n"));
    143:       if (pep->nrma) {
    144:         PetscCall(PetscViewerASCIIPrintf(viewer,"  computed matrix norms: %g",(double)pep->nrma[0]));
    145:         for (i=1;i<pep->nmat;i++) PetscCall(PetscViewerASCIIPrintf(viewer,", %g",(double)pep->nrma[i]));
    146:         PetscCall(PetscViewerASCIIPrintf(viewer,"\n"));
    147:       }
    148:       break;
    149:     case PEP_CONV_USER:
    150:       PetscCall(PetscViewerASCIIPrintf(viewer,"user-defined\n"));break;
    151:     }
    152:     PetscCall(PetscViewerASCIIUseTabs(viewer,PETSC_TRUE));
    153:     PetscCall(PetscViewerASCIIPrintf(viewer,"  extraction type: %s\n",PEPExtractTypes[pep->extract]));
    154:     if (pep->refine) {
    155:       PetscCall(PetscViewerASCIIPrintf(viewer,"  iterative refinement: %s, with %s scheme\n",PEPRefineTypes[pep->refine],PEPRefineSchemes[pep->scheme]));
    156:       PetscCall(PetscViewerASCIIPrintf(viewer,"  refinement stopping criterion: tol=%g, its=%" PetscInt_FMT "\n",(double)pep->rtol,pep->rits));
    157:       if (pep->npart>1) PetscCall(PetscViewerASCIIPrintf(viewer,"  splitting communicator in %" PetscInt_FMT " partitions for refinement\n",pep->npart));
    158:     }
    159:     if (pep->nini) PetscCall(PetscViewerASCIIPrintf(viewer,"  dimension of user-provided initial space: %" PetscInt_FMT "\n",PetscAbs(pep->nini)));
    160:   } else PetscTryTypeMethod(pep,view,viewer);
    161:   PetscCall(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO));
    162:   if (!pep->V) PetscCall(PEPGetBV(pep,&pep->V));
    163:   PetscCall(BVView(pep->V,viewer));
    164:   if (!pep->rg) PetscCall(PEPGetRG(pep,&pep->rg));
    165:   PetscCall(RGIsTrivial(pep->rg,&istrivial));
    166:   if (!istrivial) PetscCall(RGView(pep->rg,viewer));
    167:   PetscCall(PetscObjectTypeCompare((PetscObject)pep,PEPLINEAR,&islinear));
    168:   if (!islinear) {
    169:     if (!pep->ds) PetscCall(PEPGetDS(pep,&pep->ds));
    170:     PetscCall(DSView(pep->ds,viewer));
    171:   }
    172:   PetscCall(PetscViewerPopFormat(viewer));
    173:   if (!pep->st) PetscCall(PEPGetST(pep,&pep->st));
    174:   PetscCall(STView(pep->st,viewer));
    175:   if (pep->refine!=PEP_REFINE_NONE) {
    176:     PetscCall(PetscViewerASCIIPushTab(viewer));
    177:     if (pep->npart>1) {
    178:       if (pep->refinesubc->color==0) {
    179:         PetscCall(PetscSubcommGetChild(pep->refinesubc,&child));
    180:         PetscCall(PetscViewerASCIIGetStdout(child,&sviewer));
    181:         PetscCall(KSPView(pep->refineksp,sviewer));
    182:       }
    183:     } else PetscCall(KSPView(pep->refineksp,viewer));
    184:     PetscCall(PetscViewerASCIIPopTab(viewer));
    185:   }
    186:   PetscFunctionReturn(PETSC_SUCCESS);
    187: }

    189: /*@
    190:    PEPViewFromOptions - View (print) a `PEP` object based on values in the options database.

    192:    Collective

    194:    Input Parameters:
    195: +  pep  - the polynomial eigensolver context
    196: .  obj  - optional object that provides the options prefix used to query the options database
    197: -  name - command line option

    199:    Level: intermediate

    201: .seealso: [](ch:pep), `PEPView()`, `PEPCreate()`, `PetscObjectViewFromOptions()`
    202: @*/
    203: PetscErrorCode PEPViewFromOptions(PEP pep,PetscObject obj,const char name[])
    204: {
    205:   PetscFunctionBegin;
    207:   PetscCall(PetscObjectViewFromOptions((PetscObject)pep,obj,name));
    208:   PetscFunctionReturn(PETSC_SUCCESS);
    209: }

    211: /*@
    212:    PEPConvergedReasonView - Displays the reason a `PEP` solve converged or diverged.

    214:    Collective

    216:    Input Parameters:
    217: +  pep - the polynomial eigensolver context
    218: -  viewer - the viewer to display the reason

    220:    Options Database Key:
    221: .  -pep_converged_reason - print reason for convergence/divergence, and number of iterations

    223:    Notes:
    224:    Use `PEPConvergedReasonViewFromOptions()` to display the reason based on values
    225:    in the options database.

    227:    To change the format of the output call `PetscViewerPushFormat()` before this
    228:    call. Use `PETSC_VIEWER_DEFAULT` for the default, or `PETSC_VIEWER_FAILED` to only
    229:    display a reason if it fails. The latter can be set in the command line with
    230:    `-pep_converged_reason ::failed`.

    232:    Level: intermediate

    234: .seealso: [](ch:pep), `PEPSetConvergenceTest()`, `PEPSetTolerances()`, `PEPGetIterationNumber()`, `PEPConvergedReasonViewFromOptions()`
    235: @*/
    236: PetscErrorCode PEPConvergedReasonView(PEP pep,PetscViewer viewer)
    237: {
    238:   PetscBool         isAscii;
    239:   PetscViewerFormat format;

    241:   PetscFunctionBegin;
    242:   if (!viewer) viewer = PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)pep));
    243:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isAscii));
    244:   if (isAscii) {
    245:     PetscCall(PetscViewerGetFormat(viewer,&format));
    246:     PetscCall(PetscViewerASCIIAddTab(viewer,((PetscObject)pep)->tablevel));
    247:     if (pep->reason > 0 && format != PETSC_VIEWER_FAILED) PetscCall(PetscViewerASCIIPrintf(viewer,"%s Polynomial eigensolve converged (%" PetscInt_FMT " eigenpair%s) due to %s; iterations %" PetscInt_FMT "\n",((PetscObject)pep)->prefix?((PetscObject)pep)->prefix:"",pep->nconv,(pep->nconv>1)?"s":"",PEPConvergedReasons[pep->reason],pep->its));
    248:     else if (pep->reason <= 0) PetscCall(PetscViewerASCIIPrintf(viewer,"%s Polynomial eigensolve did not converge due to %s; iterations %" PetscInt_FMT "\n",((PetscObject)pep)->prefix?((PetscObject)pep)->prefix:"",PEPConvergedReasons[pep->reason],pep->its));
    249:     PetscCall(PetscViewerASCIISubtractTab(viewer,((PetscObject)pep)->tablevel));
    250:   }
    251:   PetscFunctionReturn(PETSC_SUCCESS);
    252: }

    254: /*@
    255:    PEPConvergedReasonViewFromOptions - Processes command line options to determine if/how
    256:    the `PEP` converged reason is to be viewed.

    258:    Collective

    260:    Input Parameter:
    261: .  pep - the polynomial eigensolver context

    263:    Level: intermediate

    265: .seealso: [](ch:pep), `PEPConvergedReasonView()`
    266: @*/
    267: PetscErrorCode PEPConvergedReasonViewFromOptions(PEP pep)
    268: {
    269:   PetscViewer       viewer;
    270:   PetscBool         flg;
    271:   static PetscBool  incall = PETSC_FALSE;
    272:   PetscViewerFormat format;

    274:   PetscFunctionBegin;
    275:   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
    276:   incall = PETSC_TRUE;
    277:   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)pep),((PetscObject)pep)->options,((PetscObject)pep)->prefix,"-pep_converged_reason",&viewer,&format,&flg));
    278:   if (flg) {
    279:     PetscCall(PetscViewerPushFormat(viewer,format));
    280:     PetscCall(PEPConvergedReasonView(pep,viewer));
    281:     PetscCall(PetscViewerPopFormat(viewer));
    282:     PetscCall(PetscViewerDestroy(&viewer));
    283:   }
    284:   incall = PETSC_FALSE;
    285:   PetscFunctionReturn(PETSC_SUCCESS);
    286: }

    288: static PetscErrorCode PEPErrorView_ASCII(PEP pep,PEPErrorType etype,PetscViewer viewer)
    289: {
    290:   PetscReal      error;
    291:   PetscInt       i,j,k,nvals;

    293:   PetscFunctionBegin;
    294:   nvals = (pep->which==PEP_ALL)? pep->nconv: pep->nev;
    295:   if (pep->which!=PEP_ALL && pep->nconv<pep->nev) {
    296:     PetscCall(PetscViewerASCIIPrintf(viewer," Problem: less than %" PetscInt_FMT " eigenvalues converged\n\n",pep->nev));
    297:     PetscFunctionReturn(PETSC_SUCCESS);
    298:   }
    299:   if (pep->which==PEP_ALL && !nvals) {
    300:     PetscCall(PetscViewerASCIIPrintf(viewer," No eigenvalues have been found\n\n"));
    301:     PetscFunctionReturn(PETSC_SUCCESS);
    302:   }
    303:   for (i=0;i<nvals;i++) {
    304:     PetscCall(PEPComputeError(pep,i,etype,&error));
    305:     if (error>=5.0*pep->tol) {
    306:       PetscCall(PetscViewerASCIIPrintf(viewer," Problem: some of the first %" PetscInt_FMT " relative errors are higher than the tolerance\n\n",nvals));
    307:       PetscFunctionReturn(PETSC_SUCCESS);
    308:     }
    309:   }
    310:   if (pep->which==PEP_ALL) PetscCall(PetscViewerASCIIPrintf(viewer," Found %" PetscInt_FMT " eigenvalues, all of them computed up to the required tolerance:",nvals));
    311:   else PetscCall(PetscViewerASCIIPrintf(viewer," All requested eigenvalues computed up to the required tolerance:"));
    312:   for (i=0;i<=(nvals-1)/8;i++) {
    313:     PetscCall(PetscViewerASCIIPrintf(viewer,"\n     "));
    314:     for (j=0;j<PetscMin(8,nvals-8*i);j++) {
    315:       k = pep->perm[8*i+j];
    316:       PetscCall(SlepcPrintEigenvalueASCII(viewer,pep->eigr[k],pep->eigi[k]));
    317:       if (8*i+j+1<nvals) PetscCall(PetscViewerASCIIPrintf(viewer,", "));
    318:     }
    319:   }
    320:   PetscCall(PetscViewerASCIIPrintf(viewer,"\n\n"));
    321:   PetscFunctionReturn(PETSC_SUCCESS);
    322: }

    324: static PetscErrorCode PEPErrorView_DETAIL(PEP pep,PEPErrorType etype,PetscViewer viewer)
    325: {
    326:   PetscReal      error,re,im;
    327:   PetscScalar    kr,ki;
    328:   PetscInt       i;
    329:   char           ex[30],sep[]=" ---------------------- --------------------\n";

    331:   PetscFunctionBegin;
    332:   if (!pep->nconv) PetscFunctionReturn(PETSC_SUCCESS);
    333:   switch (etype) {
    334:     case PEP_ERROR_ABSOLUTE:
    335:       PetscCall(PetscSNPrintf(ex,sizeof(ex),"   ||P(k)x||"));
    336:       break;
    337:     case PEP_ERROR_RELATIVE:
    338:       PetscCall(PetscSNPrintf(ex,sizeof(ex),"||P(k)x||/||kx||"));
    339:       break;
    340:     case PEP_ERROR_BACKWARD:
    341:       PetscCall(PetscSNPrintf(ex,sizeof(ex),"    eta(x,k)"));
    342:       break;
    343:   }
    344:   PetscCall(PetscViewerASCIIPrintf(viewer,"%s            k             %s\n%s",sep,ex,sep));
    345:   for (i=0;i<pep->nconv;i++) {
    346:     PetscCall(PEPGetEigenpair(pep,i,&kr,&ki,NULL,NULL));
    347:     PetscCall(PEPComputeError(pep,i,etype,&error));
    348: #if defined(PETSC_USE_COMPLEX)
    349:     re = PetscRealPart(kr);
    350:     im = PetscImaginaryPart(kr);
    351: #else
    352:     re = kr;
    353:     im = ki;
    354: #endif
    355:     if (im!=0.0) PetscCall(PetscViewerASCIIPrintf(viewer,"  % 9f%+9fi      %12g\n",(double)re,(double)im,(double)error));
    356:     else PetscCall(PetscViewerASCIIPrintf(viewer,"    % 12f           %12g\n",(double)re,(double)error));
    357:   }
    358:   PetscCall(PetscViewerASCIIPrintf(viewer,"%s",sep));
    359:   PetscFunctionReturn(PETSC_SUCCESS);
    360: }

    362: static PetscErrorCode PEPErrorView_MATLAB(PEP pep,PEPErrorType etype,PetscViewer viewer)
    363: {
    364:   PetscReal      error;
    365:   PetscInt       i;
    366:   const char     *name;

    368:   PetscFunctionBegin;
    369:   PetscCall(PetscObjectGetName((PetscObject)pep,&name));
    370:   PetscCall(PetscViewerASCIIPrintf(viewer,"Error_%s = [\n",name));
    371:   for (i=0;i<pep->nconv;i++) {
    372:     PetscCall(PEPComputeError(pep,i,etype,&error));
    373:     PetscCall(PetscViewerASCIIPrintf(viewer,"%18.16e\n",(double)error));
    374:   }
    375:   PetscCall(PetscViewerASCIIPrintf(viewer,"];\n"));
    376:   PetscFunctionReturn(PETSC_SUCCESS);
    377: }

    379: /*@
    380:    PEPErrorView - Displays the errors associated with the computed solution
    381:    (as well as the eigenvalues).

    383:    Collective

    385:    Input Parameters:
    386: +  pep    - the polynomial eigensolver context
    387: .  etype  - error type
    388: -  viewer - optional visualization context

    390:    Options Database Keys:
    391: +  -pep_error_absolute - print absolute errors of each eigenpair
    392: .  -pep_error_relative - print relative errors of each eigenpair
    393: -  -pep_error_backward - print backward errors of each eigenpair

    395:    Notes:
    396:    By default, this function checks the error of all eigenpairs and prints
    397:    the eigenvalues if all of them are below the requested tolerance.
    398:    If the viewer has format `PETSC_VIEWER_ASCII_INFO_DETAIL` then a table with
    399:    eigenvalues and corresponding errors is printed.

    401:    All the command-line options listed above admit an optional argument
    402:    specifying the viewer type and options. For instance, use
    403:    `-pep_error_relative :myerr.m:ascii_matlab` to save the errors in a file
    404:    that can be executed in Matlab.

    406:    Level: intermediate

    408: .seealso: [](ch:pep), `PEPSolve()`, `PEPValuesView()`, `PEPVectorsView()`
    409: @*/
    410: PetscErrorCode PEPErrorView(PEP pep,PEPErrorType etype,PetscViewer viewer)
    411: {
    412:   PetscBool         isascii;
    413:   PetscViewerFormat format;

    415:   PetscFunctionBegin;
    417:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pep),&viewer));
    419:   PetscCheckSameComm(pep,1,viewer,3);
    420:   PEPCheckSolved(pep,1);
    421:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
    422:   if (!isascii) PetscFunctionReturn(PETSC_SUCCESS);

    424:   PetscCall(PetscViewerGetFormat(viewer,&format));
    425:   switch (format) {
    426:     case PETSC_VIEWER_DEFAULT:
    427:     case PETSC_VIEWER_ASCII_INFO:
    428:       PetscCall(PEPErrorView_ASCII(pep,etype,viewer));
    429:       break;
    430:     case PETSC_VIEWER_ASCII_INFO_DETAIL:
    431:       PetscCall(PEPErrorView_DETAIL(pep,etype,viewer));
    432:       break;
    433:     case PETSC_VIEWER_ASCII_MATLAB:
    434:       PetscCall(PEPErrorView_MATLAB(pep,etype,viewer));
    435:       break;
    436:     default:
    437:       PetscCall(PetscInfo(pep,"Unsupported viewer format %s\n",PetscViewerFormats[format]));
    438:   }
    439:   PetscFunctionReturn(PETSC_SUCCESS);
    440: }

    442: /*@
    443:    PEPErrorViewFromOptions - Processes command line options to determine if/how
    444:    the errors of the computed solution are to be viewed.

    446:    Collective

    448:    Input Parameter:
    449: .  pep - the polynomial eigensolver context

    451:    Level: developer

    453: .seealso: [](ch:pep), `PEPErrorView()`
    454: @*/
    455: PetscErrorCode PEPErrorViewFromOptions(PEP pep)
    456: {
    457:   PetscViewer       viewer;
    458:   PetscBool         flg;
    459:   static PetscBool  incall = PETSC_FALSE;
    460:   PetscViewerFormat format;

    462:   PetscFunctionBegin;
    463:   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
    464:   incall = PETSC_TRUE;
    465:   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)pep),((PetscObject)pep)->options,((PetscObject)pep)->prefix,"-pep_error_absolute",&viewer,&format,&flg));
    466:   if (flg) {
    467:     PetscCall(PetscViewerPushFormat(viewer,format));
    468:     PetscCall(PEPErrorView(pep,PEP_ERROR_ABSOLUTE,viewer));
    469:     PetscCall(PetscViewerPopFormat(viewer));
    470:     PetscCall(PetscViewerDestroy(&viewer));
    471:   }
    472:   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)pep),((PetscObject)pep)->options,((PetscObject)pep)->prefix,"-pep_error_relative",&viewer,&format,&flg));
    473:   if (flg) {
    474:     PetscCall(PetscViewerPushFormat(viewer,format));
    475:     PetscCall(PEPErrorView(pep,PEP_ERROR_RELATIVE,viewer));
    476:     PetscCall(PetscViewerPopFormat(viewer));
    477:     PetscCall(PetscViewerDestroy(&viewer));
    478:   }
    479:   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)pep),((PetscObject)pep)->options,((PetscObject)pep)->prefix,"-pep_error_backward",&viewer,&format,&flg));
    480:   if (flg) {
    481:     PetscCall(PetscViewerPushFormat(viewer,format));
    482:     PetscCall(PEPErrorView(pep,PEP_ERROR_BACKWARD,viewer));
    483:     PetscCall(PetscViewerPopFormat(viewer));
    484:     PetscCall(PetscViewerDestroy(&viewer));
    485:   }
    486:   incall = PETSC_FALSE;
    487:   PetscFunctionReturn(PETSC_SUCCESS);
    488: }

    490: static PetscErrorCode PEPValuesView_DRAW(PEP pep,PetscViewer viewer)
    491: {
    492:   PetscDraw      draw;
    493:   PetscDrawSP    drawsp;
    494:   PetscReal      re,im;
    495:   PetscInt       i,k;

    497:   PetscFunctionBegin;
    498:   if (!pep->nconv) PetscFunctionReturn(PETSC_SUCCESS);
    499:   PetscCall(PetscViewerDrawGetDraw(viewer,0,&draw));
    500:   PetscCall(PetscDrawSetTitle(draw,"Computed Eigenvalues"));
    501:   PetscCall(PetscDrawSPCreate(draw,1,&drawsp));
    502:   for (i=0;i<pep->nconv;i++) {
    503:     k = pep->perm[i];
    504: #if defined(PETSC_USE_COMPLEX)
    505:     re = PetscRealPart(pep->eigr[k]);
    506:     im = PetscImaginaryPart(pep->eigr[k]);
    507: #else
    508:     re = pep->eigr[k];
    509:     im = pep->eigi[k];
    510: #endif
    511:     PetscCall(PetscDrawSPAddPoint(drawsp,&re,&im));
    512:   }
    513:   PetscCall(PetscDrawSPDraw(drawsp,PETSC_TRUE));
    514:   PetscCall(PetscDrawSPSave(drawsp));
    515:   PetscCall(PetscDrawSPDestroy(&drawsp));
    516:   PetscFunctionReturn(PETSC_SUCCESS);
    517: }

    519: static PetscErrorCode PEPValuesView_BINARY(PEP pep,PetscViewer viewer)
    520: {
    521: #if defined(PETSC_HAVE_COMPLEX)
    522:   PetscInt       i,k;
    523:   PetscComplex   *ev;
    524: #endif

    526:   PetscFunctionBegin;
    527: #if defined(PETSC_HAVE_COMPLEX)
    528:   PetscCall(PetscMalloc1(pep->nconv,&ev));
    529:   for (i=0;i<pep->nconv;i++) {
    530:     k = pep->perm[i];
    531: #if defined(PETSC_USE_COMPLEX)
    532:     ev[i] = pep->eigr[k];
    533: #else
    534:     ev[i] = PetscCMPLX(pep->eigr[k],pep->eigi[k]);
    535: #endif
    536:   }
    537:   PetscCall(PetscViewerBinaryWrite(viewer,ev,pep->nconv,PETSC_COMPLEX));
    538:   PetscCall(PetscFree(ev));
    539: #endif
    540:   PetscFunctionReturn(PETSC_SUCCESS);
    541: }

    543: #if defined(PETSC_HAVE_HDF5)
    544: static PetscErrorCode PEPValuesView_HDF5(PEP pep,PetscViewer viewer)
    545: {
    546:   PetscInt       i,k,n,N;
    547:   PetscMPIInt    rank;
    548:   Vec            v;
    549:   char           vname[30];
    550:   const char     *ename;

    552:   PetscFunctionBegin;
    553:   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)pep),&rank));
    554:   N = pep->nconv;
    555:   n = rank? 0: N;
    556:   /* create a vector containing the eigenvalues */
    557:   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)pep),n,N,&v));
    558:   PetscCall(PetscObjectGetName((PetscObject)pep,&ename));
    559:   PetscCall(PetscSNPrintf(vname,sizeof(vname),"eigr_%s",ename));
    560:   PetscCall(PetscObjectSetName((PetscObject)v,vname));
    561:   if (!rank) {
    562:     for (i=0;i<pep->nconv;i++) {
    563:       k = pep->perm[i];
    564:       PetscCall(VecSetValue(v,i,pep->eigr[k],INSERT_VALUES));
    565:     }
    566:   }
    567:   PetscCall(VecAssemblyBegin(v));
    568:   PetscCall(VecAssemblyEnd(v));
    569:   PetscCall(VecView(v,viewer));
    570: #if !defined(PETSC_USE_COMPLEX)
    571:   /* in real scalars write the imaginary part as a separate vector */
    572:   PetscCall(PetscSNPrintf(vname,sizeof(vname),"eigi_%s",ename));
    573:   PetscCall(PetscObjectSetName((PetscObject)v,vname));
    574:   if (!rank) {
    575:     for (i=0;i<pep->nconv;i++) {
    576:       k = pep->perm[i];
    577:       PetscCall(VecSetValue(v,i,pep->eigi[k],INSERT_VALUES));
    578:     }
    579:   }
    580:   PetscCall(VecAssemblyBegin(v));
    581:   PetscCall(VecAssemblyEnd(v));
    582:   PetscCall(VecView(v,viewer));
    583: #endif
    584:   PetscCall(VecDestroy(&v));
    585:   PetscFunctionReturn(PETSC_SUCCESS);
    586: }
    587: #endif

    589: static PetscErrorCode PEPValuesView_ASCII(PEP pep,PetscViewer viewer)
    590: {
    591:   PetscInt       i,k;

    593:   PetscFunctionBegin;
    594:   PetscCall(PetscViewerASCIIPrintf(viewer,"Eigenvalues = \n"));
    595:   for (i=0;i<pep->nconv;i++) {
    596:     k = pep->perm[i];
    597:     PetscCall(PetscViewerASCIIPrintf(viewer,"   "));
    598:     PetscCall(SlepcPrintEigenvalueASCII(viewer,pep->eigr[k],pep->eigi[k]));
    599:     PetscCall(PetscViewerASCIIPrintf(viewer,"\n"));
    600:   }
    601:   PetscCall(PetscViewerASCIIPrintf(viewer,"\n"));
    602:   PetscFunctionReturn(PETSC_SUCCESS);
    603: }

    605: static PetscErrorCode PEPValuesView_MATLAB(PEP pep,PetscViewer viewer)
    606: {
    607:   PetscInt       i,k;
    608:   PetscReal      re,im;
    609:   const char     *name;

    611:   PetscFunctionBegin;
    612:   PetscCall(PetscObjectGetName((PetscObject)pep,&name));
    613:   PetscCall(PetscViewerASCIIPrintf(viewer,"Lambda_%s = [\n",name));
    614:   for (i=0;i<pep->nconv;i++) {
    615:     k = pep->perm[i];
    616: #if defined(PETSC_USE_COMPLEX)
    617:     re = PetscRealPart(pep->eigr[k]);
    618:     im = PetscImaginaryPart(pep->eigr[k]);
    619: #else
    620:     re = pep->eigr[k];
    621:     im = pep->eigi[k];
    622: #endif
    623:     if (im!=0.0) PetscCall(PetscViewerASCIIPrintf(viewer,"%18.16e%+18.16ei\n",(double)re,(double)im));
    624:     else PetscCall(PetscViewerASCIIPrintf(viewer,"%18.16e\n",(double)re));
    625:   }
    626:   PetscCall(PetscViewerASCIIPrintf(viewer,"];\n"));
    627:   PetscFunctionReturn(PETSC_SUCCESS);
    628: }

    630: /*@
    631:    PEPValuesView - Displays the computed eigenvalues in a viewer.

    633:    Collective

    635:    Input Parameters:
    636: +  pep    - the polynomial eigensolver context
    637: -  viewer - the viewer

    639:    Options Database Key:
    640: .  -pep_view_values - print computed eigenvalues

    642:    Note:
    643:    The command-line option listed above admits an optional argument
    644:    specifying the viewer type and options. For instance, use
    645:    `-pep_view_values :evals.m:ascii_matlab` to save the values in a file
    646:    that can be executed in Matlab.
    647:    See `PetscObjectViewFromOptions()` for more details.

    649:    Level: intermediate

    651: .seealso: [](ch:pep), `PEPSolve()`, `PEPVectorsView()`, `PEPErrorView()`
    652: @*/
    653: PetscErrorCode PEPValuesView(PEP pep,PetscViewer viewer)
    654: {
    655:   PetscBool         isascii,isdraw,isbinary;
    656:   PetscViewerFormat format;
    657: #if defined(PETSC_HAVE_HDF5)
    658:   PetscBool         ishdf5;
    659: #endif

    661:   PetscFunctionBegin;
    663:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pep),&viewer));
    665:   PetscCheckSameComm(pep,1,viewer,2);
    666:   PEPCheckSolved(pep,1);
    667:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw));
    668:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary));
    669: #if defined(PETSC_HAVE_HDF5)
    670:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERHDF5,&ishdf5));
    671: #endif
    672:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii));
    673:   if (isdraw) PetscCall(PEPValuesView_DRAW(pep,viewer));
    674:   else if (isbinary) PetscCall(PEPValuesView_BINARY(pep,viewer));
    675: #if defined(PETSC_HAVE_HDF5)
    676:   else if (ishdf5) PetscCall(PEPValuesView_HDF5(pep,viewer));
    677: #endif
    678:   else if (isascii) {
    679:     PetscCall(PetscViewerGetFormat(viewer,&format));
    680:     switch (format) {
    681:       case PETSC_VIEWER_DEFAULT:
    682:       case PETSC_VIEWER_ASCII_INFO:
    683:       case PETSC_VIEWER_ASCII_INFO_DETAIL:
    684:         PetscCall(PEPValuesView_ASCII(pep,viewer));
    685:         break;
    686:       case PETSC_VIEWER_ASCII_MATLAB:
    687:         PetscCall(PEPValuesView_MATLAB(pep,viewer));
    688:         break;
    689:       default:
    690:         PetscCall(PetscInfo(pep,"Unsupported viewer format %s\n",PetscViewerFormats[format]));
    691:     }
    692:   }
    693:   PetscFunctionReturn(PETSC_SUCCESS);
    694: }

    696: /*@
    697:    PEPValuesViewFromOptions - Processes command line options to determine if/how
    698:    the computed eigenvalues are to be viewed.

    700:    Collective

    702:    Input Parameter:
    703: .  pep - the polynomial eigensolver context

    705:    Level: developer

    707: .seealso: [](ch:pep), `PEPValuesView()`
    708: @*/
    709: PetscErrorCode PEPValuesViewFromOptions(PEP pep)
    710: {
    711:   PetscViewer       viewer;
    712:   PetscBool         flg;
    713:   static PetscBool  incall = PETSC_FALSE;
    714:   PetscViewerFormat format;

    716:   PetscFunctionBegin;
    717:   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
    718:   incall = PETSC_TRUE;
    719:   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)pep),((PetscObject)pep)->options,((PetscObject)pep)->prefix,"-pep_view_values",&viewer,&format,&flg));
    720:   if (flg) {
    721:     PetscCall(PetscViewerPushFormat(viewer,format));
    722:     PetscCall(PEPValuesView(pep,viewer));
    723:     PetscCall(PetscViewerPopFormat(viewer));
    724:     PetscCall(PetscViewerDestroy(&viewer));
    725:   }
    726:   incall = PETSC_FALSE;
    727:   PetscFunctionReturn(PETSC_SUCCESS);
    728: }

    730: /*@
    731:    PEPVectorsView - Outputs computed eigenvectors to a viewer.

    733:    Collective

    735:    Input Parameters:
    736: +  pep    - the polynomial eigensolver context
    737: -  viewer - the viewer

    739:    Options Database Key:
    740: .  -pep_view_vectors - output eigenvectors

    742:    Notes:
    743:    If PETSc was configured with real scalars, complex conjugate eigenvectors
    744:    will be viewed as two separate real vectors, one containing the real part
    745:    and another one containing the imaginary part.

    747:    The command-line option listed above admits an optional argument
    748:    specifying the viewer type and options. For instance, use
    749:    `-pep_view_vectors binary:evecs.bin` to save the vectors in a binary file.
    750:    See `PetscObjectViewFromOptions()` for more details.

    752:    Level: intermediate

    754: .seealso: [](ch:pep), `PEPSolve()`, `PEPValuesView()`, `PEPErrorView()`
    755: @*/
    756: PetscErrorCode PEPVectorsView(PEP pep,PetscViewer viewer)
    757: {
    758:   PetscInt       i,k;
    759:   Vec            xr,xi=NULL;

    761:   PetscFunctionBegin;
    763:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)pep),&viewer));
    765:   PetscCheckSameComm(pep,1,viewer,2);
    766:   PEPCheckSolved(pep,1);
    767:   if (pep->nconv) {
    768:     PetscCall(PEPComputeVectors(pep));
    769:     PetscCall(BVCreateVec(pep->V,&xr));
    770: #if !defined(PETSC_USE_COMPLEX)
    771:     PetscCall(BVCreateVec(pep->V,&xi));
    772: #endif
    773:     for (i=0;i<pep->nconv;i++) {
    774:       k = pep->perm[i];
    775:       PetscCall(BV_GetEigenvector(pep->V,k,pep->eigi[k],xr,xi));
    776:       PetscCall(SlepcViewEigenvector(viewer,xr,xi,"X",i,(PetscObject)pep));
    777:     }
    778:     PetscCall(VecDestroy(&xr));
    779: #if !defined(PETSC_USE_COMPLEX)
    780:     PetscCall(VecDestroy(&xi));
    781: #endif
    782:   }
    783:   PetscFunctionReturn(PETSC_SUCCESS);
    784: }

    786: /*@
    787:    PEPVectorsViewFromOptions - Processes command line options to determine if/how
    788:    the computed eigenvectors are to be viewed.

    790:    Collective

    792:    Input Parameter:
    793: .  pep - the polynomial eigensolver context

    795:    Level: developer

    797: .seealso: [](ch:pep), `PEPVectorsView()`
    798: @*/
    799: PetscErrorCode PEPVectorsViewFromOptions(PEP pep)
    800: {
    801:   PetscViewer       viewer;
    802:   PetscBool         flg = PETSC_FALSE;
    803:   static PetscBool  incall = PETSC_FALSE;
    804:   PetscViewerFormat format;

    806:   PetscFunctionBegin;
    807:   if (incall) PetscFunctionReturn(PETSC_SUCCESS);
    808:   incall = PETSC_TRUE;
    809:   PetscCall(PetscOptionsCreateViewer(PetscObjectComm((PetscObject)pep),((PetscObject)pep)->options,((PetscObject)pep)->prefix,"-pep_view_vectors",&viewer,&format,&flg));
    810:   if (flg) {
    811:     PetscCall(PetscViewerPushFormat(viewer,format));
    812:     PetscCall(PEPVectorsView(pep,viewer));
    813:     PetscCall(PetscViewerPopFormat(viewer));
    814:     PetscCall(PetscViewerDestroy(&viewer));
    815:   }
    816:   incall = PETSC_FALSE;
    817:   PetscFunctionReturn(PETSC_SUCCESS);
    818: }