xref: /petsc/src/mat/tests/ex261.c (revision 14277c9297e98638593654668ce43885242b9940)
1*14277c92SJacob Faibussowitsch static const char help[] = "Tests MatGetDiagonal().\n\n";
2*14277c92SJacob Faibussowitsch 
3*14277c92SJacob Faibussowitsch #include <petscmat.h>
4*14277c92SJacob Faibussowitsch 
5*14277c92SJacob Faibussowitsch static PetscErrorCode CheckDiagonal(Mat A, Vec diag, PetscScalar dval)
6*14277c92SJacob Faibussowitsch {
7*14277c92SJacob Faibussowitsch   static PetscBool   first_time = PETSC_TRUE;
8*14277c92SJacob Faibussowitsch   const PetscReal    rtol = 1e-10, atol = PETSC_SMALL;
9*14277c92SJacob Faibussowitsch   PetscInt           rstart, rend, n;
10*14277c92SJacob Faibussowitsch   const PetscScalar *arr;
11*14277c92SJacob Faibussowitsch 
12*14277c92SJacob Faibussowitsch   PetscFunctionBegin;
13*14277c92SJacob Faibussowitsch   PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
14*14277c92SJacob Faibussowitsch   // If matrix is AIJ, MatSetRandom() will have randomly choosen the locations of nonzeros,
15*14277c92SJacob Faibussowitsch   // which may not be on the diagonal. So a reallocation is not necessarily a bad thing here.
16*14277c92SJacob Faibussowitsch   if (first_time) PetscCall(MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
17*14277c92SJacob Faibussowitsch   for (PetscInt i = rstart; i < rend; ++i) PetscCall(MatSetValue(A, i, i, dval, INSERT_VALUES));
18*14277c92SJacob Faibussowitsch   if (first_time) {
19*14277c92SJacob Faibussowitsch     PetscCall(MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE));
20*14277c92SJacob Faibussowitsch     first_time = PETSC_FALSE;
21*14277c92SJacob Faibussowitsch   }
22*14277c92SJacob Faibussowitsch 
23*14277c92SJacob Faibussowitsch   PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
24*14277c92SJacob Faibussowitsch   PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
25*14277c92SJacob Faibussowitsch   PetscCall(MatViewFromOptions(A, NULL, "-mat_view_assembled"));
26*14277c92SJacob Faibussowitsch 
27*14277c92SJacob Faibussowitsch   PetscCall(VecSetRandom(diag, NULL));
28*14277c92SJacob Faibussowitsch   PetscCall(MatGetDiagonal(A, diag));
29*14277c92SJacob Faibussowitsch   PetscCall(VecViewFromOptions(diag, NULL, "-diag_vec_view"));
30*14277c92SJacob Faibussowitsch 
31*14277c92SJacob Faibussowitsch   PetscCall(VecGetLocalSize(diag, &n));
32*14277c92SJacob Faibussowitsch   PetscCall(VecGetArrayRead(diag, &arr));
33*14277c92SJacob Faibussowitsch   for (PetscInt i = 0; i < n; ++i) {
34*14277c92SJacob Faibussowitsch     const PetscScalar lhs = arr[i];
35*14277c92SJacob Faibussowitsch 
36*14277c92SJacob Faibussowitsch     if (!PetscIsCloseAtTolScalar(lhs, dval, rtol, atol)) {
37*14277c92SJacob Faibussowitsch       const PetscReal lhs_r  = PetscRealPart(lhs);
38*14277c92SJacob Faibussowitsch       const PetscReal lhs_i  = PetscImaginaryPart(lhs);
39*14277c92SJacob Faibussowitsch       const PetscReal dval_r = PetscRealPart(dval);
40*14277c92SJacob Faibussowitsch       const PetscReal dval_i = PetscImaginaryPart(dval);
41*14277c92SJacob Faibussowitsch 
42*14277c92SJacob Faibussowitsch       PetscCheck(PetscIsCloseAtTol(lhs_r, dval_r, rtol, atol), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Real component actual[%" PetscInt_FMT "] %g != expected[%" PetscInt_FMT "] %g", i, (double)lhs_r, i, (double)dval_r);
43*14277c92SJacob Faibussowitsch       PetscCheck(PetscIsCloseAtTol(lhs_i, dval_i, rtol, atol), PETSC_COMM_SELF, PETSC_ERR_PLIB, "Imaginary component actual[%" PetscInt_FMT "] %g != expected[%" PetscInt_FMT "] %g", i, (double)lhs_i, i, (double)dval_i);
44*14277c92SJacob Faibussowitsch     }
45*14277c92SJacob Faibussowitsch   }
46*14277c92SJacob Faibussowitsch   PetscCall(VecRestoreArrayRead(diag, &arr));
47*14277c92SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
48*14277c92SJacob Faibussowitsch }
49*14277c92SJacob Faibussowitsch 
50*14277c92SJacob Faibussowitsch static PetscErrorCode InitializeMatrix(Mat A)
51*14277c92SJacob Faibussowitsch {
52*14277c92SJacob Faibussowitsch   MatType mtype;
53*14277c92SJacob Faibussowitsch   char   *tmp;
54*14277c92SJacob Faibussowitsch 
55*14277c92SJacob Faibussowitsch   PetscFunctionBegin;
56*14277c92SJacob Faibussowitsch   PetscCall(MatSetUp(A));
57*14277c92SJacob Faibussowitsch   PetscCall(MatGetType(A, &mtype));
58*14277c92SJacob Faibussowitsch   PetscCall(PetscStrstr(mtype, "aij", &tmp));
59*14277c92SJacob Faibussowitsch   if (tmp) {
60*14277c92SJacob Faibussowitsch     PetscInt  rows, cols, diag_nnz, offdiag_nnz;
61*14277c92SJacob Faibussowitsch     PetscInt *dnnz, *onnz;
62*14277c92SJacob Faibussowitsch 
63*14277c92SJacob Faibussowitsch     // is some kind of AIJ
64*14277c92SJacob Faibussowitsch     PetscCall(MatGetLocalSize(A, &rows, &cols));
65*14277c92SJacob Faibussowitsch     // at least 3 nonzeros in diagonal block
66*14277c92SJacob Faibussowitsch     diag_nnz = PetscMin(cols, 3);
67*14277c92SJacob Faibussowitsch     // leave at least 3 *zeros* per row
68*14277c92SJacob Faibussowitsch     offdiag_nnz = PetscMax(cols - diag_nnz - 3, 0);
69*14277c92SJacob Faibussowitsch     PetscCall(PetscMalloc2(rows, &dnnz, rows, &onnz));
70*14277c92SJacob Faibussowitsch     for (PetscInt i = 0; i < rows; ++i) {
71*14277c92SJacob Faibussowitsch       dnnz[i] = diag_nnz;
72*14277c92SJacob Faibussowitsch       onnz[i] = offdiag_nnz;
73*14277c92SJacob Faibussowitsch     }
74*14277c92SJacob Faibussowitsch     PetscCall(MatXAIJSetPreallocation(A, PETSC_DECIDE, dnnz, onnz, NULL, NULL));
75*14277c92SJacob Faibussowitsch     PetscCall(PetscFree2(dnnz, onnz));
76*14277c92SJacob Faibussowitsch   }
77*14277c92SJacob Faibussowitsch 
78*14277c92SJacob Faibussowitsch   PetscCall(MatSetRandom(A, NULL));
79*14277c92SJacob Faibussowitsch   PetscCall(MatViewFromOptions(A, NULL, "-mat_view_setup"));
80*14277c92SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
81*14277c92SJacob Faibussowitsch }
82*14277c92SJacob Faibussowitsch 
83*14277c92SJacob Faibussowitsch int main(int argc, char **argv)
84*14277c92SJacob Faibussowitsch {
85*14277c92SJacob Faibussowitsch   Mat A;
86*14277c92SJacob Faibussowitsch   Vec diag;
87*14277c92SJacob Faibussowitsch 
88*14277c92SJacob Faibussowitsch   PetscFunctionBeginUser;
89*14277c92SJacob Faibussowitsch   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
90*14277c92SJacob Faibussowitsch 
91*14277c92SJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_WORLD, &A));
92*14277c92SJacob Faibussowitsch   PetscCall(MatSetSizes(A, 10, 10, PETSC_DECIDE, PETSC_DECIDE));
93*14277c92SJacob Faibussowitsch   PetscCall(MatSetFromOptions(A));
94*14277c92SJacob Faibussowitsch 
95*14277c92SJacob Faibussowitsch   PetscCall(InitializeMatrix(A));
96*14277c92SJacob Faibussowitsch 
97*14277c92SJacob Faibussowitsch   PetscCall(MatCreateVecs(A, &diag, NULL));
98*14277c92SJacob Faibussowitsch 
99*14277c92SJacob Faibussowitsch   PetscCall(CheckDiagonal(A, diag, 0.0));
100*14277c92SJacob Faibussowitsch   PetscCall(CheckDiagonal(A, diag, 1.0));
101*14277c92SJacob Faibussowitsch   PetscCall(CheckDiagonal(A, diag, 2.0));
102*14277c92SJacob Faibussowitsch 
103*14277c92SJacob Faibussowitsch   PetscCall(VecDestroy(&diag));
104*14277c92SJacob Faibussowitsch   PetscCall(MatDestroy(&A));
105*14277c92SJacob Faibussowitsch   PetscCall(PetscFinalize());
106*14277c92SJacob Faibussowitsch   return 0;
107*14277c92SJacob Faibussowitsch }
108*14277c92SJacob Faibussowitsch 
109*14277c92SJacob Faibussowitsch /*TEST
110*14277c92SJacob Faibussowitsch 
111*14277c92SJacob Faibussowitsch   testset:
112*14277c92SJacob Faibussowitsch     output_file: ./output/empty.out
113*14277c92SJacob Faibussowitsch     nsize: {{1 2}}
114*14277c92SJacob Faibussowitsch     suffix: dense
115*14277c92SJacob Faibussowitsch     test:
116*14277c92SJacob Faibussowitsch       suffix: standard
117*14277c92SJacob Faibussowitsch       args: -mat_type dense
118*14277c92SJacob Faibussowitsch     test:
119*14277c92SJacob Faibussowitsch       suffix: cuda
120*14277c92SJacob Faibussowitsch       requires: cuda
121*14277c92SJacob Faibussowitsch       args: -mat_type densecuda
122*14277c92SJacob Faibussowitsch     test:
123*14277c92SJacob Faibussowitsch       suffix: hip
124*14277c92SJacob Faibussowitsch       requires: hip
125*14277c92SJacob Faibussowitsch       args: -mat_type densehip
126*14277c92SJacob Faibussowitsch 
127*14277c92SJacob Faibussowitsch   testset:
128*14277c92SJacob Faibussowitsch     output_file: ./output/empty.out
129*14277c92SJacob Faibussowitsch     nsize: {{1 2}}
130*14277c92SJacob Faibussowitsch     suffix: aij
131*14277c92SJacob Faibussowitsch     test:
132*14277c92SJacob Faibussowitsch       suffix: standard
133*14277c92SJacob Faibussowitsch       args: -mat_type aij
134*14277c92SJacob Faibussowitsch     test:
135*14277c92SJacob Faibussowitsch       suffix: cuda
136*14277c92SJacob Faibussowitsch       requires: cuda
137*14277c92SJacob Faibussowitsch       args: -mat_type aijcusparse
138*14277c92SJacob Faibussowitsch     test:
139*14277c92SJacob Faibussowitsch       suffix: hip
140*14277c92SJacob Faibussowitsch       requires: hip
141*14277c92SJacob Faibussowitsch       args: -mat_type aijhipsparse
142*14277c92SJacob Faibussowitsch     test:
143*14277c92SJacob Faibussowitsch       suffix: kokkos
144*14277c92SJacob Faibussowitsch       requires: kokkos, kokkos_kernels
145*14277c92SJacob Faibussowitsch       args: -mat_type aijkokkos
146*14277c92SJacob Faibussowitsch 
147*14277c92SJacob Faibussowitsch TEST*/
148