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[] = "Tests the case when both arguments of MFNSolve() are the same Vec.\n\n"
12 : "The command line options are:\n"
13 : " -t <sval>, where <sval> = scalar value that multiplies the argument.\n"
14 : " -n <n>, where <n> = number of grid subdivisions in x dimension.\n"
15 : " -m <m>, where <m> = number of grid subdivisions in y dimension.\n\n";
16 :
17 : #include <slepcmfn.h>
18 :
19 3 : int main(int argc,char **argv)
20 : {
21 3 : Mat A; /* problem matrix */
22 3 : MFN mfn;
23 3 : FN f;
24 3 : PetscReal norm;
25 3 : PetscScalar t=0.3;
26 3 : PetscInt N,n=25,m,Istart,Iend,II,i,j;
27 3 : PetscBool flag;
28 3 : Vec v,y;
29 :
30 3 : PetscFunctionBeginUser;
31 3 : PetscCall(SlepcInitialize(&argc,&argv,NULL,help));
32 :
33 3 : PetscCall(PetscOptionsGetInt(NULL,NULL,"-n",&n,NULL));
34 3 : PetscCall(PetscOptionsGetInt(NULL,NULL,"-m",&m,&flag));
35 3 : if (!flag) m=n;
36 3 : N = n*m;
37 3 : PetscCall(PetscOptionsGetScalar(NULL,NULL,"-t",&t,NULL));
38 3 : PetscCall(PetscPrintf(PETSC_COMM_WORLD,"\nMatrix exponential y=exp(t*A)*e, of the 2-D Laplacian, N=%" PetscInt_FMT " (%" PetscInt_FMT "x%" PetscInt_FMT " grid)\n\n",N,n,m));
39 :
40 : /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
41 : Build the 2-D Laplacian
42 : - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
43 :
44 3 : PetscCall(MatCreate(PETSC_COMM_WORLD,&A));
45 3 : PetscCall(MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,N,N));
46 3 : PetscCall(MatSetFromOptions(A));
47 :
48 3 : PetscCall(MatGetOwnershipRange(A,&Istart,&Iend));
49 1878 : for (II=Istart;II<Iend;II++) {
50 1875 : i = II/n; j = II-i*n;
51 1875 : if (i>0) PetscCall(MatSetValue(A,II,II-n,-1.0,INSERT_VALUES));
52 1875 : if (i<m-1) PetscCall(MatSetValue(A,II,II+n,-1.0,INSERT_VALUES));
53 1875 : if (j>0) PetscCall(MatSetValue(A,II,II-1,-1.0,INSERT_VALUES));
54 1875 : if (j<n-1) PetscCall(MatSetValue(A,II,II+1,-1.0,INSERT_VALUES));
55 1875 : PetscCall(MatSetValue(A,II,II,4.0,INSERT_VALUES));
56 : }
57 :
58 3 : PetscCall(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY));
59 3 : PetscCall(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY));
60 :
61 : /* set v = ones(n,1) */
62 3 : PetscCall(MatCreateVecs(A,&v,&y));
63 3 : PetscCall(VecSet(v,1.0));
64 :
65 : /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
66 : Create the solver and set various options
67 : - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
68 :
69 3 : PetscCall(FNCreate(PETSC_COMM_WORLD,&f));
70 3 : PetscCall(FNSetType(f,FNEXP));
71 :
72 3 : PetscCall(MFNCreate(PETSC_COMM_WORLD,&mfn));
73 3 : PetscCall(MFNSetOperator(mfn,A));
74 3 : PetscCall(MFNSetFN(mfn,f));
75 3 : PetscCall(MFNSetErrorIfNotConverged(mfn,PETSC_TRUE));
76 3 : PetscCall(MFNSetFromOptions(mfn));
77 :
78 : /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
79 : Solve the problem, y=exp(t*A)*v
80 : - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
81 :
82 3 : PetscCall(FNSetScale(f,t,1.0));
83 3 : PetscCall(MFNSolve(mfn,v,y));
84 3 : PetscCall(VecNorm(y,NORM_2,&norm));
85 3 : PetscCall(PetscPrintf(PETSC_COMM_WORLD," Computed vector at time t=%.4g has norm %g\n\n",(double)PetscRealPart(t),(double)norm));
86 :
87 : /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
88 : Repeat the computation in two steps, overwriting v:
89 : v=exp(0.5*t*A)*v, v=exp(0.5*t*A)*v
90 : - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
91 :
92 3 : PetscCall(FNSetScale(f,0.5*t,1.0));
93 3 : PetscCall(MFNSolve(mfn,v,v));
94 3 : PetscCall(MFNSolve(mfn,v,v));
95 : /* compute norm of difference */
96 3 : PetscCall(VecAXPY(y,-1.0,v));
97 3 : PetscCall(VecNorm(y,NORM_2,&norm));
98 3 : if (norm<100*PETSC_MACHINE_EPSILON) PetscCall(PetscPrintf(PETSC_COMM_WORLD," The norm of the difference is <100*eps\n\n"));
99 0 : else PetscCall(PetscPrintf(PETSC_COMM_WORLD," The norm of the difference is %g\n\n",(double)norm));
100 :
101 : /*
102 : Free work space
103 : */
104 3 : PetscCall(MFNDestroy(&mfn));
105 3 : PetscCall(FNDestroy(&f));
106 3 : PetscCall(MatDestroy(&A));
107 3 : PetscCall(VecDestroy(&v));
108 3 : PetscCall(VecDestroy(&y));
109 3 : PetscCall(SlepcFinalize());
110 : return 0;
111 : }
112 :
113 : /*TEST
114 :
115 : testset:
116 : args: -mfn_type {{krylov expokit}}
117 : output_file: output/test2_1.out
118 : test:
119 : suffix: 1
120 : test:
121 : suffix: 1_cuda
122 : args: -mat_type aijcusparse
123 : requires: cuda
124 : test:
125 : suffix: 1_hip
126 : args: -mat_type aijhipsparse
127 : requires: hip
128 :
129 : test:
130 : suffix: 3
131 : args: -mfn_type expokit -t 0.6 -mfn_ncv 24
132 : requires: !__float128
133 :
134 : TEST*/
|