Actual source code: ex81.c
1: static char help[] = "Constant velocity check with 1st-order generalized-alpha.\n";
3: #include <petscts.h>
5: typedef struct {
6: PetscReal v0; /* constant velocity */
7: PetscReal u0; /* initial condition */
8: PetscReal radius; /* spectral radius of integrator */
9: } UserParams;
11: static void Exact(PetscReal t, PetscReal v0, PetscReal u0, PetscScalar *ut)
12: {
13: if (ut) *ut = u0 + v0 * t;
14: }
16: PetscErrorCode Residual(TS ts, PetscReal t, Vec U, Vec V, Vec R, void *ctx)
17: {
18: UserParams *user = (UserParams *)ctx;
19: const PetscScalar *v;
20: PetscScalar *r;
22: PetscFunctionBeginUser;
23: PetscCall(VecGetArrayRead(V, &v));
24: PetscCall(VecGetArrayWrite(R, &r));
26: r[0] = v[0] - user->v0;
28: PetscCall(VecRestoreArrayRead(V, &v));
29: PetscCall(VecRestoreArrayWrite(R, &r));
30: PetscFunctionReturn(PETSC_SUCCESS);
31: }
33: PetscErrorCode Tangent(TS ts, PetscReal t, Vec U, Vec V, PetscReal shiftV, Mat J, Mat P, void *ctx)
34: {
35: PetscReal T = 0;
37: PetscFunctionBeginUser;
38: T = shiftV;
40: PetscCall(MatSetValue(P, 0, 0, T, INSERT_VALUES));
41: PetscCall(MatAssemblyBegin(P, MAT_FINAL_ASSEMBLY));
42: PetscCall(MatAssemblyEnd(P, MAT_FINAL_ASSEMBLY));
43: if (J != P) {
44: PetscCall(MatAssemblyBegin(J, MAT_FINAL_ASSEMBLY));
45: PetscCall(MatAssemblyEnd(J, MAT_FINAL_ASSEMBLY));
46: }
47: PetscFunctionReturn(PETSC_SUCCESS);
48: }
50: int main(int argc, char *argv[])
51: {
52: PetscMPIInt size;
53: TS ts;
54: Vec R;
55: Mat J;
56: Vec U;
57: PetscScalar *u, u_exact;
58: PetscReal u_err;
59: PetscReal atol = 1e-15;
60: PetscReal t_final = 3.0;
61: PetscInt n_step = 8;
62: UserParams user = {/*v0=*/1, /*u0=*/1, /*radius=*/0.0};
64: PetscFunctionBeginUser;
65: PetscCall(PetscInitialize(&argc, &argv, NULL, help));
66: PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
67: PetscCheck(size == 1, PETSC_COMM_WORLD, PETSC_ERR_WRONG_MPI_SIZE, "Only for sequential runs");
69: PetscOptionsBegin(PETSC_COMM_SELF, "", "ex81 options", "");
70: PetscCall(PetscOptionsReal("-velocity", "Constant velocity", __FILE__, user.v0, &user.v0, NULL));
71: PetscCall(PetscOptionsReal("-initial_u", "Initial displacement", __FILE__, user.u0, &user.u0, NULL));
72: PetscCall(PetscOptionsReal("-radius", "Spectral radius", __FILE__, user.radius, &user.radius, NULL));
73: PetscOptionsEnd();
75: PetscCall(TSCreate(PETSC_COMM_SELF, &ts));
76: PetscCall(TSSetType(ts, TSALPHA));
77: PetscCall(TSSetMaxTime(ts, t_final));
78: PetscCall(TSSetExactFinalTime(ts, TS_EXACTFINALTIME_MATCHSTEP));
79: PetscCall(TSSetTimeStep(ts, t_final / n_step));
80: PetscCall(TSAlphaSetRadius(ts, user.radius));
82: PetscCall(VecCreateSeq(PETSC_COMM_SELF, 1, &R));
83: PetscCall(VecSetUp(R));
84: PetscCall(MatCreateSeqDense(PETSC_COMM_SELF, 1, 1, NULL, &J));
85: PetscCall(MatSetUp(J));
86: PetscCall(TSSetIFunction(ts, R, Residual, &user));
87: PetscCall(TSSetIJacobian(ts, J, J, Tangent, &user));
88: PetscCall(VecDestroy(&R));
89: PetscCall(MatDestroy(&J));
91: PetscCall(VecCreateSeq(PETSC_COMM_SELF, 1, &U));
92: PetscCall(VecGetArrayWrite(U, &u));
93: u[0] = user.u0;
94: PetscCall(VecRestoreArrayWrite(U, &u));
96: PetscCall(TSSetSolution(ts, U));
97: PetscCall(TSSetFromOptions(ts));
98: PetscCall(TSSolve(ts, NULL));
100: PetscCall(VecGetArray(U, &u));
101: Exact(t_final, user.v0, user.u0, &u_exact);
102: u_err = PetscAbsScalar(u[0] - u_exact);
103: PetscCall(PetscPrintf(PETSC_COMM_WORLD, "u(t=%g) = %g (error = %g)\n", (double)t_final, (double)PetscRealPart(u[0]), (double)u_err));
104: PetscCheck(u_err < atol, PETSC_COMM_WORLD, PETSC_ERR_PLIB, "Inexact displacement.");
105: PetscCall(VecRestoreArray(U, &u));
107: PetscCall(VecDestroy(&U));
108: PetscCall(TSDestroy(&ts));
109: PetscCall(PetscFinalize());
110: return 0;
111: }
113: /*TEST
115: test:
116: suffix: a
117: args: -radius 0.0
118: requires: !single
120: test:
121: suffix: b
122: args: -radius 0.5
123: requires: !single
125: test:
126: suffix: c
127: args: -radius 1.0
128: requires: !single
130: TEST*/