static char help[] = "Test MatAXPY()\n\n"; #include int main(int argc, char **args) { Mat C, C1, C2, CU; PetscScalar v; PetscInt Ii, J, Istart, Iend; PetscInt i, j, m = 3, n; PetscMPIInt size; PetscBool mat_nonsymmetric = PETSC_FALSE, flg; MatInfo info; PetscFunctionBeginUser; PetscCall(PetscInitialize(&argc, &args, NULL, help)); PetscCall(PetscOptionsGetInt(NULL, NULL, "-m", &m, NULL)); PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size)); n = 2 * size; /* Set flag if we are doing a nonsymmetric problem; the default is symmetric. */ PetscCall(PetscOptionsGetBool(NULL, NULL, "-mat_nonsym", &mat_nonsymmetric, NULL)); PetscCall(MatCreate(PETSC_COMM_WORLD, &C)); PetscCall(MatSetSizes(C, PETSC_DECIDE, PETSC_DECIDE, m * n, m * n)); PetscCall(MatSetFromOptions(C)); PetscCall(MatSeqAIJSetPreallocation(C, 5, NULL)); PetscCall(MatMPIAIJSetPreallocation(C, 5, NULL, 5, NULL)); PetscCall(MatGetOwnershipRange(C, &Istart, &Iend)); for (Ii = Istart; Ii < Iend; Ii++) { v = -1.0; i = Ii / n; j = Ii - i * n; if (i > 0) { J = Ii - n; PetscCall(MatSetValues(C, 1, &Ii, 1, &J, &v, ADD_VALUES)); } if (i < m - 1) { J = Ii + n; PetscCall(MatSetValues(C, 1, &Ii, 1, &J, &v, ADD_VALUES)); } if (j > 0) { J = Ii - 1; PetscCall(MatSetValues(C, 1, &Ii, 1, &J, &v, ADD_VALUES)); } if (j < n - 1) { J = Ii + 1; PetscCall(MatSetValues(C, 1, &Ii, 1, &J, &v, ADD_VALUES)); } v = 4.0; PetscCall(MatSetValues(C, 1, &Ii, 1, &Ii, &v, ADD_VALUES)); } /* Make the matrix nonsymmetric if desired */ if (mat_nonsymmetric) { for (Ii = Istart; Ii < Iend; Ii++) { v = -1.5; i = Ii / n; if (i > 1) { J = Ii - n - 1; PetscCall(MatSetValues(C, 1, &Ii, 1, &J, &v, ADD_VALUES)); } } } else { PetscCall(MatSetOption(C, MAT_SYMMETRIC, PETSC_TRUE)); PetscCall(MatSetOption(C, MAT_SYMMETRY_ETERNAL, PETSC_TRUE)); } PetscCall(MatAssemblyBegin(C, MAT_FINAL_ASSEMBLY)); PetscCall(MatAssemblyEnd(C, MAT_FINAL_ASSEMBLY)); PetscCall(PetscObjectSetName((PetscObject)C, "C")); PetscCall(MatViewFromOptions(C, NULL, "-view")); /* C1 = 2.0*C1 + C, C1 is anti-diagonal and has different non-zeros than C */ PetscCall(MatCreate(PETSC_COMM_WORLD, &C1)); PetscCall(MatSetSizes(C1, PETSC_DECIDE, PETSC_DECIDE, m * n, m * n)); PetscCall(MatSetFromOptions(C1)); PetscCall(MatSeqAIJSetPreallocation(C1, 1, NULL)); PetscCall(MatMPIAIJSetPreallocation(C1, 1, NULL, 1, NULL)); for (Ii = Istart; Ii < Iend; Ii++) { v = 1.0; i = m * n - Ii - 1; j = Ii; PetscCall(MatSetValues(C1, 1, &i, 1, &j, &v, ADD_VALUES)); } PetscCall(MatAssemblyBegin(C1, MAT_FINAL_ASSEMBLY)); PetscCall(MatAssemblyEnd(C1, MAT_FINAL_ASSEMBLY)); PetscCall(PetscObjectSetName((PetscObject)C1, "C1")); PetscCall(MatViewFromOptions(C1, NULL, "-view")); PetscCall(MatDuplicate(C1, MAT_COPY_VALUES, &CU)); PetscCall(PetscPrintf(PETSC_COMM_WORLD, " MatAXPY(C1,2.0,C,DIFFERENT_NONZERO_PATTERN)...\n")); PetscCall(MatAXPY(C1, 2.0, C, DIFFERENT_NONZERO_PATTERN)); PetscCall(MatAXPY(CU, 2.0, C, UNKNOWN_NONZERO_PATTERN)); PetscCall(MatGetInfo(C1, MAT_GLOBAL_SUM, &info)); 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)); PetscCall(MatViewFromOptions(C1, NULL, "-view")); PetscCall(MatMultEqual(CU, C1, 10, &flg)); if (!flg) { PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error UNKNOWN_NONZERO_PATTERN (supposedly DIFFERENT_NONZERO_PATTERN)\n")); PetscCall(MatViewFromOptions(CU, NULL, "-view")); } PetscCall(MatDestroy(&CU)); /* Secondly, compute C1 = 2.0*C2 + C1, C2 has non-zero pattern of C */ PetscCall(MatDuplicate(C, MAT_DO_NOT_COPY_VALUES, &C2)); PetscCall(MatDuplicate(C1, MAT_COPY_VALUES, &CU)); for (Ii = Istart; Ii < Iend; Ii++) { v = 1.0; PetscCall(MatSetValues(C2, 1, &Ii, 1, &Ii, &v, ADD_VALUES)); } PetscCall(MatAssemblyBegin(C2, MAT_FINAL_ASSEMBLY)); PetscCall(MatAssemblyEnd(C2, MAT_FINAL_ASSEMBLY)); PetscCall(PetscObjectSetName((PetscObject)C2, "C2")); PetscCall(MatViewFromOptions(C2, NULL, "-view")); PetscCall(PetscPrintf(PETSC_COMM_WORLD, " MatAXPY(C1,2.0,C2,SUBSET_NONZERO_PATTERN)...\n")); PetscCall(MatAXPY(C1, 2.0, C2, SUBSET_NONZERO_PATTERN)); PetscCall(MatAXPY(CU, 2.0, C2, UNKNOWN_NONZERO_PATTERN)); PetscCall(MatGetInfo(C1, MAT_GLOBAL_SUM, &info)); 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)); PetscCall(MatViewFromOptions(C1, NULL, "-view")); PetscCall(MatMultEqual(CU, C1, 10, &flg)); if (!flg) { PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error UNKNOWN_NONZERO_PATTERN (supposedly SUBSET_NONZERO_PATTERN)\n")); PetscCall(MatViewFromOptions(CU, NULL, "-view")); } PetscCall(MatDestroy(&CU)); /* Test SAME_NONZERO_PATTERN computing C2 = C2 + 2.0 * C */ PetscCall(MatDuplicate(C2, MAT_COPY_VALUES, &CU)); PetscCall(PetscPrintf(PETSC_COMM_WORLD, " MatAXPY(C2,2.0,C,SAME_NONZERO_PATTERN)...\n")); PetscCall(MatAXPY(C2, 2.0, C, SAME_NONZERO_PATTERN)); PetscCall(MatAXPY(CU, 2.0, C, UNKNOWN_NONZERO_PATTERN)); PetscCall(MatGetInfo(C2, MAT_GLOBAL_SUM, &info)); 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)); PetscCall(MatViewFromOptions(C2, NULL, "-view")); PetscCall(MatMultEqual(CU, C2, 10, &flg)); if (!flg) { PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Error UNKNOWN_NONZERO_PATTERN (supposedly SUBSET_NONZERO_PATTERN)\n")); PetscCall(MatViewFromOptions(CU, NULL, "-view")); } PetscCall(MatDestroy(&CU)); PetscCall(MatDestroy(&C1)); PetscCall(MatDestroy(&C2)); PetscCall(MatDestroy(&C)); PetscCall(PetscFinalize()); return 0; } /*TEST test: suffix: 1 filter: grep -v " type:" | grep -v "Mat Object" args: -view diff_args: -j test: output_file: output/ex132_1.out requires: cuda suffix: 1_cuda filter: grep -v " type:" | grep -v "Mat Object" args: -view -mat_type aijcusparse diff_args: -j test: output_file: output/ex132_1.out requires: kokkos_kernels suffix: 1_kokkos filter: grep -v " type:" | grep -v "Mat Object" args: -view -mat_type aijkokkos diff_args: -j test: suffix: 2 filter: grep -v " type:" | grep -v "Mat Object" args: -view -mat_nonsym diff_args: -j test: output_file: output/ex132_2.out requires: cuda suffix: 2_cuda filter: grep -v " type:" | grep -v "Mat Object" args: -view -mat_type aijcusparse -mat_nonsym diff_args: -j test: output_file: output/ex132_2.out requires: kokkos_kernels suffix: 2_kokkos filter: grep -v " type:" | grep -v "Mat Object" args: -view -mat_type aijkokkos -mat_nonsym diff_args: -j test: nsize: 2 suffix: 1_par filter: grep -v " type:" | grep -v "Mat Object" args: -view diff_args: -j test: nsize: 2 output_file: output/ex132_1_par.out requires: cuda suffix: 1_par_cuda filter: grep -v " type:" | grep -v "Mat Object" args: -view -mat_type aijcusparse diff_args: -j test: nsize: 2 output_file: output/ex132_1_par.out requires: kokkos_kernels suffix: 1_par_kokkos filter: grep -v " type:" | grep -v "Mat Object" args: -view -mat_type aijkokkos diff_args: -j test: nsize: 2 suffix: 2_par filter: grep -v " type:" | grep -v "Mat Object" args: -view -mat_nonsym diff_args: -j test: nsize: 2 output_file: output/ex132_2_par.out requires: cuda suffix: 2_par_cuda filter: grep -v " type:" | grep -v "Mat Object" args: -view -mat_type aijcusparse -mat_nonsym diff_args: -j testset: nsize: 2 output_file: output/ex132_2_par.out requires: kokkos_kernels filter: grep -v " type:" | grep -v "Mat Object" args: -view -mat_type aijkokkos -mat_nonsym diff_args: -j test: suffix: 2_par_kokkos_no_gpu_aware args: -use_gpu_aware_mpi 0 test: requires: defined(HAVE_MPI_GPU_AWARE) suffix: 2_par_kokkos_gpu_aware args: -use_gpu_aware_mpi 1 TEST*/