GCC Code Coverage Report


Directory: ./
File: src/eps/tutorials/ex29.c
Date: 2025-10-03 04:28:47
Exec Total Coverage
Lines: 71 73 97.3%
Functions: 3 3 100.0%
Branches: 177 292 60.6%

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 10 int main(int argc,char **argv)
29 {
30 10 Mat A; /* operator matrix */
31 10 EPS eps; /* eigenproblem solver context */
32 10 PetscReal seconds=2.5; /* maximum time allowed for computation */
33 10 PetscLogDouble deadline; /* time to abort computation */
34 10 PetscInt N,m=15,nconv;
35 10 PetscBool terse;
36 10 PetscViewer viewer;
37 10 EPSConvergedReason reason;
38
39
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
10 PetscFunctionBeginUser;
40
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
10 PetscCall(SlepcInitialize(&argc,&argv,NULL,help));
41
42
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
10 PetscCall(PetscOptionsGetInt(NULL,NULL,"-m",&m,NULL));
43 10 N = m*(m+1)/2;
44
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
10 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 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
10 PetscCall(PetscOptionsGetReal(NULL,NULL,"-seconds",&seconds,NULL));
46
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
10 PetscCall(PetscPrintf(PETSC_COMM_WORLD,"Maximum time for computation is set to %g seconds.\n\n",(double)seconds));
47 10 deadline = seconds;
48
2/4
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
10 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 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
10 PetscCall(MatCreate(PETSC_COMM_WORLD,&A));
55
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
10 PetscCall(MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,N,N));
56
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
10 PetscCall(MatSetFromOptions(A));
57
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
10 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 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
10 PetscCall(EPSCreate(PETSC_COMM_WORLD,&eps));
64
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
10 PetscCall(EPSSetOperators(eps,A,NULL));
65
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
10 PetscCall(EPSSetProblemType(eps,EPS_NHEP));
66
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
10 PetscCall(EPSSetStoppingTestFunction(eps,MyStoppingTest,&deadline,NULL));
67
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
10 PetscCall(EPSSetFromOptions(eps));
68
69 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
70 Solve the eigensystem
71 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
72
73
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
10 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 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
10 PetscCall(PetscOptionsHasName(NULL,NULL,"-terse",&terse));
81
1/8
✗ Branch 0 not taken.
✓ Branch 1 taken 10 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.
10 if (terse) PetscCall(EPSErrorView(eps,EPS_ERROR_RELATIVE,NULL));
82 else {
83
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
10 PetscCall(PetscViewerASCIIGetStdout(PETSC_COMM_WORLD,&viewer));
84
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
10 PetscCall(PetscViewerPushFormat(viewer,PETSC_VIEWER_ASCII_INFO_DETAIL));
85
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
10 PetscCall(EPSGetConvergedReason(eps,&reason));
86
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
10 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 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
10 PetscCall(EPSGetConverged(eps,&nconv));
91
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
10 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 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
10 PetscCall(PetscViewerPopFormat(viewer));
94 }
95
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
10 PetscCall(EPSDestroy(&eps));
96
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
10 PetscCall(MatDestroy(&A));
97
3/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
10 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 10 PetscErrorCode MatMarkovModel(PetscInt m,Mat A)
121 {
122 10 const PetscReal cst = 0.5/(PetscReal)(m-1);
123 10 PetscReal pd,pu;
124 10 PetscInt Istart,Iend,i,j,jmax,ix=0;
125
126
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
10 PetscFunctionBeginUser;
127
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
10 PetscCall(MatGetOwnershipRange(A,&Istart,&Iend));
128
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
3510 for (i=1;i<=m;i++) {
129 3500 jmax = m-i+1;
130
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
617750 for (j=1;j<=jmax;j++) {
131 614250 ix = ix + 1;
132
2/4
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
614250 if (ix-1<Istart || ix>Iend) continue; /* compute only owned rows */
133
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
614250 if (j!=jmax) {
134 610750 pd = cst*(PetscReal)(i+j-1);
135 /* north */
136
6/8
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
610750 if (i==1) PetscCall(MatSetValue(A,ix-1,ix,2*pd,INSERT_VALUES));
137
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
607260 else PetscCall(MatSetValue(A,ix-1,ix,pd,INSERT_VALUES));
138 /* east */
139
6/8
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
610750 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 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
607260 else PetscCall(MatSetValue(A,ix-1,ix+jmax-1,pd,INSERT_VALUES));
141 }
142 /* south */
143 614250 pu = 0.5 - cst*(PetscReal)(i+j-3);
144
6/8
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
614250 if (j>1) PetscCall(MatSetValue(A,ix-1,ix-2,pu,INSERT_VALUES));
145 /* west */
146
6/8
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 8 times.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✓ Branch 7 taken 2 times.
614250 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 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
10 PetscCall(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY));
150
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
10 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 540 PetscErrorCode MyStoppingTest(EPS eps,PetscInt its,PetscInt max_it,PetscInt nconv,PetscInt nev,EPSConvergedReason *reason,void *ctx)
160 {
161 540 PetscLogDouble now,deadline = *(PetscLogDouble*)ctx;
162
163
1/2
✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
540 PetscFunctionBeginUser;
164 /* check if usual termination conditions are met */
165
4/6
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
540 PetscCall(EPSStoppingBasic(eps,its,max_it,nconv,nev,reason,NULL));
166
1/2
✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
540 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.
540 PetscCall(PetscTime(&now));
169
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
540 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.
51 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