Actual source code: ex11.c
1: static const char help[] = "Tests PCMG setup with DMKSP{Create|Compute}Operators.\n\n";
3: #include <petscksp.h>
4: #include <petscdmda.h>
6: typedef struct {
7: PetscBool same_operator;
8: PetscInt ncreate;
9: PetscInt ncompute;
10: } AppCtx;
12: static PetscErrorCode AssembleDiagonal(Mat A, PetscScalar diag)
13: {
14: PetscInt rstart, rend;
16: PetscFunctionBeginUser;
17: PetscCall(MatZeroEntries(A));
18: PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
19: for (PetscInt row = rstart; row < rend; row++) PetscCall(MatSetValue(A, row, row, diag, INSERT_VALUES));
20: PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
21: PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
22: PetscFunctionReturn(PETSC_SUCCESS);
23: }
25: static PetscErrorCode CreateOperators(KSP ksp, Mat *A, Mat *P, void *ctx)
26: {
27: AppCtx *user = (AppCtx *)ctx;
28: DM dm;
30: PetscFunctionBeginUser;
31: PetscCall(KSPGetDM(ksp, &dm));
32: PetscCall(DMCreateMatrix(dm, A));
33: if (!user->same_operator) PetscCall(DMCreateMatrix(dm, P));
34: else *P = *A; /* No need to increment ref count of A */
35: user->ncreate++;
36: PetscFunctionReturn(PETSC_SUCCESS);
37: }
39: static PetscErrorCode ComputeOperators(KSP ksp, Mat A, Mat P, void *ctx)
40: {
41: AppCtx *user = (AppCtx *)ctx;
43: PetscFunctionBeginUser;
44: PetscCall(AssembleDiagonal(P, 3.0));
45: if (A != P) PetscCall(AssembleDiagonal(A, 2.0));
46: user->ncompute++;
47: PetscFunctionReturn(PETSC_SUCCESS);
48: }
50: int main(int argc, char **argv)
51: {
52: AppCtx user;
53: DM dm;
54: KSP ksp, cksp;
55: PC pc;
56: Mat A, P;
57: PetscBool user_finest = PETSC_TRUE, expected_same_operator, use_amat;
58: PetscInt nl, expected_ncreate, expected_ncompute;
60: PetscFunctionBeginUser;
61: user.same_operator = PETSC_FALSE;
62: user.ncreate = 0;
63: user.ncompute = 0;
65: PetscCall(PetscInitialize(&argc, &argv, NULL, help));
66: PetscCall(PetscOptionsGetBool(NULL, NULL, "-user_finest", &user_finest, NULL));
67: PetscCall(PetscOptionsGetBool(NULL, NULL, "-same_operator", &user.same_operator, NULL));
69: PetscCall(DMDACreate1d(PETSC_COMM_WORLD, DM_BOUNDARY_NONE, 3, 1, 1, NULL, &dm));
70: PetscCall(DMSetFromOptions(dm));
71: PetscCall(DMSetUp(dm));
73: PetscCall(DMKSPSetCreateOperators(dm, CreateOperators, &user));
74: PetscCall(DMKSPSetComputeOperators(dm, ComputeOperators, &user));
76: PetscCall(KSPCreate(PETSC_COMM_WORLD, &ksp));
77: PetscCall(KSPSetDM(ksp, dm));
78: PetscCall(KSPSetDMActive(ksp, KSP_DMACTIVE_OPERATOR, (PetscBool)!user_finest));
79: PetscCall(KSPSetType(ksp, KSPPREONLY));
80: PetscCall(KSPGetPC(ksp, &pc));
81: PetscCall(PCSetType(pc, PCMG));
82: if (user_finest) {
83: PetscCall(DMCreateMatrix(dm, &A));
84: PetscCall(AssembleDiagonal(A, 2.0));
85: P = A;
86: if (!user.same_operator) {
87: PetscCall(DMCreateMatrix(dm, &P));
88: PetscCall(AssembleDiagonal(P, 3.0));
89: }
90: PetscCall(KSPSetOperators(ksp, A, P));
91: PetscCall(MatDestroy(&A));
92: if (!user.same_operator) PetscCall(MatDestroy(&P));
93: }
94: PetscCall(KSPSetFromOptions(ksp));
95: PetscCall(KSPSetUp(ksp));
96: PetscCall(KSPViewFromOptions(ksp, NULL, "-ksp_view"));
98: PetscCall(PCMGGetLevels(pc, &nl));
99: PetscCall(PCGetUseAmat(pc, &use_amat));
100: expected_ncreate = user_finest ? nl - 1 : nl;
101: expected_ncompute = user_finest ? nl - 1 : nl;
102: expected_same_operator = (PetscBool)(!use_amat || user.same_operator);
103: PetscCheck(user.ncreate == expected_ncreate, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Expected PCMG to create %" PetscInt_FMT " operators: found %" PetscInt_FMT, expected_ncreate, user.ncreate);
104: PetscCheck(user.ncompute == expected_ncompute, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Expected PCMG to compute %" PetscInt_FMT " operators: found %" PetscInt_FMT, expected_ncompute, user.ncompute);
106: for (PetscInt l = nl - 1; l > 0; l--) {
107: KSP sksp;
109: PetscCall(PCMGGetSmootherDown(pc, l, &sksp));
110: PetscCall(KSPGetOperators(sksp, &A, &P));
111: if (!expected_same_operator) PetscCheck(A != P, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Smooth KSP operators were not distinct");
112: else PetscCheck(A == P, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Smooth KSP operators were not Pmat-only");
113: }
114: PetscCall(PCMGGetCoarseSolve(pc, &cksp));
115: PetscCall(KSPGetOperators(cksp, &A, &P));
116: if (!expected_same_operator) PetscCheck(A != P, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Coarse KSP operators were not distinct");
117: else PetscCheck(A == P, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Coarse KSP operators were not Pmat-only");
118: PetscCall(KSPDestroy(&ksp));
119: PetscCall(DMDestroy(&dm));
120: PetscCall(PetscFinalize());
121: return 0;
122: }
124: /*TEST
126: test:
127: args: -pc_mg_galerkin none -user_finest {{0 1}} -same_operator {{0 1}} -da_refine {{0 1 2}} -pc_use_amat {{0 1}}
128: output_file: output/empty.out
130: TEST*/