xref: /petsc/src/mat/tests/ex132.c (revision df4cd43f92eaa320656440c40edb1046daee8f75)
1 
2 static char help[] = "Test MatAXPY()\n\n";
3 
4 #include <petscmat.h>
5 
6 int main(int argc, char **args)
7 {
8   Mat         C, C1, C2, CU;
9   PetscScalar v;
10   PetscInt    Ii, J, Istart, Iend;
11   PetscInt    i, j, m = 3, n;
12   PetscMPIInt size;
13   PetscBool   mat_nonsymmetric = PETSC_FALSE, flg;
14   MatInfo     info;
15 
16   PetscFunctionBeginUser;
17   PetscCall(PetscInitialize(&argc, &args, (char *)0, help));
18   PetscCall(PetscOptionsGetInt(NULL, NULL, "-m", &m, NULL));
19   PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
20   n = 2 * size;
21 
22   /* Set flag if we are doing a nonsymmetric problem; the default is symmetric. */
23   PetscCall(PetscOptionsGetBool(NULL, NULL, "-mat_nonsym", &mat_nonsymmetric, NULL));
24 
25   PetscCall(MatCreate(PETSC_COMM_WORLD, &C));
26   PetscCall(MatSetSizes(C, PETSC_DECIDE, PETSC_DECIDE, m * n, m * n));
27   PetscCall(MatSetFromOptions(C));
28   PetscCall(MatSeqAIJSetPreallocation(C, 5, NULL));
29   PetscCall(MatMPIAIJSetPreallocation(C, 5, NULL, 5, NULL));
30 
31   PetscCall(MatGetOwnershipRange(C, &Istart, &Iend));
32   for (Ii = Istart; Ii < Iend; Ii++) {
33     v = -1.0;
34     i = Ii / n;
35     j = Ii - i * n;
36     if (i > 0) {
37       J = Ii - n;
38       PetscCall(MatSetValues(C, 1, &Ii, 1, &J, &v, ADD_VALUES));
39     }
40     if (i < m - 1) {
41       J = Ii + n;
42       PetscCall(MatSetValues(C, 1, &Ii, 1, &J, &v, ADD_VALUES));
43     }
44     if (j > 0) {
45       J = Ii - 1;
46       PetscCall(MatSetValues(C, 1, &Ii, 1, &J, &v, ADD_VALUES));
47     }
48     if (j < n - 1) {
49       J = Ii + 1;
50       PetscCall(MatSetValues(C, 1, &Ii, 1, &J, &v, ADD_VALUES));
51     }
52     v = 4.0;
53     PetscCall(MatSetValues(C, 1, &Ii, 1, &Ii, &v, ADD_VALUES));
54   }
55 
56   /* Make the matrix nonsymmetric if desired */
57   if (mat_nonsymmetric) {
58     for (Ii = Istart; Ii < Iend; Ii++) {
59       v = -1.5;
60       i = Ii / n;
61       if (i > 1) {
62         J = Ii - n - 1;
63         PetscCall(MatSetValues(C, 1, &Ii, 1, &J, &v, ADD_VALUES));
64       }
65     }
66   } else {
67     PetscCall(MatSetOption(C, MAT_SYMMETRIC, PETSC_TRUE));
68     PetscCall(MatSetOption(C, MAT_SYMMETRY_ETERNAL, PETSC_TRUE));
69   }
70   PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY));
71   PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY));
72   PetscCall(PetscObjectSetName((PetscObject)C, "C"));
73   PetscCall(MatViewFromOptions(C, NULL, "-view"));
74 
75   /* C1 = 2.0*C1 + C, C1 is anti-diagonal and has different non-zeros than C */
76   PetscCall(MatCreate(PETSC_COMM_WORLD, &C1));
77   PetscCall(MatSetSizes(C1, PETSC_DECIDE, PETSC_DECIDE, m * n, m * n));
78   PetscCall(MatSetFromOptions(C1));
79   PetscCall(MatSeqAIJSetPreallocation(C1, 1, NULL));
80   PetscCall(MatMPIAIJSetPreallocation(C1, 1, NULL, 1, NULL));
81   for (Ii = Istart; Ii < Iend; Ii++) {
82     v = 1.0;
83     i = m * n - Ii - 1;
84     j = Ii;
85     PetscCall(MatSetValues(C1, 1, &i, 1, &j, &v, ADD_VALUES));
86   }
87   PetscCall(MatAssemblyBegin(C1, MAT_FINAL_ASSEMBLY));
88   PetscCall(MatAssemblyEnd(C1, MAT_FINAL_ASSEMBLY));
89   PetscCall(PetscObjectSetName((PetscObject)C1, "C1"));
90   PetscCall(MatViewFromOptions(C1, NULL, "-view"));
91   PetscCall(MatDuplicate(C1, MAT_COPY_VALUES, &CU));
92 
93   PetscCall(PetscPrintf(PETSC_COMM_WORLD, " MatAXPY(C1,2.0,C,DIFFERENT_NONZERO_PATTERN)...\n"));
94   PetscCall(MatAXPY(C1, 2.0, C, DIFFERENT_NONZERO_PATTERN));
95   PetscCall(MatAXPY(CU, 2.0, C, UNKNOWN_NONZERO_PATTERN));
96   PetscCall(MatGetInfo(C1, MAT_GLOBAL_SUM, &info));
97   PetscCall(PetscPrintf(PETSC_COMM_WORLD, " C1: nz_allocated = %g; nz_used = %g; nz_unneeded = %g\n", info.nz_allocated, info.nz_used, info.nz_unneeded));
98   PetscCall(MatViewFromOptions(C1, NULL, "-view"));
99   PetscCall(MatMultEqual(CU, C1, 10, &flg));
100   if (!flg) {
101     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error UNKNOWN_NONZERO_PATTERN (supposedly DIFFERENT_NONZERO_PATTERN)\n"));
102     PetscCall(MatViewFromOptions(CU, NULL, "-view"));
103   }
104   PetscCall(MatDestroy(&CU));
105 
106   /* Secondly, compute C1 = 2.0*C2 + C1, C2 has non-zero pattern of C */
107   PetscCall(MatDuplicate(C, MAT_DO_NOT_COPY_VALUES, &C2));
108   PetscCall(MatDuplicate(C1, MAT_COPY_VALUES, &CU));
109 
110   for (Ii = Istart; Ii < Iend; Ii++) {
111     v = 1.0;
112     PetscCall(MatSetValues(C2, 1, &Ii, 1, &Ii, &v, ADD_VALUES));
113   }
114   PetscCall(MatAssemblyBegin(C2, MAT_FINAL_ASSEMBLY));
115   PetscCall(MatAssemblyEnd(C2, MAT_FINAL_ASSEMBLY));
116   PetscCall(PetscObjectSetName((PetscObject)C2, "C2"));
117   PetscCall(MatViewFromOptions(C2, NULL, "-view"));
118   PetscCall(PetscPrintf(PETSC_COMM_WORLD, " MatAXPY(C1,2.0,C2,SUBSET_NONZERO_PATTERN)...\n"));
119   PetscCall(MatAXPY(C1, 2.0, C2, SUBSET_NONZERO_PATTERN));
120   PetscCall(MatAXPY(CU, 2.0, C2, UNKNOWN_NONZERO_PATTERN));
121   PetscCall(MatGetInfo(C1, MAT_GLOBAL_SUM, &info));
122   PetscCall(PetscPrintf(PETSC_COMM_WORLD, " C1: nz_allocated = %g; nz_used = %g; nz_unneeded = %g\n", info.nz_allocated, info.nz_used, info.nz_unneeded));
123   PetscCall(MatViewFromOptions(C1, NULL, "-view"));
124   PetscCall(MatMultEqual(CU, C1, 10, &flg));
125   if (!flg) {
126     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error UNKNOWN_NONZERO_PATTERN (supposedly SUBSET_NONZERO_PATTERN)\n"));
127     PetscCall(MatViewFromOptions(CU, NULL, "-view"));
128   }
129   PetscCall(MatDestroy(&CU));
130 
131   /* Test SAME_NONZERO_PATTERN computing C2 = C2 + 2.0 * C */
132   PetscCall(MatDuplicate(C2, MAT_COPY_VALUES, &CU));
133   PetscCall(PetscPrintf(PETSC_COMM_WORLD, " MatAXPY(C2,2.0,C,SAME_NONZERO_PATTERN)...\n"));
134   PetscCall(MatAXPY(C2, 2.0, C, SAME_NONZERO_PATTERN));
135   PetscCall(MatAXPY(CU, 2.0, C, UNKNOWN_NONZERO_PATTERN));
136   PetscCall(MatGetInfo(C2, MAT_GLOBAL_SUM, &info));
137   PetscCall(PetscPrintf(PETSC_COMM_WORLD, " C2: nz_allocated = %g; nz_used = %g; nz_unneeded = %g\n", info.nz_allocated, info.nz_used, info.nz_unneeded));
138   PetscCall(MatViewFromOptions(C2, NULL, "-view"));
139   PetscCall(MatMultEqual(CU, C2, 10, &flg));
140   if (!flg) {
141     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error UNKNOWN_NONZERO_PATTERN (supposedly SUBSET_NONZERO_PATTERN)\n"));
142     PetscCall(MatViewFromOptions(CU, NULL, "-view"));
143   }
144   PetscCall(MatDestroy(&CU));
145 
146   PetscCall(MatDestroy(&C1));
147   PetscCall(MatDestroy(&C2));
148   PetscCall(MatDestroy(&C));
149 
150   PetscCall(PetscFinalize());
151   return 0;
152 }
153 
154 /*TEST
155 
156    test:
157      suffix: 1
158      filter: grep -v " type:" | grep -v "Mat Object"
159      args: -view
160      diff_args: -j
161 
162    test:
163      output_file: output/ex132_1.out
164      requires: cuda
165      suffix: 1_cuda
166      filter: grep -v " type:" | grep -v "Mat Object"
167      args: -view -mat_type aijcusparse
168      diff_args: -j
169 
170    test:
171      output_file: output/ex132_1.out
172      requires: kokkos_kernels
173      suffix: 1_kokkos
174      filter: grep -v " type:" | grep -v "Mat Object"
175      args: -view -mat_type aijkokkos
176      diff_args: -j
177 
178    test:
179      suffix: 2
180      filter: grep -v " type:" | grep -v "Mat Object"
181      args: -view -mat_nonsym
182      diff_args: -j
183 
184    test:
185      output_file: output/ex132_2.out
186      requires: cuda
187      suffix: 2_cuda
188      filter: grep -v " type:" | grep -v "Mat Object"
189      args: -view -mat_type aijcusparse -mat_nonsym
190      diff_args: -j
191 
192    test:
193      output_file: output/ex132_2.out
194      requires: kokkos_kernels
195      suffix: 2_kokkos
196      filter: grep -v " type:" | grep -v "Mat Object"
197      args: -view -mat_type aijkokkos -mat_nonsym
198      diff_args: -j
199 
200    test:
201      nsize: 2
202      suffix: 1_par
203      filter: grep -v " type:" | grep -v "Mat Object"
204      args: -view
205      diff_args: -j
206 
207    test:
208      nsize: 2
209      output_file: output/ex132_1_par.out
210      requires: cuda
211      suffix: 1_par_cuda
212      filter: grep -v " type:" | grep -v "Mat Object"
213      args: -view -mat_type aijcusparse
214      diff_args: -j
215 
216    test:
217      nsize: 2
218      output_file: output/ex132_1_par.out
219      requires: kokkos_kernels
220      suffix: 1_par_kokkos
221      filter: grep -v " type:" | grep -v "Mat Object"
222      args: -view -mat_type aijkokkos
223      diff_args: -j
224 
225    test:
226      nsize: 2
227      suffix: 2_par
228      filter: grep -v " type:" | grep -v "Mat Object"
229      args: -view -mat_nonsym
230      diff_args: -j
231 
232    test:
233      nsize: 2
234      output_file: output/ex132_2_par.out
235      requires: cuda
236      suffix: 2_par_cuda
237      filter: grep -v " type:" | grep -v "Mat Object"
238      args: -view -mat_type aijcusparse -mat_nonsym
239      diff_args: -j
240 
241    testset:
242      nsize: 2
243      output_file: output/ex132_2_par.out
244      requires: kokkos_kernels
245      filter: grep -v " type:" | grep -v "Mat Object"
246      args: -view -mat_type aijkokkos -mat_nonsym
247      diff_args: -j
248      test:
249        suffix: 2_par_kokkos_no_gpu_aware
250        args: -use_gpu_aware_mpi 0
251      test:
252        requires: defined(HAVE_MPI_GPU_AWARE)
253        suffix: 2_par_kokkos_gpu_aware
254        args: -use_gpu_aware_mpi 1
255 
256 TEST*/
257