Actual source code: ex70.c
1: static char help[] = "Tests that SNESSetUp() propagates application context to the NPC only when the NPC has no existing context.\n\n";
3: #include <petscsnes.h>
5: typedef struct {
6: PetscInt tag;
7: } AppCtx;
9: PetscErrorCode FormFunction(SNES snes, Vec x, Vec f, PetscCtx ctx)
10: {
11: const PetscScalar *xx;
12: PetscScalar *ff;
14: PetscFunctionBeginUser;
15: PetscCall(VecGetArrayRead(x, &xx));
16: PetscCall(VecGetArray(f, &ff));
17: ff[0] = xx[0];
18: PetscCall(VecRestoreArrayRead(x, &xx));
19: PetscCall(VecRestoreArray(f, &ff));
20: PetscFunctionReturn(PETSC_SUCCESS);
21: }
23: PetscErrorCode FormJacobian(SNES snes, Vec x, Mat jac, Mat B, PetscCtx ctx)
24: {
25: PetscScalar one = 1.0;
26: PetscInt idx = 0;
28: PetscFunctionBeginUser;
29: PetscCall(MatSetValues(B, 1, &idx, 1, &idx, &one, INSERT_VALUES));
30: PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
31: PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
32: if (jac != B) {
33: PetscCall(MatAssemblyBegin(jac, MAT_FINAL_ASSEMBLY));
34: PetscCall(MatAssemblyEnd(jac, MAT_FINAL_ASSEMBLY));
35: }
36: PetscFunctionReturn(PETSC_SUCCESS);
37: }
39: int main(int argc, char **argv)
40: {
41: SNES snes, npc;
42: Vec x, r;
43: Mat J;
44: AppCtx parent_ctx, npc_ctx;
45: void *retrieved_ctx;
46: PetscBool test_preserve = PETSC_FALSE;
48: PetscFunctionBeginUser;
49: PetscCall(PetscInitialize(&argc, &argv, NULL, help));
50: PetscCall(PetscOptionsGetBool(NULL, NULL, "-test_preserve", &test_preserve, NULL));
52: parent_ctx.tag = 1;
53: npc_ctx.tag = 2;
55: PetscCall(VecCreate(PETSC_COMM_WORLD, &x));
56: PetscCall(VecSetSizes(x, PETSC_DECIDE, 1));
57: PetscCall(VecSetFromOptions(x));
58: PetscCall(VecDuplicate(x, &r));
60: PetscCall(MatCreate(PETSC_COMM_WORLD, &J));
61: PetscCall(MatSetSizes(J, PETSC_DECIDE, PETSC_DECIDE, 1, 1));
62: PetscCall(MatSetFromOptions(J));
63: PetscCall(MatSetUp(J));
65: PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes));
66: PetscCall(SNESSetFunction(snes, r, FormFunction, NULL));
67: PetscCall(SNESSetJacobian(snes, J, J, FormJacobian, NULL));
68: PetscCall(SNESSetApplicationContext(snes, &parent_ctx));
70: /* Use SNESSetNPC with a freshly created SNES so no automatic context copy occurs */
71: PetscCall(SNESCreate(PETSC_COMM_WORLD, &npc));
72: if (test_preserve) PetscCall(SNESSetApplicationContext(npc, &npc_ctx));
73: PetscCall(SNESSetNPC(snes, npc));
74: PetscCall(SNESDestroy(&npc));
76: PetscCall(SNESSetFromOptions(snes));
77: PetscCall(SNESSetUp(snes));
79: PetscCall(SNESGetNPC(snes, &npc));
80: PetscCall(SNESGetApplicationContext(npc, &retrieved_ctx));
81: if (test_preserve) {
82: PetscCheck(retrieved_ctx == (void *)&npc_ctx, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "NPC context was overwritten by parent context");
83: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "NPC kept its own context (tag=%" PetscInt_FMT ")\n", ((AppCtx *)retrieved_ctx)->tag));
84: } else {
85: PetscCheck(retrieved_ctx == (void *)&parent_ctx, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "NPC did not inherit parent context");
86: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "NPC inherited parent context (tag=%" PetscInt_FMT ")\n", ((AppCtx *)retrieved_ctx)->tag));
87: }
89: PetscCall(VecDestroy(&x));
90: PetscCall(VecDestroy(&r));
91: PetscCall(MatDestroy(&J));
92: PetscCall(SNESDestroy(&snes));
93: PetscCall(PetscFinalize());
94: return 0;
95: }
97: /*TEST
99: test:
100: suffix: inherit
101: nsize: 1
102: output_file: output/ex70_inherit.out
104: test:
105: suffix: preserve
106: nsize: 1
107: args: -test_preserve
108: output_file: output/ex70_preserve.out
110: TEST*/