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*/