Actual source code: ex16.c

  1: static char help[] = "Solves the trivial ODE du/dt = 1, u(0) = 0. \n\n";
  2: /*
  3:   This example tests TSEvent's capability to handle complicated cases.
  4:   Test 1: an event close to endpoint of a time step should not be detected twice.
  5:   Test 2: two events in the same time step should be detected in the correct order.
  6:   Test 3: three events in the same time step should be detected in the correct order.
  7: */

  9: #include <petscts.h>

 11: static PetscErrorCode RHSFunction(TS, PetscReal, Vec, Vec, void *);
 12: static PetscErrorCode RHSJacobian(TS, PetscReal, Vec, Mat, Mat, void *);

 14: static PetscErrorCode Event(TS, PetscReal, Vec, PetscReal *, void *);
 15: static PetscErrorCode PostEvent(TS, PetscInt, PetscInt[], PetscReal, Vec, PetscBool, void *);

 17: int main(int argc, char **argv)
 18: {
 19:   TS              ts;
 20:   const PetscReal t_end = 2.0;
 21:   Vec             x;
 22:   Vec             f;
 23:   Mat             A;

 25:   PetscFunctionBeginUser;
 26:   PetscCall(PetscInitialize(&argc, &argv, NULL, help));

 28:   PetscCall(TSCreate(PETSC_COMM_WORLD, &ts));

 30:   PetscCall(VecCreate(PETSC_COMM_WORLD, &f));
 31:   PetscCall(VecSetSizes(f, 1, PETSC_DECIDE));
 32:   PetscCall(VecSetFromOptions(f));
 33:   PetscCall(VecSetUp(f));
 34:   PetscCall(TSSetRHSFunction(ts, f, RHSFunction, NULL));
 35:   PetscCall(VecDestroy(&f));

 37:   PetscCall(MatCreate(PETSC_COMM_WORLD, &A));
 38:   PetscCall(MatSetSizes(A, 1, 1, PETSC_DECIDE, PETSC_DECIDE));
 39:   PetscCall(MatSetFromOptions(A));
 40:   PetscCall(MatSetUp(A));
 41:   PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
 42:   PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
 43:   /* ensure that the Jacobian matrix has diagonal entries since that is required by TS */
 44:   PetscCall(MatShift(A, (PetscReal)1));
 45:   PetscCall(MatShift(A, (PetscReal)-1));
 46:   PetscCall(TSSetRHSJacobian(ts, A, A, RHSJacobian, NULL));
 47:   PetscCall(MatDestroy(&A));

 49:   PetscCall(VecCreate(PETSC_COMM_WORLD, &x));
 50:   PetscCall(VecSetSizes(x, 1, PETSC_DECIDE));
 51:   PetscCall(VecSetFromOptions(x));
 52:   PetscCall(VecSetUp(x));
 53:   PetscCall(TSSetSolution(ts, x));
 54:   PetscCall(VecDestroy(&x));

 56:   {
 57:     PetscInt  direction[3];
 58:     PetscBool terminate[3];
 59:     direction[0] = +1;
 60:     terminate[0] = PETSC_FALSE;
 61:     direction[1] = -1;
 62:     terminate[1] = PETSC_FALSE;
 63:     direction[2] = 0;
 64:     terminate[2] = PETSC_FALSE;
 65:     PetscCall(TSSetEventHandler(ts, 3, direction, terminate, Event, PostEvent, NULL));
 66:   }
 67:   PetscCall(TSSetExactFinalTime(ts, TS_EXACTFINALTIME_STEPOVER));
 68:   PetscCall(TSSetMaxTime(ts, t_end));
 69:   PetscCall(TSSetFromOptions(ts));

 71:   PetscCall(TSSolve(ts, NULL));

 73:   PetscCall(TSDestroy(&ts));
 74:   PetscCall(PetscFinalize());
 75:   return 0;
 76: }

 78: PetscErrorCode RHSFunction(TS ts, PetscReal t, Vec x, Vec f, void *ctx)
 79: {
 80:   PetscFunctionBeginUser;
 81:   PetscCall(VecSet(f, (PetscReal)1));
 82:   PetscFunctionReturn(PETSC_SUCCESS);
 83: }

 85: PetscErrorCode RHSJacobian(TS ts, PetscReal t, Vec x, Mat A, Mat B, void *ctx)
 86: {
 87:   PetscFunctionBeginUser;
 88:   PetscCall(MatZeroEntries(B));
 89:   if (B != A) PetscCall(MatZeroEntries(A));
 90:   PetscFunctionReturn(PETSC_SUCCESS);
 91: }

 93: PetscErrorCode Event(TS ts, PetscReal t, Vec x, PetscReal *fvalue, void *ctx)
 94: {
 95:   PetscFunctionBeginUser;
 96:   fvalue[0] = t - 1.1;
 97:   fvalue[1] = 1.2 - t;
 98:   fvalue[2] = t - 1.3;
 99:   PetscFunctionReturn(PETSC_SUCCESS);
100: }

102: PetscErrorCode PostEvent(TS ts, PetscInt nevents, PetscInt event_list[], PetscReal t, Vec x, PetscBool forwardsolve, void *ctx)
103: {
104:   PetscInt           i;
105:   const PetscScalar *a;

107:   PetscFunctionBeginUser;
108:   PetscCall(TSGetStepNumber(ts, &i));
109:   PetscCall(VecGetArrayRead(x, &a));
110:   PetscCall(PetscPrintf(PetscObjectComm((PetscObject)ts), "%-10s-> step %" PetscInt_FMT " time %g value %g\n", PETSC_FUNCTION_NAME, i, (double)t, (double)PetscRealPart(a[0])));
111:   PetscCall(VecRestoreArrayRead(x, &a));
112:   PetscFunctionReturn(PETSC_SUCCESS);
113: }

115: /*TEST

117:     test:
118:       args: -ts_type beuler -ts_dt 0.1 -ts_event_monitor

120:     test:
121:       suffix: 2
122:       args: -ts_type beuler -ts_dt 0.2 -ts_event_monitor

124:     test:
125:       suffix: 3
126:       args: -ts_type beuler -ts_dt 0.5 -ts_event_monitor
127: TEST*/