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

Actual source code: ex56.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: */

     11: static char help[] = "Eigenvalue problem with Hamiltonian structure.\n\n"
     12:   "The command line options are:\n"
     13:   "  -n <n>, where <n> = dimension of the blocks.\n\n";

     15: #include <slepceps.h>

     17: /*
     18:    This example computes eigenvalues of a matrix

     20:         H = [ A    B
     21:               C  -A^* ],

     23:    where B and C are Hermitian or real symmetric. In particular, A, B and C have
     24:    the following Toeplitz structure:

     26:         A = pentadiag{a,b,c,d,e}
     27:         B = tridiag{a,c,conj(a)}
     28:         C = tridiag{b,e,conj(b)}

     30:    where a,b,d are complex scalars, and c is real.
     31: */

     33: int main(int argc,char **argv)
     34: {
     35:   Mat            H,A,B,C;    /* problem matrices */
     36:   EPS            eps;        /* eigenproblem solver context */
     37:   PetscScalar    a,b,c,d,e;
     38:   PetscInt       n=24,Istart,Iend,i;
     39:   PetscBool      terse;

     41:   PetscFunctionBeginUser;
     42:   PetscCall(SlepcInitialize(&argc,&argv,(char*)0,help));

     44:   PetscCall(PetscOptionsGetInt(NULL,NULL,"-n",&n,NULL));
     45:   PetscCall(PetscPrintf(PETSC_COMM_WORLD,"\nHamiltonian eigenproblem, n=%" PetscInt_FMT "\n\n",n));

     47:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
     48:                Compute the problem matrices R and C
     49:      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

     51: #if defined(PETSC_USE_COMPLEX)
     52:   a = PetscCMPLX(-0.1,0.2);
     53:   b = PetscCMPLX(1.0,0.5);
     54:   d = PetscCMPLX(2.0,0.2);
     55: #else
     56:   a = -0.1;
     57:   b = 1.0;
     58:   d = 2.0;
     59: #endif
     60:   c = 4.5;
     61:   e = -2.5;

     63:   PetscCall(MatCreate(PETSC_COMM_WORLD,&A));
     64:   PetscCall(MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,n,n));
     65:   PetscCall(MatSetFromOptions(A));

     67:   PetscCall(MatCreate(PETSC_COMM_WORLD,&B));
     68:   PetscCall(MatSetSizes(B,PETSC_DECIDE,PETSC_DECIDE,n,n));
     69:   PetscCall(MatSetFromOptions(B));

     71:   PetscCall(MatCreate(PETSC_COMM_WORLD,&C));
     72:   PetscCall(MatSetSizes(C,PETSC_DECIDE,PETSC_DECIDE,n,n));
     73:   PetscCall(MatSetFromOptions(C));

     75:   PetscCall(MatGetOwnershipRange(A,&Istart,&Iend));
     76:   for (i=Istart;i<Iend;i++) {
     77:     if (i>1) PetscCall(MatSetValue(A,i,i-2,a,INSERT_VALUES));
     78:     if (i>0) PetscCall(MatSetValue(A,i,i-1,b,INSERT_VALUES));
     79:     PetscCall(MatSetValue(A,i,i,c,INSERT_VALUES));
     80:     if (i<n-1) PetscCall(MatSetValue(A,i,i+1,d,INSERT_VALUES));
     81:     if (i<n-2) PetscCall(MatSetValue(A,i,i+2,e,INSERT_VALUES));
     82:   }

     84:   PetscCall(MatGetOwnershipRange(B,&Istart,&Iend));
     85:   for (i=Istart;i<Iend;i++) {
     86:     if (i>0) PetscCall(MatSetValue(B,i,i-1,a,INSERT_VALUES));
     87:     PetscCall(MatSetValue(B,i,i,c,INSERT_VALUES));
     88:     if (i<n-1) PetscCall(MatSetValue(B,i,i+1,PetscConj(a),INSERT_VALUES));
     89:   }

     91:   PetscCall(MatGetOwnershipRange(C,&Istart,&Iend));
     92:   for (i=Istart;i<Iend;i++) {
     93:     if (i>0) PetscCall(MatSetValue(C,i,i-1,b,INSERT_VALUES));
     94:     PetscCall(MatSetValue(C,i,i,e,INSERT_VALUES));
     95:     if (i<n-1) PetscCall(MatSetValue(C,i,i+1,PetscConj(b),INSERT_VALUES));
     96:   }

     98:   PetscCall(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY));
     99:   PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
    100:   PetscCall(MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY));
    101:   PetscCall(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY));
    102:   PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
    103:   PetscCall(MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY));

    105:   PetscCall(MatCreateHamiltonian(A,B,C,&H));

    107:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    108:                 Create the eigensolver and set various options
    109:      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

    111:   PetscCall(EPSCreate(PETSC_COMM_WORLD,&eps));
    112:   PetscCall(EPSSetOperators(eps,H,NULL));
    113:   PetscCall(EPSSetProblemType(eps,EPS_HAMILT));
    114:   PetscCall(EPSSetFromOptions(eps));

    116:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    117:                  Solve the eigensystem and display solution
    118:      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

    120:   PetscCall(EPSSolve(eps));

    122:   /* show detailed info unless -terse option is given by user */
    123:   PetscCall(PetscOptionsHasName(NULL,NULL,"-terse",&terse));
    124:   if (terse) PetscCall(EPSErrorView(eps,EPS_ERROR_RELATIVE,NULL));
    125:   else {
    126:     PetscCall(PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD,PETSC_VIEWER_ASCII_INFO_DETAIL));
    127:     PetscCall(EPSConvergedReasonView(eps,PETSC_VIEWER_STDOUT_WORLD));
    128:     PetscCall(EPSErrorView(eps,EPS_ERROR_RELATIVE,PETSC_VIEWER_STDOUT_WORLD));
    129:     PetscCall(PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD));
    130:   }

    132:   PetscCall(EPSDestroy(&eps));
    133:   PetscCall(MatDestroy(&A));
    134:   PetscCall(MatDestroy(&B));
    135:   PetscCall(MatDestroy(&C));
    136:   PetscCall(MatDestroy(&H));
    137:   PetscCall(SlepcFinalize());
    138:   return 0;
    139: }

    141: /*TEST

    143:    testset:
    144:       args: -eps_nev 8 -eps_ncv 28 -terse
    145:       nsize: {{1 2}}
    146:       requires: double !complex
    147:       output_file: output/ex56_1.out
    148:       test:
    149:          suffix: 1
    150:       test:
    151:          args: -eps_non_hermitian
    152:          suffix: 1_nhep

    154:    testset:
    155:       args: -eps_nev 4 -eps_ncv 16 -terse
    156:       nsize: {{1 2}}
    157:       requires: double complex
    158:       output_file: output/ex56_1_complex.out
    159:       test:
    160:          TODO: no support for complex scalars yet
    161:          suffix: 1_complex
    162:       test:
    163:          args: -eps_non_hermitian
    164:          suffix: 1_complex_nhep

    166: TEST*/