LCOV - code coverage report
Current view: top level - nep/tutorials - ex27.c (source / functions) Hit Total Coverage
Test: SLEPc Lines: 101 115 87.8 %
Date: 2024-12-18 00:42:09 Functions: 3 4 75.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[] = "Simple nonlinear eigenproblem using the NLEIGS solver.\n\n"
      12             :   "The command line options are:\n"
      13             :   "  -n <n>, where <n> = matrix dimension.\n"
      14             :   "  -split <0/1>, to select the split form in the problem definition (enabled by default)\n";
      15             : 
      16             : /*
      17             :    Solve T(lambda)x=0 using NLEIGS solver
      18             :       with T(lambda) = -D+sqrt(lambda)*I
      19             :       where D is the Laplacian operator in 1 dimension
      20             :       and with the interpolation interval [.01,16]
      21             : */
      22             : 
      23             : #include <slepcnep.h>
      24             : 
      25             : /*
      26             :    User-defined routines
      27             : */
      28             : PetscErrorCode FormFunction(NEP,PetscScalar,Mat,Mat,void*);
      29             : PetscErrorCode FormJacobian(NEP,PetscScalar,Mat,void*);
      30             : PetscErrorCode ComputeSingularities(NEP,PetscInt*,PetscScalar*,void*);
      31             : 
      32           5 : int main(int argc,char **argv)
      33             : {
      34           5 :   NEP            nep;             /* nonlinear eigensolver context */
      35           5 :   Mat            F,J,A[2];
      36           5 :   NEPType        type;
      37           5 :   PetscInt       n=100,nev,Istart,Iend,i;
      38           5 :   PetscBool      terse,split=PETSC_TRUE;
      39           5 :   RG             rg;
      40           5 :   FN             f[2];
      41           5 :   PetscScalar    coeffs;
      42             : 
      43           5 :   PetscFunctionBeginUser;
      44           5 :   PetscCall(SlepcInitialize(&argc,&argv,NULL,help));
      45           5 :   PetscCall(PetscOptionsGetInt(NULL,NULL,"-n",&n,NULL));
      46           5 :   PetscCall(PetscOptionsGetBool(NULL,NULL,"-split",&split,NULL));
      47           7 :   PetscCall(PetscPrintf(PETSC_COMM_WORLD,"\nSquare root eigenproblem, n=%" PetscInt_FMT "%s\n\n",n,split?" (in split form)":""));
      48             : 
      49             :   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      50             :      Create nonlinear eigensolver context
      51             :      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
      52             : 
      53           5 :   PetscCall(NEPCreate(PETSC_COMM_WORLD,&nep));
      54             : 
      55             :   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      56             :      Select the NLEIGS solver and set required options for it
      57             :      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
      58             : 
      59           5 :   PetscCall(NEPSetType(nep,NEPNLEIGS));
      60           5 :   PetscCall(NEPNLEIGSSetSingularitiesFunction(nep,ComputeSingularities,NULL));
      61           5 :   PetscCall(NEPGetRG(nep,&rg));
      62           5 :   PetscCall(RGSetType(rg,RGINTERVAL));
      63             : #if defined(PETSC_USE_COMPLEX)
      64             :   PetscCall(RGIntervalSetEndpoints(rg,0.01,16.0,-0.001,0.001));
      65             : #else
      66           5 :   PetscCall(RGIntervalSetEndpoints(rg,0.01,16.0,0,0));
      67             : #endif
      68           5 :   PetscCall(NEPSetTarget(nep,1.1));
      69             : 
      70             :   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
      71             :      Define the nonlinear problem
      72             :      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
      73             : 
      74           5 :   if (split) {
      75             :     /*
      76             :        Create matrices for the split form
      77             :     */
      78           3 :     PetscCall(MatCreate(PETSC_COMM_WORLD,&A[0]));
      79           3 :     PetscCall(MatSetSizes(A[0],PETSC_DECIDE,PETSC_DECIDE,n,n));
      80           3 :     PetscCall(MatSetFromOptions(A[0]));
      81           3 :     PetscCall(MatGetOwnershipRange(A[0],&Istart,&Iend));
      82         223 :     for (i=Istart;i<Iend;i++) {
      83         220 :       if (i>0) PetscCall(MatSetValue(A[0],i,i-1,1.0,INSERT_VALUES));
      84         220 :       if (i<n-1) PetscCall(MatSetValue(A[0],i,i+1,1.0,INSERT_VALUES));
      85         220 :       PetscCall(MatSetValue(A[0],i,i,-2.0,INSERT_VALUES));
      86             :     }
      87           3 :     PetscCall(MatAssemblyBegin(A[0],MAT_FINAL_ASSEMBLY));
      88           3 :     PetscCall(MatAssemblyEnd(A[0],MAT_FINAL_ASSEMBLY));
      89             : 
      90           3 :     PetscCall(MatCreateConstantDiagonal(PETSC_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,n,n,1.0,&A[1]));
      91             : 
      92             :     /*
      93             :        Define functions for the split form
      94             :      */
      95           3 :     PetscCall(FNCreate(PETSC_COMM_WORLD,&f[0]));
      96           3 :     PetscCall(FNSetType(f[0],FNRATIONAL));
      97           3 :     coeffs = 1.0;
      98           3 :     PetscCall(FNRationalSetNumerator(f[0],1,&coeffs));
      99           3 :     PetscCall(FNCreate(PETSC_COMM_WORLD,&f[1]));
     100           3 :     PetscCall(FNSetType(f[1],FNSQRT));
     101           3 :     PetscCall(NEPSetSplitOperator(nep,2,A,f,SUBSET_NONZERO_PATTERN));
     102             : 
     103             :   } else {
     104             :     /*
     105             :        Callback form: create matrix and set Function evaluation routine
     106             :      */
     107           2 :     PetscCall(MatCreate(PETSC_COMM_WORLD,&F));
     108           2 :     PetscCall(MatSetSizes(F,PETSC_DECIDE,PETSC_DECIDE,n,n));
     109           2 :     PetscCall(MatSetFromOptions(F));
     110           2 :     PetscCall(MatSeqAIJSetPreallocation(F,3,NULL));
     111           2 :     PetscCall(MatMPIAIJSetPreallocation(F,3,NULL,1,NULL));
     112           2 :     PetscCall(NEPSetFunction(nep,F,F,FormFunction,NULL));
     113             : 
     114           2 :     PetscCall(MatCreate(PETSC_COMM_WORLD,&J));
     115           2 :     PetscCall(MatSetSizes(J,PETSC_DECIDE,PETSC_DECIDE,n,n));
     116           2 :     PetscCall(MatSetFromOptions(J));
     117           2 :     PetscCall(MatSeqAIJSetPreallocation(J,1,NULL));
     118           2 :     PetscCall(MatMPIAIJSetPreallocation(J,1,NULL,1,NULL));
     119           2 :     PetscCall(NEPSetJacobian(nep,J,FormJacobian,NULL));
     120             :   }
     121             : 
     122             :   /*
     123             :      Set solver parameters at runtime
     124             :   */
     125           5 :   PetscCall(NEPSetFromOptions(nep));
     126             : 
     127             :   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     128             :                       Solve the eigensystem
     129             :      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     130           5 :   PetscCall(NEPSolve(nep));
     131           5 :   PetscCall(NEPGetType(nep,&type));
     132           5 :   PetscCall(PetscPrintf(PETSC_COMM_WORLD," Solution method: %s\n",type));
     133           5 :   PetscCall(NEPGetDimensions(nep,&nev,NULL,NULL));
     134           5 :   PetscCall(PetscPrintf(PETSC_COMM_WORLD," Number of requested eigenvalues: %" PetscInt_FMT "\n",nev));
     135             : 
     136             :   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     137             :                     Display solution and clean up
     138             :      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     139             : 
     140             :   /* show detailed info unless -terse option is given by user */
     141           5 :   PetscCall(PetscOptionsHasName(NULL,NULL,"-terse",&terse));
     142           5 :   if (terse) PetscCall(NEPErrorView(nep,NEP_ERROR_BACKWARD,NULL));
     143             :   else {
     144           0 :     PetscCall(PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD,PETSC_VIEWER_ASCII_INFO_DETAIL));
     145           0 :     PetscCall(NEPConvergedReasonView(nep,PETSC_VIEWER_STDOUT_WORLD));
     146           0 :     PetscCall(NEPErrorView(nep,NEP_ERROR_BACKWARD,PETSC_VIEWER_STDOUT_WORLD));
     147           0 :     PetscCall(PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD));
     148             :   }
     149           5 :   PetscCall(NEPDestroy(&nep));
     150           5 :   if (split) {
     151           3 :     PetscCall(MatDestroy(&A[0]));
     152           3 :     PetscCall(MatDestroy(&A[1]));
     153           3 :     PetscCall(FNDestroy(&f[0]));
     154           3 :     PetscCall(FNDestroy(&f[1]));
     155             :   } else {
     156           2 :     PetscCall(MatDestroy(&F));
     157           2 :     PetscCall(MatDestroy(&J));
     158             :   }
     159           5 :   PetscCall(SlepcFinalize());
     160             :   return 0;
     161             : }
     162             : 
     163             : /* ------------------------------------------------------------------- */
     164             : /*
     165             :    FormFunction - Computes Function matrix  T(lambda)
     166             : */
     167          55 : PetscErrorCode FormFunction(NEP nep,PetscScalar lambda,Mat fun,Mat B,void *ctx)
     168             : {
     169          55 :   PetscInt       i,n,col[3],Istart,Iend;
     170          55 :   PetscBool      FirstBlock=PETSC_FALSE,LastBlock=PETSC_FALSE;
     171          55 :   PetscScalar    value[3],t;
     172             : 
     173          55 :   PetscFunctionBeginUser;
     174             :   /*
     175             :      Compute Function entries and insert into matrix
     176             :   */
     177          55 :   t = PetscSqrtScalar(lambda);
     178          55 :   PetscCall(MatGetSize(fun,&n,NULL));
     179          55 :   PetscCall(MatGetOwnershipRange(fun,&Istart,&Iend));
     180          55 :   if (Istart==0) FirstBlock=PETSC_TRUE;
     181          55 :   if (Iend==n) LastBlock=PETSC_TRUE;
     182          55 :   value[0]=1.0; value[1]=t-2.0; value[2]=1.0;
     183        5445 :   for (i=(FirstBlock? Istart+1: Istart); i<(LastBlock? Iend-1: Iend); i++) {
     184        5390 :     col[0]=i-1; col[1]=i; col[2]=i+1;
     185        5390 :     PetscCall(MatSetValues(fun,1,&i,3,col,value,INSERT_VALUES));
     186             :   }
     187          55 :   if (LastBlock) {
     188          55 :     i=n-1; col[0]=n-2; col[1]=n-1;
     189          55 :     PetscCall(MatSetValues(fun,1,&i,2,col,value,INSERT_VALUES));
     190             :   }
     191          55 :   if (FirstBlock) {
     192          55 :     i=0; col[0]=0; col[1]=1; value[0]=t-2.0; value[1]=1.0;
     193          55 :     PetscCall(MatSetValues(fun,1,&i,2,col,value,INSERT_VALUES));
     194             :   }
     195             : 
     196             :   /*
     197             :      Assemble matrix
     198             :   */
     199          55 :   PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
     200          55 :   PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
     201          55 :   if (fun != B) {
     202           0 :     PetscCall(MatAssemblyBegin(fun,MAT_FINAL_ASSEMBLY));
     203           0 :     PetscCall(MatAssemblyEnd(fun,MAT_FINAL_ASSEMBLY));
     204             :   }
     205          55 :   PetscFunctionReturn(PETSC_SUCCESS);
     206             : }
     207             : 
     208             : /* ------------------------------------------------------------------- */
     209             : /*
     210             :    FormJacobian - Computes Jacobian matrix  T'(lambda)
     211             : */
     212           0 : PetscErrorCode FormJacobian(NEP nep,PetscScalar lambda,Mat jac,void *ctx)
     213             : {
     214           0 :   Vec            d;
     215             : 
     216           0 :   PetscFunctionBeginUser;
     217           0 :   PetscCall(MatCreateVecs(jac,&d,NULL));
     218           0 :   PetscCall(VecSet(d,0.5/PetscSqrtScalar(lambda)));
     219           0 :   PetscCall(MatDiagonalSet(jac,d,INSERT_VALUES));
     220           0 :   PetscCall(VecDestroy(&d));
     221           0 :   PetscFunctionReturn(PETSC_SUCCESS);
     222             : }
     223             : 
     224             : /* ------------------------------------------------------------------- */
     225             : /*
     226             :    ComputeSingularities - Computes maxnp points (at most) in the complex plane where
     227             :    the function T(.) is not analytic.
     228             : 
     229             :    In this case, we discretize the singularity region (-inf,0)~(-10e+6,-10e-6)
     230             : */
     231           5 : PetscErrorCode ComputeSingularities(NEP nep,PetscInt *maxnp,PetscScalar *xi,void *pt)
     232             : {
     233           5 :   PetscReal h;
     234           5 :   PetscInt  i;
     235             : 
     236           5 :   PetscFunctionBeginUser;
     237           5 :   h = 11.0/(*maxnp-1);
     238           5 :   xi[0] = -1e-5; xi[*maxnp-1] = -1e+6;
     239       49995 :   for (i=1;i<*maxnp-1;i++) xi[i] = -PetscPowReal(10,-5+h*i);
     240           5 :   PetscFunctionReturn(PETSC_SUCCESS);
     241             : }
     242             : 
     243             : /*TEST
     244             : 
     245             :    testset:
     246             :       args: -nep_nev 3 -terse
     247             :       output_file: output/ex27_1.out
     248             :       requires: !single
     249             :       filter: sed -e "s/[+-]0\.0*i//g"
     250             :       test:
     251             :          suffix: 1
     252             :          args: -nep_nleigs_interpolation_degree 90
     253             :       test:
     254             :          suffix: 3
     255             :          args: -nep_tol 1e-8 -nep_nleigs_rk_shifts 1.06,1.1,1.12,1.15 -nep_conv_norm -nep_nleigs_interpolation_degree 20
     256             :       test:
     257             :          suffix: 5_cuda
     258             :          args: -mat_type aijcusparse
     259             :          requires: cuda
     260             :       test:
     261             :          suffix: 5_hip
     262             :          args: -mat_type aijhipsparse
     263             :          requires: hip
     264             : 
     265             :    testset:
     266             :       args: -split 0 -nep_nev 3 -terse
     267             :       output_file: output/ex27_2.out
     268             :       filter: sed -e "s/[+-]0\.0*i//g"
     269             :       test:
     270             :          suffix: 2
     271             :          args: -nep_nleigs_interpolation_degree 90
     272             :          requires: !single
     273             :       test:
     274             :          suffix: 4
     275             :          args: -nep_nleigs_rk_shifts 1.06,1.1,1.12,1.15 -nep_nleigs_interpolation_degree 20
     276             :          requires: double
     277             :       test:
     278             :          suffix: 6_cuda
     279             :          args: -mat_type aijcusparse
     280             :          requires: cuda !single
     281             :       test:
     282             :          suffix: 6_hip
     283             :          args: -mat_type aijhipsparse
     284             :          requires: hip !single
     285             : 
     286             :    testset:
     287             :       args: -split 0 -nep_type ciss -nep_ciss_extraction {{ritz hankel caa}} -rg_type ellipse -rg_ellipse_center 8 -rg_ellipse_radius .7 -nep_ciss_moments 4 -rg_ellipse_vscale 0.1 -terse
     288             :       requires: complex !single
     289             :       output_file: output/ex27_7.out
     290             :       timeoutfactor: 2
     291             :       test:
     292             :          suffix: 7
     293             :       test:
     294             :          suffix: 7_par
     295             :          nsize: 2
     296             :          args: -nep_ciss_partitions 2
     297             : 
     298             :    testset:
     299             :       args: -nep_type ciss -rg_type ellipse -rg_ellipse_center 8 -rg_ellipse_radius .7 -rg_ellipse_vscale 0.1 -terse
     300             :       requires: complex
     301             :       filter: sed -e "s/ (in split form)//" | sed -e "s/56925/56924/" | sed -e "s/60753/60754/" | sed -e "s/92630/92629/" | sed -e "s/24705/24706/"
     302             :       output_file: output/ex27_7.out
     303             :       timeoutfactor: 2
     304             :       test:
     305             :          suffix: 8
     306             :       test:
     307             :          suffix: 8_parallel
     308             :          nsize: 4
     309             :          args: -nep_ciss_partitions 4 -ds_parallel distributed
     310             :       test:
     311             :          suffix: 8_hpddm
     312             :          args: -nep_ciss_ksp_type hpddm
     313             :          requires: hpddm
     314             : 
     315             :    test:
     316             :       suffix: 9
     317             :       args: -nep_nev 4 -n 20 -terse
     318             :       requires: !single
     319             :       filter: sed -e "s/[+-]0\.0*i//g"
     320             : 
     321             : TEST*/

Generated by: LCOV version 1.14