Actual source code: ex72.c
1: static char help[] = "Tests that SNESSetConvergenceTest() is preserved when SNESSetType() changes to a VI type.\n\n";
3: #include <petscsnes.h>
5: typedef struct {
6: PetscBool called;
7: } TestCtx;
9: static PetscErrorCode CustomConvergedTest(SNES snes, PetscInt it, PetscReal xnorm, PetscReal snorm, PetscReal fnorm, SNESConvergedReason *reason, PetscCtx ctx)
10: {
11: TestCtx *tctx = (TestCtx *)ctx;
13: PetscFunctionBeginUser;
14: tctx->called = PETSC_TRUE;
15: PetscCall(SNESConvergedDefault(snes, it, xnorm, snorm, fnorm, reason, NULL));
16: PetscFunctionReturn(PETSC_SUCCESS);
17: }
19: static PetscErrorCode FormFunction(SNES snes, Vec x, Vec f, PetscCtx ctx)
20: {
21: PetscFunctionBeginUser;
22: PetscCall(VecCopy(x, f));
23: PetscFunctionReturn(PETSC_SUCCESS);
24: }
26: static PetscErrorCode FormJacobian(SNES snes, Vec x, Mat J, Mat B, PetscCtx ctx)
27: {
28: PetscInt idx = 0;
29: PetscScalar one = 1.0;
31: PetscFunctionBeginUser;
32: PetscCall(MatSetValues(B, 1, &idx, 1, &idx, &one, INSERT_VALUES));
33: PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
34: PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
35: PetscFunctionReturn(PETSC_SUCCESS);
36: }
38: int main(int argc, char **argv)
39: {
40: SNES snes;
41: Vec x, r, xl, xu;
42: Mat J;
43: TestCtx ctx;
45: PetscFunctionBeginUser;
46: PetscCall(PetscInitialize(&argc, &argv, NULL, help));
48: ctx.called = PETSC_FALSE;
50: PetscCall(VecCreate(PETSC_COMM_WORLD, &x));
51: PetscCall(VecSetSizes(x, PETSC_DECIDE, 1));
52: PetscCall(VecSetFromOptions(x));
53: PetscCall(VecSet(x, 0.5));
54: PetscCall(VecDuplicate(x, &r));
55: PetscCall(VecDuplicate(x, &xl));
56: PetscCall(VecDuplicate(x, &xu));
57: PetscCall(VecSet(xl, 0.0));
58: PetscCall(VecSet(xu, 1.0));
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));
69: /* Set custom convergence test BEFORE setting the VI type to verify it is preserved */
70: PetscCall(SNESSetConvergenceTest(snes, CustomConvergedTest, &ctx, NULL));
72: PetscCall(SNESSetType(snes, SNESVINEWTONRSLS));
73: PetscCall(SNESVISetVariableBounds(snes, xl, xu));
74: PetscCall(SNESSetFromOptions(snes));
76: PetscCall(SNESSolve(snes, NULL, x));
78: PetscCheck(ctx.called, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Custom convergence test was not invoked; SNESSetType() overwrote it");
79: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "Custom convergence test preserved after SNESSetType() to SNESVINEWTONRSLS\n"));
81: PetscCall(SNESDestroy(&snes));
82: PetscCall(VecDestroy(&x));
83: PetscCall(VecDestroy(&r));
84: PetscCall(VecDestroy(&xl));
85: PetscCall(VecDestroy(&xu));
86: PetscCall(MatDestroy(&J));
87: PetscCall(PetscFinalize());
88: return 0;
89: }
91: /*TEST
93: test:
94: nsize: 1
95: output_file: output/ex72.out
97: TEST*/