Actual source code: ex12.c
1: static const char help[] = "Tests PCASMGetSubKSP() ordering and reused submatrices across a change of operator.\n\n";
3: #include <petscksp.h>
5: int main(int argc, char **args)
6: {
7: Mat A;
8: PC pc;
9: IS is;
10: Vec x, b;
11: KSP *subksp;
12: PetscInt n = 16, rstart, rend, nlocal;
13: PetscBool before_setup = PETSC_FALSE;
15: PetscFunctionBeginUser;
16: PetscCall(PetscInitialize(&argc, &args, NULL, help));
18: PetscCall(MatCreate(PETSC_COMM_WORLD, &A));
19: PetscCall(MatSetSizes(A, PETSC_DECIDE, PETSC_DECIDE, n, n));
20: PetscCall(MatSetFromOptions(A));
21: PetscCall(MatSetUp(A));
22: PetscCall(MatGetOwnershipRange(A, &rstart, &rend));
23: for (PetscInt row = rstart; row < rend; row++) {
24: PetscCall(MatSetValue(A, row, row, 2.0, INSERT_VALUES));
25: if (row > 0) PetscCall(MatSetValue(A, row, row - 1, -1.0, INSERT_VALUES));
26: if (row < n - 1) PetscCall(MatSetValue(A, row, row + 1, -1.0, INSERT_VALUES));
27: }
28: PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
29: PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
31: PetscCall(MatCreateVecs(A, &x, &b));
32: PetscCall(VecSet(b, 1.0));
34: PetscCall(PCCreate(PETSC_COMM_WORLD, &pc));
35: PetscCall(PCSetType(pc, PCASM));
36: PetscCall(PCSetOperators(pc, A, A));
38: PetscCall(ISCreateStride(PETSC_COMM_SELF, rend - rstart, rstart, 1, &is));
39: PetscCall(PCASMSetLocalSubdomains(pc, 1, &is, NULL));
41: /* Specifying the subdomains sets n_local_true, but the sub-KSPs are not
42: allocated until PCSetUp(). Querying them here must raise an error rather
43: than hand back a null array. */
44: PetscCall(PetscOptionsGetBool(NULL, NULL, "-before_setup", &before_setup, NULL));
45: if (before_setup) PetscCall(PCASMGetSubKSP(pc, &nlocal, NULL, &subksp));
47: /* After setup the sub-KSPs exist. */
48: PetscCall(PCSetFromOptions(pc));
49: PetscCall(PCSetUp(pc));
50: PetscCall(PCASMGetSubKSP(pc, &nlocal, NULL, &subksp));
51: PetscCheck(nlocal == 1, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Expected 1 local subdomain, got %" PetscInt_FMT, nlocal);
52: PetscCheck(subksp, PETSC_COMM_SELF, PETSC_ERR_PLIB, "PCASMGetSubKSP() returned a null array after PCSetUp()");
53: PetscCall(PCApply(pc, b, x));
55: /* A subsolver told to factor in place, e.g. -sub_pc_type ilu
56: -sub_pc_factor_in_place, has overwritten its submatrix with the factors
57: and left it flagged as factored. Changing the operator refills those
58: submatrices with MAT_REUSE_MATRIX, which a matrix still flagged as
59: factored rejects. */
60: PetscCall(MatScale(A, 2.0));
61: PetscCall(PCSetOperators(pc, A, A));
62: PetscCall(PCSetUp(pc));
63: PetscCall(PCApply(pc, b, x));
65: PetscCall(VecDestroy(&x));
66: PetscCall(VecDestroy(&b));
67: PetscCall(ISDestroy(&is));
68: PetscCall(PCDestroy(&pc));
69: PetscCall(MatDestroy(&A));
70: PetscCall(PetscFinalize());
71: return 0;
72: }
74: /*TEST
76: test:
77: suffix: 1
78: nsize: {{1 2}}
79: args: -sub_pc_type ilu -sub_pc_factor_in_place
80: output_file: output/empty.out
82: test:
83: suffix: 2
84: requires: !defined(PETSCTEST_VALGRIND) !defined(PETSC_HAVE_SANITIZER)
85: args: -before_setup -petsc_ci_portable_error_output -error_output_stdout
86: filter: grep -E "(PETSC ERROR)" | grep -E "(wrong order|Need to call|PCASMGetSubKSP\(\)|main\(\))"
88: TEST*/