LCOV - code coverage report
Current view: top level - nep/tests - test7.c (source / functions) Hit Total Coverage
Test: SLEPc Lines: 213 217 98.2 %
Date: 2024-05-03 00:51:52 Functions: 13 13 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             : static char help[] = "Test the NLEIGS solver with shell matrices.\n\n"
      12             :   "This is based on ex27.\n"
      13             :   "The command line options are:\n"
      14             :   "  -n <n>, where <n> = matrix dimension.\n"
      15             :   "  -split <0/1>, to select the split form in the problem definition (enabled by default).\n";
      16             : 
      17             : /*
      18             :    Solve T(lambda)x=0 using NLEIGS solver
      19             :       with T(lambda) = -D+sqrt(lambda)*I
      20             :       where D is the Laplacian operator in 1 dimension
      21             :       and with the interpolation interval [.01,16]
      22             : */
      23             : 
      24             : #include <slepcnep.h>
      25             : 
      26             : /* User-defined routines */
      27             : PetscErrorCode FormFunction(NEP,PetscScalar,Mat,Mat,void*);
      28             : PetscErrorCode ComputeSingularities(NEP,PetscInt*,PetscScalar*,void*);
      29             : PetscErrorCode MatMult_A0(Mat,Vec,Vec);
      30             : PetscErrorCode MatGetDiagonal_A0(Mat,Vec);
      31             : PetscErrorCode MatDuplicate_A0(Mat,MatDuplicateOption,Mat*);
      32             : PetscErrorCode MatMult_A1(Mat,Vec,Vec);
      33             : PetscErrorCode MatGetDiagonal_A1(Mat,Vec);
      34             : PetscErrorCode MatDuplicate_A1(Mat,MatDuplicateOption,Mat*);
      35             : PetscErrorCode MatMult_F(Mat,Vec,Vec);
      36             : PetscErrorCode MatGetDiagonal_F(Mat,Vec);
      37             : PetscErrorCode MatDuplicate_F(Mat,MatDuplicateOption,Mat*);
      38             : PetscErrorCode MatDestroy_F(Mat);
      39             : 
      40             : typedef struct {
      41             :   PetscScalar t;  /* square root of lambda */
      42             : } MatCtx;
      43             : 
      44           6 : int main(int argc,char **argv)
      45             : {
      46           6 :   NEP            nep;
      47           6 :   KSP            *ksp;
      48           6 :   PC             pc;
      49           6 :   Mat            F,A[2];
      50           6 :   NEPType        type;
      51           6 :   PetscInt       i,n=100,nev,its,nsolve;
      52           6 :   PetscReal      keep,tol=PETSC_SQRT_MACHINE_EPSILON/10;
      53           6 :   RG             rg;
      54           6 :   FN             f[2];
      55           6 :   PetscBool      terse,flg,lock,split=PETSC_TRUE;
      56           6 :   PetscScalar    coeffs;
      57           6 :   MatCtx         *ctx;
      58             : 
      59           6 :   PetscFunctionBeginUser;
      60           6 :   PetscCall(SlepcInitialize(&argc,&argv,(char*)0,help));
      61           6 :   PetscCall(PetscOptionsGetInt(NULL,NULL,"-n",&n,NULL));
      62           6 :   PetscCall(PetscOptionsGetBool(NULL,NULL,"-split",&split,NULL));
      63           9 :   PetscCall(PetscPrintf(PETSC_COMM_WORLD,"\nSquare root eigenproblem, n=%" PetscInt_FMT "%s\n\n",n,split?" (in split form)":""));
      64             : 
      65             :   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      66             :      Create NEP context, configure NLEIGS with appropriate options
      67             :      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
      68             : 
      69           6 :   PetscCall(NEPCreate(PETSC_COMM_WORLD,&nep));
      70           6 :   PetscCall(NEPSetType(nep,NEPNLEIGS));
      71           6 :   PetscCall(NEPNLEIGSSetSingularitiesFunction(nep,ComputeSingularities,NULL));
      72           6 :   PetscCall(NEPGetRG(nep,&rg));
      73           6 :   PetscCall(RGSetType(rg,RGINTERVAL));
      74             : #if defined(PETSC_USE_COMPLEX)
      75             :   PetscCall(RGIntervalSetEndpoints(rg,0.01,16.0,-0.001,0.001));
      76             : #else
      77           6 :   PetscCall(RGIntervalSetEndpoints(rg,0.01,16.0,0,0));
      78             : #endif
      79           6 :   PetscCall(NEPSetTarget(nep,1.1));
      80           6 :   PetscCall(NEPNLEIGSGetKSPs(nep,&nsolve,&ksp));
      81          12 :   for (i=0;i<nsolve;i++) {
      82           6 :    PetscCall(KSPSetType(ksp[i],KSPBICG));
      83           6 :    PetscCall(KSPGetPC(ksp[i],&pc));
      84           6 :    PetscCall(PCSetType(pc,PCJACOBI));
      85           6 :    PetscCall(KSPSetTolerances(ksp[i],tol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT));
      86             :   }
      87             : 
      88             :   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      89             :      Define the nonlinear problem
      90             :      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
      91             : 
      92           6 :   if (split) {
      93             :     /* Create matrix A0 (tridiagonal) */
      94           3 :     PetscCall(MatCreateShell(PETSC_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,n,n,NULL,&A[0]));
      95           3 :     PetscCall(MatShellSetOperation(A[0],MATOP_MULT,(void(*)(void))MatMult_A0));
      96           3 :     PetscCall(MatShellSetOperation(A[0],MATOP_MULT_TRANSPOSE,(void(*)(void))MatMult_A0));
      97           3 :     PetscCall(MatShellSetOperation(A[0],MATOP_GET_DIAGONAL,(void(*)(void))MatGetDiagonal_A0));
      98           3 :     PetscCall(MatShellSetOperation(A[0],MATOP_DUPLICATE,(void(*)(void))MatDuplicate_A0));
      99             : 
     100             :     /* Create matrix A0 (identity) */
     101           3 :     PetscCall(MatCreateShell(PETSC_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,n,n,NULL,&A[1]));
     102           3 :     PetscCall(MatShellSetOperation(A[1],MATOP_MULT,(void(*)(void))MatMult_A1));
     103           3 :     PetscCall(MatShellSetOperation(A[1],MATOP_MULT_TRANSPOSE,(void(*)(void))MatMult_A1));
     104           3 :     PetscCall(MatShellSetOperation(A[1],MATOP_GET_DIAGONAL,(void(*)(void))MatGetDiagonal_A1));
     105           3 :     PetscCall(MatShellSetOperation(A[1],MATOP_DUPLICATE,(void(*)(void))MatDuplicate_A1));
     106             : 
     107             :     /* Define functions for the split form */
     108           3 :     PetscCall(FNCreate(PETSC_COMM_WORLD,&f[0]));
     109           3 :     PetscCall(FNSetType(f[0],FNRATIONAL));
     110           3 :     coeffs = 1.0;
     111           3 :     PetscCall(FNRationalSetNumerator(f[0],1,&coeffs));
     112           3 :     PetscCall(FNCreate(PETSC_COMM_WORLD,&f[1]));
     113           3 :     PetscCall(FNSetType(f[1],FNSQRT));
     114           3 :     PetscCall(NEPSetSplitOperator(nep,2,A,f,SUBSET_NONZERO_PATTERN));
     115             :   } else {
     116             :     /* Callback form: create shell matrix for F=A0+sqrt(lambda)*A1  */
     117           3 :     PetscCall(PetscNew(&ctx));
     118           3 :     PetscCall(MatCreateShell(PETSC_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,n,n,(void*)ctx,&F));
     119           3 :     PetscCall(MatShellSetOperation(F,MATOP_MULT,(void(*)(void))MatMult_F));
     120           3 :     PetscCall(MatShellSetOperation(F,MATOP_MULT_TRANSPOSE,(void(*)(void))MatMult_F));
     121           3 :     PetscCall(MatShellSetOperation(F,MATOP_GET_DIAGONAL,(void(*)(void))MatGetDiagonal_F));
     122           3 :     PetscCall(MatShellSetOperation(F,MATOP_DUPLICATE,(void(*)(void))MatDuplicate_F));
     123           3 :     PetscCall(MatShellSetOperation(F,MATOP_DESTROY,(void(*)(void))MatDestroy_F));
     124             :     /* Set Function evaluation routine */
     125           3 :     PetscCall(NEPSetFunction(nep,F,F,FormFunction,NULL));
     126             :   }
     127             : 
     128             :   /* Set solver parameters at runtime */
     129           6 :   PetscCall(NEPSetFromOptions(nep));
     130             : 
     131             :   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     132             :                       Solve the eigensystem
     133             :      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     134           6 :   PetscCall(NEPSolve(nep));
     135           6 :   PetscCall(NEPGetType(nep,&type));
     136           6 :   PetscCall(PetscPrintf(PETSC_COMM_WORLD," Solution method: %s\n",type));
     137           6 :   PetscCall(NEPGetDimensions(nep,&nev,NULL,NULL));
     138           6 :   PetscCall(PetscPrintf(PETSC_COMM_WORLD," Number of requested eigenvalues: %" PetscInt_FMT "\n",nev));
     139           6 :   PetscCall(PetscObjectTypeCompare((PetscObject)nep,NEPNLEIGS,&flg));
     140           6 :   if (flg) {
     141           6 :     PetscCall(NEPNLEIGSGetRestart(nep,&keep));
     142           6 :     PetscCall(NEPNLEIGSGetLocking(nep,&lock));
     143           6 :     PetscCall(NEPNLEIGSGetInterpolation(nep,&tol,&its));
     144           6 :     PetscCall(PetscPrintf(PETSC_COMM_WORLD," Restart factor is %3.2f",(double)keep));
     145           6 :     if (lock) PetscCall(PetscPrintf(PETSC_COMM_WORLD," (locking activated)"));
     146           6 :     PetscCall(PetscPrintf(PETSC_COMM_WORLD,"\n Divided diferences with tol=%6.2g maxit=%" PetscInt_FMT "\n",(double)tol,its));
     147           6 :     PetscCall(PetscPrintf(PETSC_COMM_WORLD,"\n"));
     148             :   }
     149             : 
     150             :   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     151             :                     Display solution and clean up
     152             :      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     153             : 
     154             :   /* show detailed info unless -terse option is given by user */
     155           6 :   PetscCall(PetscOptionsHasName(NULL,NULL,"-terse",&terse));
     156           6 :   if (terse) PetscCall(NEPErrorView(nep,NEP_ERROR_RELATIVE,NULL));
     157             :   else {
     158           0 :     PetscCall(PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD,PETSC_VIEWER_ASCII_INFO_DETAIL));
     159           0 :     PetscCall(NEPConvergedReasonView(nep,PETSC_VIEWER_STDOUT_WORLD));
     160           0 :     PetscCall(NEPErrorView(nep,NEP_ERROR_RELATIVE,PETSC_VIEWER_STDOUT_WORLD));
     161           0 :     PetscCall(PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD));
     162             :   }
     163           6 :   PetscCall(NEPDestroy(&nep));
     164           6 :   if (split) {
     165           3 :     PetscCall(MatDestroy(&A[0]));
     166           3 :     PetscCall(MatDestroy(&A[1]));
     167           3 :     PetscCall(FNDestroy(&f[0]));
     168           3 :     PetscCall(FNDestroy(&f[1]));
     169           3 :   } else PetscCall(MatDestroy(&F));
     170           6 :   PetscCall(SlepcFinalize());
     171             :   return 0;
     172             : }
     173             : 
     174             : /*
     175             :    FormFunction - Computes Function matrix  T(lambda)
     176             : */
     177          78 : PetscErrorCode FormFunction(NEP nep,PetscScalar lambda,Mat fun,Mat B,void *ctx)
     178             : {
     179          78 :   MatCtx         *ctxF;
     180             : 
     181          78 :   PetscFunctionBeginUser;
     182          78 :   PetscCall(MatShellGetContext(fun,&ctxF));
     183          78 :   ctxF->t = PetscSqrtScalar(lambda);
     184          78 :   PetscFunctionReturn(PETSC_SUCCESS);
     185             : }
     186             : 
     187             : /*
     188             :    ComputeSingularities - Computes maxnp points (at most) in the complex plane where
     189             :    the function T(.) is not analytic.
     190             : 
     191             :    In this case, we discretize the singularity region (-inf,0)~(-10e+6,-10e-6)
     192             : */
     193           6 : PetscErrorCode ComputeSingularities(NEP nep,PetscInt *maxnp,PetscScalar *xi,void *pt)
     194             : {
     195           6 :   PetscReal h;
     196           6 :   PetscInt  i;
     197             : 
     198           6 :   PetscFunctionBeginUser;
     199           6 :   h = 12.0/(*maxnp-1);
     200           6 :   xi[0] = -1e-6; xi[*maxnp-1] = -1e+6;
     201       59994 :   for (i=1;i<*maxnp-1;i++) xi[i] = -PetscPowReal(10,-6+h*i);
     202           6 :   PetscFunctionReturn(PETSC_SUCCESS);
     203             : }
     204             : 
     205             : /* -------------------------------- A0 ----------------------------------- */
     206             : 
     207       16905 : PetscErrorCode MatMult_A0(Mat A,Vec x,Vec y)
     208             : {
     209       16905 :   PetscInt          i,n;
     210       16905 :   PetscMPIInt       rank,size,next,prev;
     211       16905 :   const PetscScalar *px;
     212       16905 :   PetscScalar       *py,upper=0.0,lower=0.0;
     213       16905 :   MPI_Comm          comm;
     214             : 
     215       16905 :   PetscFunctionBeginUser;
     216       16905 :   PetscCall(PetscObjectGetComm((PetscObject)A,&comm));
     217       16905 :   PetscCallMPI(MPI_Comm_size(comm,&size));
     218       16905 :   PetscCallMPI(MPI_Comm_rank(comm,&rank));
     219       16905 :   next = rank==size-1? MPI_PROC_NULL: rank+1;
     220       16905 :   prev = rank==0? MPI_PROC_NULL: rank-1;
     221             : 
     222       16905 :   PetscCall(VecGetArrayRead(x,&px));
     223       16905 :   PetscCall(VecGetArray(y,&py));
     224       16905 :   PetscCall(VecGetLocalSize(x,&n));
     225             : 
     226       16905 :   PetscCallMPI(MPI_Sendrecv(px,1,MPIU_SCALAR,prev,0,&lower,1,MPIU_SCALAR,next,0,comm,MPI_STATUS_IGNORE));
     227       16905 :   PetscCallMPI(MPI_Sendrecv(px+n-1,1,MPIU_SCALAR,next,0,&upper,1,MPIU_SCALAR,prev,0,comm,MPI_STATUS_IGNORE));
     228             : 
     229       16905 :   py[0] = upper-2.0*px[0]+px[1];
     230     1110295 :   for (i=1;i<n-1;i++) py[i] = px[i-1]-2.0*px[i]+px[i+1];
     231       16905 :   py[n-1] = px[n-2]-2.0*px[n-1]+lower;
     232       16905 :   PetscCall(VecRestoreArrayRead(x,&px));
     233       16905 :   PetscCall(VecRestoreArray(y,&py));
     234       16905 :   PetscFunctionReturn(PETSC_SUCCESS);
     235             : }
     236             : 
     237           3 : PetscErrorCode MatGetDiagonal_A0(Mat A,Vec diag)
     238             : {
     239           3 :   PetscFunctionBeginUser;
     240           3 :   PetscCall(VecSet(diag,-2.0));
     241           3 :   PetscFunctionReturn(PETSC_SUCCESS);
     242             : }
     243             : 
     244           9 : PetscErrorCode MatDuplicate_A0(Mat A,MatDuplicateOption op,Mat *B)
     245             : {
     246           9 :   PetscInt       m,n,M,N;
     247           9 :   MPI_Comm       comm;
     248             : 
     249           9 :   PetscFunctionBegin;
     250           9 :   PetscCall(MatGetSize(A,&M,&N));
     251           9 :   PetscCall(MatGetLocalSize(A,&m,&n));
     252           9 :   PetscCall(PetscObjectGetComm((PetscObject)A,&comm));
     253           9 :   PetscCall(MatCreateShell(comm,m,n,M,N,NULL,B));
     254           9 :   PetscCall(MatShellSetOperation(*B,MATOP_MULT,(void(*)(void))MatMult_A0));
     255           9 :   PetscCall(MatShellSetOperation(*B,MATOP_MULT_TRANSPOSE,(void(*)(void))MatMult_A0));
     256           9 :   PetscCall(MatShellSetOperation(*B,MATOP_GET_DIAGONAL,(void(*)(void))MatGetDiagonal_A0));
     257           9 :   PetscCall(MatShellSetOperation(*B,MATOP_DUPLICATE,(void(*)(void))MatDuplicate_A0));
     258           9 :   PetscFunctionReturn(PETSC_SUCCESS);
     259             : }
     260             : 
     261             : /* -------------------------------- A1 ----------------------------------- */
     262             : 
     263       16905 : PetscErrorCode MatMult_A1(Mat A,Vec x,Vec y)
     264             : {
     265       16905 :   PetscFunctionBeginUser;
     266       16905 :   PetscCall(VecCopy(x,y));
     267       16905 :   PetscFunctionReturn(PETSC_SUCCESS);
     268             : }
     269             : 
     270           3 : PetscErrorCode MatGetDiagonal_A1(Mat A,Vec diag)
     271             : {
     272           3 :   PetscFunctionBeginUser;
     273           3 :   PetscCall(VecSet(diag,1.0));
     274           3 :   PetscFunctionReturn(PETSC_SUCCESS);
     275             : }
     276             : 
     277           3 : PetscErrorCode MatDuplicate_A1(Mat A,MatDuplicateOption op,Mat *B)
     278             : {
     279           3 :   PetscInt       m,n,M,N;
     280           3 :   MPI_Comm       comm;
     281             : 
     282           3 :   PetscFunctionBegin;
     283           3 :   PetscCall(MatGetSize(A,&M,&N));
     284           3 :   PetscCall(MatGetLocalSize(A,&m,&n));
     285           3 :   PetscCall(PetscObjectGetComm((PetscObject)A,&comm));
     286           3 :   PetscCall(MatCreateShell(comm,m,n,M,N,NULL,B));
     287           3 :   PetscCall(MatShellSetOperation(*B,MATOP_MULT,(void(*)(void))MatMult_A1));
     288           3 :   PetscCall(MatShellSetOperation(*B,MATOP_MULT_TRANSPOSE,(void(*)(void))MatMult_A1));
     289           3 :   PetscCall(MatShellSetOperation(*B,MATOP_GET_DIAGONAL,(void(*)(void))MatGetDiagonal_A1));
     290           3 :   PetscCall(MatShellSetOperation(*B,MATOP_DUPLICATE,(void(*)(void))MatDuplicate_A1));
     291           3 :   PetscFunctionReturn(PETSC_SUCCESS);
     292             : }
     293             : 
     294             : /* -------------------------------- F ----------------------------------- */
     295             : 
     296      380875 : PetscErrorCode MatMult_F(Mat A,Vec x,Vec y)
     297             : {
     298      380875 :   PetscInt          i,n;
     299      380875 :   PetscMPIInt       rank,size,next,prev;
     300      380875 :   const PetscScalar *px;
     301      380875 :   PetscScalar       *py,d,upper=0.0,lower=0.0;
     302      380875 :   MatCtx            *ctx;
     303      380875 :   MPI_Comm          comm;
     304             : 
     305      380875 :   PetscFunctionBeginUser;
     306      380875 :   PetscCall(PetscObjectGetComm((PetscObject)A,&comm));
     307      380875 :   PetscCallMPI(MPI_Comm_size(comm,&size));
     308      380875 :   PetscCallMPI(MPI_Comm_rank(comm,&rank));
     309      380875 :   next = rank==size-1? MPI_PROC_NULL: rank+1;
     310      380875 :   prev = rank==0? MPI_PROC_NULL: rank-1;
     311             : 
     312      380875 :   PetscCall(MatShellGetContext(A,&ctx));
     313      380875 :   PetscCall(VecGetArrayRead(x,&px));
     314      380875 :   PetscCall(VecGetArray(y,&py));
     315      380875 :   PetscCall(VecGetLocalSize(x,&n));
     316             : 
     317      380875 :   PetscCallMPI(MPI_Sendrecv(px,1,MPIU_SCALAR,prev,0,&lower,1,MPIU_SCALAR,next,0,comm,MPI_STATUS_IGNORE));
     318      380875 :   PetscCallMPI(MPI_Sendrecv(px+n-1,1,MPIU_SCALAR,next,0,&upper,1,MPIU_SCALAR,prev,0,comm,MPI_STATUS_IGNORE));
     319             : 
     320      380875 :   d = -2.0+ctx->t;
     321      380875 :   py[0] = upper+d*px[0]+px[1];
     322    25007725 :   for (i=1;i<n-1;i++) py[i] = px[i-1]+d*px[i]+px[i+1];
     323      380875 :   py[n-1] = px[n-2]+d*px[n-1]+lower;
     324      380875 :   PetscCall(VecRestoreArrayRead(x,&px));
     325      380875 :   PetscCall(VecRestoreArray(y,&py));
     326      380875 :   PetscFunctionReturn(PETSC_SUCCESS);
     327             : }
     328             : 
     329          69 : PetscErrorCode MatGetDiagonal_F(Mat A,Vec diag)
     330             : {
     331          69 :   MatCtx         *ctx;
     332             : 
     333          69 :   PetscFunctionBeginUser;
     334          69 :   PetscCall(MatShellGetContext(A,&ctx));
     335          69 :   PetscCall(VecSet(diag,-2.0+ctx->t));
     336          69 :   PetscFunctionReturn(PETSC_SUCCESS);
     337             : }
     338             : 
     339          69 : PetscErrorCode MatDuplicate_F(Mat A,MatDuplicateOption op,Mat *B)
     340             : {
     341          69 :   MatCtx         *actx,*bctx;
     342          69 :   PetscInt       m,n,M,N;
     343          69 :   MPI_Comm       comm;
     344             : 
     345          69 :   PetscFunctionBegin;
     346          69 :   PetscCall(MatShellGetContext(A,&actx));
     347          69 :   PetscCall(MatGetSize(A,&M,&N));
     348          69 :   PetscCall(MatGetLocalSize(A,&m,&n));
     349          69 :   PetscCall(PetscNew(&bctx));
     350          69 :   bctx->t = actx->t;
     351          69 :   PetscCall(PetscObjectGetComm((PetscObject)A,&comm));
     352          69 :   PetscCall(MatCreateShell(comm,m,n,M,N,(void*)bctx,B));
     353          69 :   PetscCall(MatShellSetOperation(*B,MATOP_MULT,(void(*)(void))MatMult_F));
     354          69 :   PetscCall(MatShellSetOperation(*B,MATOP_MULT_TRANSPOSE,(void(*)(void))MatMult_F));
     355          69 :   PetscCall(MatShellSetOperation(*B,MATOP_GET_DIAGONAL,(void(*)(void))MatGetDiagonal_F));
     356          69 :   PetscCall(MatShellSetOperation(*B,MATOP_DUPLICATE,(void(*)(void))MatDuplicate_F));
     357          69 :   PetscCall(MatShellSetOperation(*B,MATOP_DESTROY,(void(*)(void))MatDestroy_F));
     358          69 :   PetscFunctionReturn(PETSC_SUCCESS);
     359             : }
     360             : 
     361          72 : PetscErrorCode MatDestroy_F(Mat A)
     362             : {
     363          72 :   MatCtx         *ctx;
     364             : 
     365          72 :   PetscFunctionBegin;
     366          72 :   PetscCall(MatShellGetContext(A,&ctx));
     367          72 :   PetscCall(PetscFree(ctx));
     368          72 :   PetscFunctionReturn(PETSC_SUCCESS);
     369             : }
     370             : 
     371             : /*TEST
     372             : 
     373             :    testset:
     374             :       nsize: {{1 2}}
     375             :       args: -nep_nev 3 -nep_tol 1e-8 -terse
     376             :       filter: sed -e "s/[+-]0\.0*i//g"
     377             :       requires: !single
     378             :       test:
     379             :          suffix: 1
     380             :          args: -nep_nleigs_locking 0 -nep_nleigs_interpolation_degree 90 -nep_nleigs_interpolation_tol 1e-8 -nep_nleigs_restart 0.4
     381             :       test:
     382             :          suffix: 2
     383             :          args: -split 0
     384             : 
     385             : TEST*/

Generated by: LCOV version 1.14