Actual source code: ex18.c

  1: static char help[] = "Solves a DAE with a non-trivial mass matrix. \n\n";
  2: /*
  3:    Solves:
  4:         U * dU/dt = U*V
  5:         U - V = 0

  7:    that can be rewritten in implicit form F = 0, with F as
  8:                  x[0] * xdot[0] - x[0] * x[1]
  9:    F(t,x,xdot) =
 10:                  x[0] - x[1]
 11:    It is equivalent to solve dU/dt = U, U = U0 with solution U = U0 * exp(tfinal)
 12: */

 14: #include <petscts.h>

 16: PetscErrorCode IFunction(TS, PetscReal, Vec, Vec, Vec, void *);
 17: PetscErrorCode IJacobian(TS, PetscReal, Vec, Vec, PetscReal, Mat, Mat, void *);

 19: int main(int argc, char **argv)
 20: {
 21:   TS        ts;
 22:   Vec       x;
 23:   PetscBool dae = PETSC_TRUE, random = PETSC_FALSE;

 25:   PetscFunctionBeginUser;
 26:   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
 27:   PetscCall(PetscOptionsGetBool(NULL, NULL, "-dae", &dae, NULL));
 28:   PetscCall(PetscOptionsGetBool(NULL, NULL, "-random", &random, NULL));

 30:   PetscCall(TSCreate(PETSC_COMM_WORLD, &ts));
 31:   PetscCall(TSSetIFunction(ts, NULL, IFunction, &dae));
 32:   PetscCall(TSSetIJacobian(ts, NULL, NULL, IJacobian, &dae));

 34:   PetscCall(VecCreate(PETSC_COMM_WORLD, &x));
 35:   PetscCall(VecSetSizes(x, 2, PETSC_DECIDE));
 36:   PetscCall(VecSetFromOptions(x));
 37:   PetscCall(VecSetUp(x));
 38:   if (random) {
 39:     PetscCall(VecSetRandom(x, NULL));
 40:     PetscCall(VecRealPart(x));
 41:   } else PetscCall(VecSet(x, 0.5));
 42:   PetscCall(TSSetSolution(ts, x));
 43:   PetscCall(VecDestroy(&x));

 45:   PetscCall(TSSetTimeStep(ts, 1.0 / 16.0));
 46:   PetscCall(TSSetMaxTime(ts, 1.0));
 47:   PetscCall(TSSetFromOptions(ts));
 48:   PetscCall(TSSolve(ts, NULL));

 50:   PetscCall(TSDestroy(&ts));
 51:   PetscCall(PetscFinalize());
 52:   return 0;
 53: }

 55: PetscErrorCode IFunction(TS ts, PetscReal t, Vec X, Vec Xdot, Vec F, void *ctx)
 56: {
 57:   const PetscScalar *xdot, *x;
 58:   PetscScalar       *f;
 59:   PetscBool          dae = *(PetscBool *)(ctx);

 61:   PetscFunctionBeginUser;
 62:   PetscCall(VecGetArrayRead(Xdot, &xdot));
 63:   PetscCall(VecGetArrayRead(X, &x));
 64:   PetscCall(VecGetArrayWrite(F, &f));
 65:   if (dae) {
 66:     f[0] = x[0] * xdot[0] - x[0] * x[1];
 67:     f[1] = x[0] - x[1];
 68:   } else {
 69:     f[0] = xdot[0] - x[0];
 70:     f[1] = xdot[1] - x[1];
 71:   }
 72:   PetscCall(VecRestoreArrayRead(Xdot, &xdot));
 73:   PetscCall(VecRestoreArrayRead(X, &x));
 74:   PetscCall(VecRestoreArrayWrite(F, &f));
 75:   PetscFunctionReturn(PETSC_SUCCESS);
 76: }

 78: PetscErrorCode IJacobian(TS ts, PetscReal t, Vec X, Vec Xdot, PetscReal shift, Mat A, Mat B, void *ctx)
 79: {
 80:   const PetscScalar *xdot, *x;
 81:   PetscBool          dae = *(PetscBool *)(ctx);

 83:   PetscFunctionBeginUser;
 84:   PetscCall(VecGetArrayRead(Xdot, &xdot));
 85:   PetscCall(VecGetArrayRead(X, &x));
 86:   if (dae) {
 87:     PetscCall(MatSetValue(B, 0, 0, shift * x[0] + xdot[0] - x[1], INSERT_VALUES));
 88:     PetscCall(MatSetValue(B, 0, 1, -x[0], INSERT_VALUES));
 89:     PetscCall(MatSetValue(B, 1, 0, 1.0, INSERT_VALUES));
 90:     PetscCall(MatSetValue(B, 1, 1, -1.0, INSERT_VALUES));
 91:   } else {
 92:     PetscCall(MatZeroEntries(B));
 93:     PetscCall(MatShift(B, shift));
 94:   }
 95:   PetscCall(VecRestoreArrayRead(X, &x));
 96:   PetscCall(VecRestoreArrayRead(Xdot, &xdot));
 97:   PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
 98:   PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
 99:   if (A != B) {
100:     PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
101:     PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
102:   }
103:   PetscFunctionReturn(PETSC_SUCCESS);
104: }

106: /*TEST

108:   testset:
109:     args: -ts_view_solution -ts_max_steps 10 -ts_dt 0.1 -ts_view_solution -ts_adapt_type {{none basic}} -ts_exact_final_time matchstep -snes_error_if_not_converged

111:     test:
112:       output_file: output/ex18_1.out
113:       suffix: bdf
114:       args: -ts_type bdf

116:     test:
117:       output_file: output/ex18_1.out
118:       suffix: dirk
119:       args: -dae {{0 1}} -ts_type dirk -ts_dirk_type {{s212 es122sal es213sal es324sal es325sal 657a es648sa 658a s659a 7510sal es7510sa 759a s7511sal 8614a 8616sal es8516sal}}

121:     test:
122:       output_file: output/ex18_1.out
123:       suffix: dirk_explicit_first_random_dae
124:       args: -dae -ts_type dirk -ts_dirk_type es122sal -random 1 -ts_max_reject -1

126: TEST*/