GCC Code Coverage Report


Directory: ./
File: src/eps/tutorials/ex29.c
Date: 2026-02-22 03:58:10
Exec Total Coverage
Lines: 71 73 97.3%
Functions: 3 3 100.0%
Branches: 176 292 60.3%

Line Branch Exec Source
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[] = "Solves the same problem as in ex5, with a user-defined stopping test.\n\n"
12 "It is a standard nonsymmetric eigenproblem with real eigenvalues and the rightmost eigenvalue is known to be 1.\n"
13 "This example illustrates how the user can set a custom stopping test function.\n\n"
14 "The command line options are:\n"
15 " -m <m>, where <m> = number of grid subdivisions in each dimension.\n"
16 " -seconds <s>, where <s> = maximum time in seconds allowed for computation.\n\n";
17
18 #include <slepceps.h>
19 #include <petsctime.h>
20
21 /*
22 User-defined routines
23 */
24
25 PetscErrorCode MyStoppingTest(EPS,PetscInt,PetscInt,PetscInt,PetscInt,EPSConvergedReason*,void*);
26 PetscErrorCode MatMarkovModel(PetscInt,Mat);
27
28 8 int main(int argc,char **argv)
29 {
30 8 Mat A; /* operator matrix */
31 8 EPS eps; /* eigenproblem solver context */
32 8 PetscReal seconds=2.5; /* maximum time allowed for computation */
33 8 PetscLogDouble deadline; /* time to abort computation */
34 8 PetscInt N,m=15,nconv;
35 8 PetscBool terse;
36 8 PetscViewer viewer;
37 8 EPSConvergedReason reason;
38
39
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
8 PetscFunctionBeginUser;
40
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
8 PetscCall(SlepcInitialize(&argc,&argv,NULL,help));
41
42
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
8 PetscCall(PetscOptionsGetInt(NULL,NULL,"-m",&m,NULL));
43 8 N = m*(m+1)/2;
44
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
8 PetscCall(PetscPrintf(PETSC_COMM_WORLD,"\nMarkov Model, N=%" PetscInt_FMT " (m=%" PetscInt_FMT ")\n",N,m));
45
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
8 PetscCall(PetscOptionsGetReal(NULL,NULL,"-seconds",&seconds,NULL));
46
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
8 PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Maximum time for computation is set to %g seconds.\n\n",(double)seconds));
47 8 deadline = seconds;
48
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
8 PetscCall(PetscTimeAdd(&deadline));
49
50 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
51 Compute the operator matrix that defines the eigensystem, Ax=kx
52 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
53
54
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
8 PetscCall(MatCreate(PETSC_COMM_WORLD,&A));
55
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
8 PetscCall(MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,N,N));
56
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
8 PetscCall(MatSetFromOptions(A));
57
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
8 PetscCall(MatMarkovModel(m,A));
58
59 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
60 Create the eigensolver and set various options
61 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
62
63
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
8 PetscCall(EPSCreate(PETSC_COMM_WORLD,&eps));
64
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
8 PetscCall(EPSSetOperators(eps,A,NULL));
65
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
8 PetscCall(EPSSetProblemType(eps,EPS_NHEP));
66
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
8 PetscCall(EPSSetStoppingTestFunction(eps,MyStoppingTest,&deadline,NULL));
67
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
8 PetscCall(EPSSetFromOptions(eps));
68
69 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
70 Solve the eigensystem
71 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
72
73
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
8 PetscCall(EPSSolve(eps));
74
75 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
76 Display solution and clean up
77 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
78
79 /* show detailed info unless -terse option is given by user */
80
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
8 PetscCall(PetscOptionsHasName(NULL,NULL,"-terse",&terse));
81
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
8 if (terse) PetscCall(EPSErrorView(eps,EPS_ERROR_RELATIVE,NULL));
82 else {
83
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
8 PetscCall(PetscViewerASCIIGetStdout(PETSC_COMM_WORLD,&viewer));
84
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
8 PetscCall(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO_DETAIL));
85
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
8 PetscCall(EPSGetConvergedReason(eps,&reason));
86
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
8 if (reason!=EPS_CONVERGED_USER) {
87 PetscCall(EPSConvergedReasonView(eps,viewer));
88 PetscCall(EPSErrorView(eps,EPS_ERROR_RELATIVE,viewer));
89 } else {
90
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
8 PetscCall(EPSGetConverged(eps,&nconv));
91
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
8 PetscCall(PetscViewerASCIIPrintf(viewer,"Eigensolve finished with %" PetscInt_FMT " converged eigenpairs; reason=%s\n",nconv,EPSConvergedReasons[reason]));
92 }
93
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
8 PetscCall(PetscViewerPopFormat(viewer));
94 }
95
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
8 PetscCall(EPSDestroy(&eps));
96
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
8 PetscCall(MatDestroy(&A));
97
2/6
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
8 PetscCall(SlepcFinalize());
98 return 0;
99 }
100
101 /*
102 Matrix generator for a Markov model of a random walk on a triangular grid.
103
104 This subroutine generates a test matrix that models a random walk on a
105 triangular grid. This test example was used by G. W. Stewart ["{SRRIT} - a
106 FORTRAN subroutine to calculate the dominant invariant subspaces of a real
107 matrix", Tech. report. TR-514, University of Maryland (1978).] and in a few
108 papers on eigenvalue problems by Y. Saad [see e.g. LAA, vol. 34, pp. 269-295
109 (1980) ]. These matrices provide reasonably easy test problems for eigenvalue
110 algorithms. The transpose of the matrix is stochastic and so it is known
111 that one is an exact eigenvalue. One seeks the eigenvector of the transpose
112 associated with the eigenvalue unity. The problem is to calculate the steady
113 state probability distribution of the system, which is the eigevector
114 associated with the eigenvalue one and scaled in such a way that the sum all
115 the components is equal to one.
116
117 Note: the code will actually compute the transpose of the stochastic matrix
118 that contains the transition probabilities.
119 */
120 8 PetscErrorCode MatMarkovModel(PetscInt m,Mat A)
121 {
122 8 const PetscReal cst = 0.5/(PetscReal)(m-1);
123 8 PetscReal pd,pu;
124 8 PetscInt Istart,Iend,i,j,jmax,ix=0;
125
126
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
8 PetscFunctionBeginUser;
127
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
8 PetscCall(MatGetOwnershipRange(A,&Istart,&Iend));
128
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
2808 for (i=1;i<=m;i++) {
129 2800 jmax = m-i+1;
130
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
494200 for (j=1;j<=jmax;j++) {
131 491400 ix = ix + 1;
132
2/4
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
491400 if (ix-1<Istart || ix>Iend) continue; /* compute only owned rows */
133
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
491400 if (j!=jmax) {
134 488600 pd = cst*(PetscReal)(i+j-1);
135 /* north */
136
6/8
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
488600 if (i==1) PetscCall(MatSetValue(A,ix-1,ix,2*pd,INSERT_VALUES));
137
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
485808 else PetscCall(MatSetValue(A,ix-1,ix,pd,INSERT_VALUES));
138 /* east */
139
6/8
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
488600 if (j==1) PetscCall(MatSetValue(A,ix-1,ix+jmax-1,2*pd,INSERT_VALUES));
140
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
485808 else PetscCall(MatSetValue(A,ix-1,ix+jmax-1,pd,INSERT_VALUES));
141 }
142 /* south */
143 491400 pu = 0.5 - cst*(PetscReal)(i+j-3);
144
6/8
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
491400 if (j>1) PetscCall(MatSetValue(A,ix-1,ix-2,pu,INSERT_VALUES));
145 /* west */
146
6/8
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
491400 if (i>1) PetscCall(MatSetValue(A,ix-1,ix-jmax-2,pu,INSERT_VALUES));
147 }
148 }
149
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
8 PetscCall(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY));
150
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
8 PetscCall(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY));
151
5/12
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
2 PetscFunctionReturn(PETSC_SUCCESS);
152 }
153
154 /*
155 Function for user-defined stopping test.
156
157 Checks that the computing time has not exceeded the deadline.
158 */
159 462 PetscErrorCode MyStoppingTest(EPS eps,PetscInt its,PetscInt max_it,PetscInt nconv,PetscInt nev,EPSConvergedReason *reason,void *ctx)
160 {
161 462 PetscLogDouble now,deadline = *(PetscLogDouble*)ctx;
162
163
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
462 PetscFunctionBeginUser;
164 /* check if usual termination conditions are met */
165
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
462 PetscCall(EPSStoppingBasic(eps,its,max_it,nconv,nev,reason,NULL));
166
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
462 if (*reason==EPS_CONVERGED_ITERATING) {
167 /* check if deadline has expired */
168
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
462 PetscCall(PetscTime(&now));
169
2/2
✓ Branch 0 taken 8 times.
✓ Branch 1 taken 8 times.
462 if (now>deadline) *reason = EPS_CONVERGED_USER;
170 }
171
5/12
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 2 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 10 not taken.
✗ Branch 11 not taken.
210 PetscFunctionReturn(PETSC_SUCCESS);
172 }
173
174 /*TEST
175
176 test:
177 suffix: 1
178 args: -m 350 -seconds 0.6
179 requires: !single
180
181 TEST*/
182