Actual source code: ex71.c
1: static char help[] = "Tests that SNESComputeJacobian() calls the user Jacobian function when a left NPC is active.\n\n";
3: #include <petscsnes.h>
5: typedef struct {
6: PetscInt jac_calls;
7: } AppCtx;
9: PetscErrorCode FormFunction(SNES snes, Vec x, Vec f, PetscCtx ctx)
10: {
11: PetscFunctionBeginUser;
12: PetscCall(VecZeroEntries(f));
13: PetscFunctionReturn(PETSC_SUCCESS);
14: }
16: PetscErrorCode FormJacobian(SNES snes, Vec x, Mat jac, Mat B, PetscCtx ctx)
17: {
18: AppCtx *appctx = (AppCtx *)ctx;
20: PetscFunctionBeginUser;
21: appctx->jac_calls++;
22: PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
23: PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
24: if (jac != B) {
25: PetscCall(MatAssemblyBegin(jac, MAT_FINAL_ASSEMBLY));
26: PetscCall(MatAssemblyEnd(jac, MAT_FINAL_ASSEMBLY));
27: }
28: PetscFunctionReturn(PETSC_SUCCESS);
29: }
31: int main(int argc, char **argv)
32: {
33: SNES snes, npc;
34: Vec x, r;
35: Mat J;
36: AppCtx appctx;
38: PetscFunctionBeginUser;
39: PetscCall(PetscInitialize(&argc, &argv, NULL, help));
41: appctx.jac_calls = 0;
43: PetscCall(VecCreate(PETSC_COMM_WORLD, &x));
44: PetscCall(VecSetSizes(x, PETSC_DECIDE, 1));
45: PetscCall(VecSetFromOptions(x));
46: PetscCall(VecDuplicate(x, &r));
48: PetscCall(MatCreate(PETSC_COMM_WORLD, &J));
49: PetscCall(MatSetSizes(J, PETSC_DECIDE, PETSC_DECIDE, 1, 1));
50: PetscCall(MatSetFromOptions(J));
51: PetscCall(MatSetUp(J));
53: PetscCall(SNESCreate(PETSC_COMM_WORLD, &snes));
54: PetscCall(SNESSetFunction(snes, r, FormFunction, NULL));
55: PetscCall(SNESSetJacobian(snes, J, J, FormJacobian, &appctx));
56: PetscCall(SNESSetNPCSide(snes, PC_LEFT));
57: PetscCall(SNESGetNPC(snes, &npc));
58: PetscCall(SNESSetType(npc, SNESNEWTONLS));
60: PetscCall(SNESSetFromOptions(snes));
61: PetscCall(SNESSetUp(snes));
63: PetscCall(VecSet(x, 1.0));
64: PetscCall(SNESComputeJacobian(snes, x, J, J));
66: PetscCheck(appctx.jac_calls > 0, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Jacobian function was not called with left NPC");
67: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Jacobian called with left NPC\n"));
69: PetscCall(VecDestroy(&x));
70: PetscCall(VecDestroy(&r));
71: PetscCall(MatDestroy(&J));
72: PetscCall(SNESDestroy(&snes));
73: PetscCall(PetscFinalize());
74: return 0;
75: }
77: /*TEST
79: test:
80: suffix: left_npc
82: TEST*/