1c4762a1bSJed Brown static char help[] = "Performs adjoint sensitivity analysis for the van der Pol equation.\n";
2c4762a1bSJed Brown
3c4762a1bSJed Brown /* ------------------------------------------------------------------------
4c4762a1bSJed Brown
5c4762a1bSJed Brown This program solves the van der Pol DAE ODE equivalent
6c4762a1bSJed Brown [ u_1' ] = [ u_2 ] (2)
7c4762a1bSJed Brown [ u_2' ] [ \mu ((1 - u_1^2) u_2 - u_1) ]
8c4762a1bSJed Brown on the domain 0 <= x <= 1, with the boundary conditions
9c4762a1bSJed Brown u_1(0) = 2, u_2(0) = - 2/3 +10/(81*\mu) - 292/(2187*\mu^2),
10c4762a1bSJed Brown and
11c4762a1bSJed Brown \mu = 10^6 ( y'(0) ~ -0.6666665432100101).,
12c4762a1bSJed Brown and computes the sensitivities of the final solution w.r.t. initial conditions and parameter \mu with the implicit theta method and its discrete adjoint.
13c4762a1bSJed Brown
1480ab5e31SHong Zhang In an IMEX setting, we can split (2) by component,
1580ab5e31SHong Zhang
1680ab5e31SHong Zhang [ u_1' ] = [ u_2 ] + [ 0 ]
1780ab5e31SHong Zhang [ u_2' ] [ 0 ] [ \mu ((1 - u_1^2) u_2 - u_1) ]
1880ab5e31SHong Zhang
1980ab5e31SHong Zhang where
2080ab5e31SHong Zhang
2180ab5e31SHong Zhang [ G(u,t) ] = [ u_2 ]
2280ab5e31SHong Zhang [ 0 ]
2380ab5e31SHong Zhang
2480ab5e31SHong Zhang and
2580ab5e31SHong Zhang
2680ab5e31SHong Zhang [ F(u',u,t) ] = [ u_1' ] - [ 0 ]
2780ab5e31SHong Zhang [ u_2' ] [ \mu ((1 - u_1^2) u_2 - u_1) ]
2880ab5e31SHong Zhang
29c4762a1bSJed Brown Notes:
30c4762a1bSJed Brown This code demonstrates the TSAdjoint interface to a DAE system.
31c4762a1bSJed Brown
32c4762a1bSJed Brown The user provides the implicit right-hand-side function
335ab1ac2bSHong Zhang [ F(u',u,t) ] = [u' - f(u,t)] = [ u_1'] - [ u_2 ]
34c4762a1bSJed Brown [ u_2'] [ \mu ((1-u_1^2)u_2-u_1) ]
35c4762a1bSJed Brown
365ab1ac2bSHong Zhang and the Jacobian of F (from the PETSc user manual)
37c4762a1bSJed Brown
385ab1ac2bSHong Zhang dF dF
395ab1ac2bSHong Zhang J(F) = a * -- + --
40c4762a1bSJed Brown du' du
41c4762a1bSJed Brown
425ab1ac2bSHong Zhang and the JacobianP of the explicit right-hand side of (2) f(u,t) ( which is equivalent to -F(0,u,t)).
43c4762a1bSJed Brown df [ 0 ]
44c4762a1bSJed Brown -- = [ ]
45c4762a1bSJed Brown dp [ (1 - u_1^2) u_2 - u_1 ].
46c4762a1bSJed Brown
47c4762a1bSJed Brown See ex20.c for more details on the Jacobian.
48c4762a1bSJed Brown
49c4762a1bSJed Brown ------------------------------------------------------------------------- */
50c4762a1bSJed Brown #include <petscts.h>
51c4762a1bSJed Brown #include <petsctao.h>
52c4762a1bSJed Brown
53c4762a1bSJed Brown typedef struct _n_User *User;
54c4762a1bSJed Brown struct _n_User {
55c4762a1bSJed Brown PetscReal mu;
56c4762a1bSJed Brown PetscReal next_output;
5780ab5e31SHong Zhang PetscBool imex;
58c4762a1bSJed Brown /* Sensitivity analysis support */
59c4762a1bSJed Brown PetscInt steps;
60c4762a1bSJed Brown PetscReal ftime;
6180ab5e31SHong Zhang Mat A; /* IJacobian matrix */
6280ab5e31SHong Zhang Mat B; /* RHSJacobian matrix */
6380ab5e31SHong Zhang Mat Jacp; /* IJacobianP matrix */
6480ab5e31SHong Zhang Mat Jacprhs; /* RHSJacobianP matrix */
65c4762a1bSJed Brown Vec U, lambda[2], mup[2]; /* adjoint variables */
66c4762a1bSJed Brown };
67c4762a1bSJed Brown
68c4762a1bSJed Brown /* ----------------------- Explicit form of the ODE -------------------- */
69c4762a1bSJed Brown
RHSFunction(TS ts,PetscReal t,Vec U,Vec F,PetscCtx ctx)70*2a8381b2SBarry Smith static PetscErrorCode RHSFunction(TS ts, PetscReal t, Vec U, Vec F, PetscCtx ctx)
71d71ae5a4SJacob Faibussowitsch {
72c4762a1bSJed Brown User user = (User)ctx;
73c4762a1bSJed Brown PetscScalar *f;
74c4762a1bSJed Brown const PetscScalar *u;
75c4762a1bSJed Brown
76c4762a1bSJed Brown PetscFunctionBeginUser;
779566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(U, &u));
789566063dSJacob Faibussowitsch PetscCall(VecGetArray(F, &f));
79c4762a1bSJed Brown f[0] = u[1];
8080ab5e31SHong Zhang if (user->imex) {
8180ab5e31SHong Zhang f[1] = 0.0;
8280ab5e31SHong Zhang } else {
83c4762a1bSJed Brown f[1] = user->mu * ((1. - u[0] * u[0]) * u[1] - u[0]);
8480ab5e31SHong Zhang }
859566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(U, &u));
869566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(F, &f));
873ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
88c4762a1bSJed Brown }
89c4762a1bSJed Brown
RHSJacobian(TS ts,PetscReal t,Vec U,Mat A,Mat B,PetscCtx ctx)90*2a8381b2SBarry Smith static PetscErrorCode RHSJacobian(TS ts, PetscReal t, Vec U, Mat A, Mat B, PetscCtx ctx)
91d71ae5a4SJacob Faibussowitsch {
92c4762a1bSJed Brown User user = (User)ctx;
93c4762a1bSJed Brown PetscReal mu = user->mu;
94c4762a1bSJed Brown PetscInt rowcol[] = {0, 1};
95c4762a1bSJed Brown PetscScalar J[2][2];
96c4762a1bSJed Brown const PetscScalar *u;
97c4762a1bSJed Brown
98c4762a1bSJed Brown PetscFunctionBeginUser;
999566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(U, &u));
100c4762a1bSJed Brown J[0][0] = 0;
101c4762a1bSJed Brown J[0][1] = 1.0;
10280ab5e31SHong Zhang if (user->imex) {
10380ab5e31SHong Zhang J[1][0] = 0.0;
10480ab5e31SHong Zhang J[1][1] = 0.0;
10580ab5e31SHong Zhang } else {
10680ab5e31SHong Zhang J[1][0] = -mu * (2.0 * u[1] * u[0] + 1.);
107c4762a1bSJed Brown J[1][1] = mu * (1.0 - u[0] * u[0]);
10880ab5e31SHong Zhang }
1099566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 2, rowcol, 2, rowcol, &J[0][0], INSERT_VALUES));
1109566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
1119566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
112c4762a1bSJed Brown if (A != B) {
1139566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
1149566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
115c4762a1bSJed Brown }
1169566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(U, &u));
1173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
118c4762a1bSJed Brown }
119c4762a1bSJed Brown
120c4762a1bSJed Brown /* ----------------------- Implicit form of the ODE -------------------- */
121c4762a1bSJed Brown
IFunction(TS ts,PetscReal t,Vec U,Vec Udot,Vec F,PetscCtx ctx)122*2a8381b2SBarry Smith static PetscErrorCode IFunction(TS ts, PetscReal t, Vec U, Vec Udot, Vec F, PetscCtx ctx)
123d71ae5a4SJacob Faibussowitsch {
124c4762a1bSJed Brown User user = (User)ctx;
125c4762a1bSJed Brown const PetscScalar *u, *udot;
126c4762a1bSJed Brown PetscScalar *f;
127c4762a1bSJed Brown
128c4762a1bSJed Brown PetscFunctionBeginUser;
1299566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(U, &u));
1309566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(Udot, &udot));
1319566063dSJacob Faibussowitsch PetscCall(VecGetArray(F, &f));
13280ab5e31SHong Zhang if (user->imex) {
13380ab5e31SHong Zhang f[0] = udot[0];
13480ab5e31SHong Zhang } else {
135c4762a1bSJed Brown f[0] = udot[0] - u[1];
13680ab5e31SHong Zhang }
137c4762a1bSJed Brown f[1] = udot[1] - user->mu * ((1.0 - u[0] * u[0]) * u[1] - u[0]);
1389566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(U, &u));
1399566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(Udot, &udot));
1409566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(F, &f));
1413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
142c4762a1bSJed Brown }
143c4762a1bSJed Brown
IJacobian(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal a,Mat A,Mat B,PetscCtx ctx)144*2a8381b2SBarry Smith static PetscErrorCode IJacobian(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal a, Mat A, Mat B, PetscCtx ctx)
145d71ae5a4SJacob Faibussowitsch {
146c4762a1bSJed Brown User user = (User)ctx;
147c4762a1bSJed Brown PetscInt rowcol[] = {0, 1};
148c4762a1bSJed Brown PetscScalar J[2][2];
149c4762a1bSJed Brown const PetscScalar *u;
150c4762a1bSJed Brown
151c4762a1bSJed Brown PetscFunctionBeginUser;
1529566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(U, &u));
153c4762a1bSJed Brown
15480ab5e31SHong Zhang if (user->imex) {
15580ab5e31SHong Zhang J[0][0] = a;
15680ab5e31SHong Zhang J[0][1] = 0.0;
15780ab5e31SHong Zhang } else {
1589371c9d4SSatish Balay J[0][0] = a;
1599371c9d4SSatish Balay J[0][1] = -1.0;
16080ab5e31SHong Zhang }
1619371c9d4SSatish Balay J[1][0] = user->mu * (2.0 * u[0] * u[1] + 1.0);
1629371c9d4SSatish Balay J[1][1] = a - user->mu * (1.0 - u[0] * u[0]);
163c4762a1bSJed Brown
1649566063dSJacob Faibussowitsch PetscCall(MatSetValues(B, 2, rowcol, 2, rowcol, &J[0][0], INSERT_VALUES));
1659566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(U, &u));
166c4762a1bSJed Brown
1679566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
1689566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
169c4762a1bSJed Brown if (B && A != B) {
1709566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY));
1719566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY));
172c4762a1bSJed Brown }
1733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
174c4762a1bSJed Brown }
175c4762a1bSJed Brown
IJacobianP(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal a,Mat A,PetscCtx ctx)176*2a8381b2SBarry Smith static PetscErrorCode IJacobianP(TS ts, PetscReal t, Vec U, Vec Udot, PetscReal a, Mat A, PetscCtx ctx)
177d71ae5a4SJacob Faibussowitsch {
178c4762a1bSJed Brown PetscInt row[] = {0, 1}, col[] = {0};
179c4762a1bSJed Brown PetscScalar J[2][1];
180c4762a1bSJed Brown const PetscScalar *u;
181c4762a1bSJed Brown
182c4762a1bSJed Brown PetscFunctionBeginUser;
1839566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(U, &u));
184c4762a1bSJed Brown J[0][0] = 0;
18580ab5e31SHong Zhang J[1][0] = -((1.0 - u[0] * u[0]) * u[1] - u[0]);
18680ab5e31SHong Zhang PetscCall(MatSetValues(A, 2, row, 1, col, &J[0][0], INSERT_VALUES));
18780ab5e31SHong Zhang PetscCall(VecRestoreArrayRead(U, &u));
18880ab5e31SHong Zhang PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
18980ab5e31SHong Zhang PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
19080ab5e31SHong Zhang PetscFunctionReturn(PETSC_SUCCESS);
19180ab5e31SHong Zhang }
19280ab5e31SHong Zhang
RHSJacobianP(TS ts,PetscReal t,Vec U,Mat A,PetscCtx ctx)193*2a8381b2SBarry Smith static PetscErrorCode RHSJacobianP(TS ts, PetscReal t, Vec U, Mat A, PetscCtx ctx)
19480ab5e31SHong Zhang {
19580ab5e31SHong Zhang User user = (User)ctx;
19680ab5e31SHong Zhang
19780ab5e31SHong Zhang PetscFunctionBeginUser;
19880ab5e31SHong Zhang if (!user->imex) {
19980ab5e31SHong Zhang PetscInt row[] = {0, 1}, col[] = {0};
20080ab5e31SHong Zhang PetscScalar J[2][1];
20180ab5e31SHong Zhang const PetscScalar *u;
20280ab5e31SHong Zhang PetscCall(VecGetArrayRead(U, &u));
20380ab5e31SHong Zhang J[0][0] = 0;
204c4762a1bSJed Brown J[1][0] = (1. - u[0] * u[0]) * u[1] - u[0];
2059566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 2, row, 1, col, &J[0][0], INSERT_VALUES));
2069566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
2079566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
2089566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(U, &u));
20980ab5e31SHong Zhang }
2103ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
211c4762a1bSJed Brown }
212c4762a1bSJed Brown
213c4762a1bSJed Brown /* Monitor timesteps and use interpolation to output at integer multiples of 0.1 */
Monitor(TS ts,PetscInt step,PetscReal t,Vec U,PetscCtx ctx)214*2a8381b2SBarry Smith static PetscErrorCode Monitor(TS ts, PetscInt step, PetscReal t, Vec U, PetscCtx ctx)
215d71ae5a4SJacob Faibussowitsch {
216c4762a1bSJed Brown const PetscScalar *u;
217c4762a1bSJed Brown PetscReal tfinal, dt;
218c4762a1bSJed Brown User user = (User)ctx;
219c4762a1bSJed Brown Vec interpolatedU;
220c4762a1bSJed Brown
221c4762a1bSJed Brown PetscFunctionBeginUser;
2229566063dSJacob Faibussowitsch PetscCall(TSGetTimeStep(ts, &dt));
2239566063dSJacob Faibussowitsch PetscCall(TSGetMaxTime(ts, &tfinal));
224c4762a1bSJed Brown
225c4762a1bSJed Brown while (user->next_output <= t && user->next_output <= tfinal) {
2269566063dSJacob Faibussowitsch PetscCall(VecDuplicate(U, &interpolatedU));
2279566063dSJacob Faibussowitsch PetscCall(TSInterpolate(ts, user->next_output, interpolatedU));
2289566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(interpolatedU, &u));
2299371c9d4SSatish Balay PetscCall(PetscPrintf(PETSC_COMM_WORLD, "[%g] %" PetscInt_FMT " TS %g (dt = %g) X %g %g\n", (double)user->next_output, step, (double)t, (double)dt, (double)PetscRealPart(u[0]), (double)PetscRealPart(u[1])));
2309566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(interpolatedU, &u));
2319566063dSJacob Faibussowitsch PetscCall(VecDestroy(&interpolatedU));
232c4762a1bSJed Brown user->next_output += 0.1;
233c4762a1bSJed Brown }
2343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
235c4762a1bSJed Brown }
236c4762a1bSJed Brown
main(int argc,char ** argv)237d71ae5a4SJacob Faibussowitsch int main(int argc, char **argv)
238d71ae5a4SJacob Faibussowitsch {
239c4762a1bSJed Brown TS ts;
240c4762a1bSJed Brown PetscBool monitor = PETSC_FALSE, implicitform = PETSC_TRUE;
241c4762a1bSJed Brown PetscScalar *x_ptr, *y_ptr, derp;
242c4762a1bSJed Brown PetscMPIInt size;
243c4762a1bSJed Brown struct _n_User user;
244c4762a1bSJed Brown
245c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
246c4762a1bSJed Brown Initialize program
247c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
248327415f7SBarry Smith PetscFunctionBeginUser;
2499566063dSJacob Faibussowitsch PetscCall(PetscInitialize(&argc, &argv, NULL, help));
2509566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(PETSC_COMM_WORLD, &size));
2513c633725SBarry Smith PetscCheck(size == 1, PETSC_COMM_WORLD, PETSC_ERR_WRONG_MPI_SIZE, "This is a uniprocessor example only!");
252c4762a1bSJed Brown
253c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
254c4762a1bSJed Brown Set runtime options
255c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
256c4762a1bSJed Brown user.next_output = 0.0;
257c4762a1bSJed Brown user.mu = 1.0e3;
258c4762a1bSJed Brown user.steps = 0;
259c4762a1bSJed Brown user.ftime = 0.5;
26080ab5e31SHong Zhang user.imex = PETSC_FALSE;
2619566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-monitor", &monitor, NULL));
2629566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetReal(NULL, NULL, "-mu", &user.mu, NULL));
2639566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetBool(NULL, NULL, "-implicitform", &implicitform, NULL));
26480ab5e31SHong Zhang PetscCall(PetscOptionsGetBool(NULL, NULL, "-imexform", &user.imex, NULL));
265c4762a1bSJed Brown
266c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
267c4762a1bSJed Brown Create necessary matrix and vectors, solve same ODE on every process
268c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2699566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_WORLD, &user.A));
2709566063dSJacob Faibussowitsch PetscCall(MatSetSizes(user.A, PETSC_DECIDE, PETSC_DECIDE, 2, 2));
2719566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(user.A));
2729566063dSJacob Faibussowitsch PetscCall(MatSetUp(user.A));
2739566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(user.A, &user.U, NULL));
27480ab5e31SHong Zhang PetscCall(MatDuplicate(user.A, MAT_DO_NOT_COPY_VALUES, &user.B));
2759566063dSJacob Faibussowitsch PetscCall(MatCreate(PETSC_COMM_WORLD, &user.Jacp));
2769566063dSJacob Faibussowitsch PetscCall(MatSetSizes(user.Jacp, PETSC_DECIDE, PETSC_DECIDE, 2, 1));
2779566063dSJacob Faibussowitsch PetscCall(MatSetFromOptions(user.Jacp));
2789566063dSJacob Faibussowitsch PetscCall(MatSetUp(user.Jacp));
27980ab5e31SHong Zhang PetscCall(MatDuplicate(user.Jacp, MAT_DO_NOT_COPY_VALUES, &user.Jacprhs));
28080ab5e31SHong Zhang PetscCall(MatZeroEntries(user.Jacprhs));
281c4762a1bSJed Brown
282c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
283c4762a1bSJed Brown Create timestepping solver context
284c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2859566063dSJacob Faibussowitsch PetscCall(TSCreate(PETSC_COMM_WORLD, &ts));
2869566063dSJacob Faibussowitsch PetscCall(TSSetEquationType(ts, TS_EQ_ODE_EXPLICIT)); /* less Jacobian evaluations when adjoint BEuler is used, otherwise no effect */
28780ab5e31SHong Zhang if (user.imex) {
28880ab5e31SHong Zhang PetscCall(TSSetIFunction(ts, NULL, IFunction, &user));
28980ab5e31SHong Zhang PetscCall(TSSetIJacobian(ts, user.A, user.A, IJacobian, &user));
29080ab5e31SHong Zhang PetscCall(TSSetIJacobianP(ts, user.Jacp, IJacobianP, &user));
29180ab5e31SHong Zhang PetscCall(TSSetRHSFunction(ts, NULL, RHSFunction, &user));
29280ab5e31SHong Zhang PetscCall(TSSetRHSJacobian(ts, user.B, NULL, RHSJacobian, &user));
29380ab5e31SHong Zhang PetscCall(TSSetRHSJacobianP(ts, user.Jacprhs, NULL, &user));
29480ab5e31SHong Zhang PetscCall(TSSetType(ts, TSARKIMEX));
29580ab5e31SHong Zhang } else {
296c4762a1bSJed Brown if (implicitform) {
2979566063dSJacob Faibussowitsch PetscCall(TSSetIFunction(ts, NULL, IFunction, &user));
2989566063dSJacob Faibussowitsch PetscCall(TSSetIJacobian(ts, user.A, user.A, IJacobian, &user));
29980ab5e31SHong Zhang PetscCall(TSSetIJacobianP(ts, user.Jacp, IJacobianP, &user));
3009566063dSJacob Faibussowitsch PetscCall(TSSetType(ts, TSCN));
301c4762a1bSJed Brown } else {
3029566063dSJacob Faibussowitsch PetscCall(TSSetRHSFunction(ts, NULL, RHSFunction, &user));
3039566063dSJacob Faibussowitsch PetscCall(TSSetRHSJacobian(ts, user.A, user.A, RHSJacobian, &user));
30480ab5e31SHong Zhang PetscCall(TSSetRHSJacobianP(ts, user.Jacp, RHSJacobianP, &user));
3059566063dSJacob Faibussowitsch PetscCall(TSSetType(ts, TSRK));
306c4762a1bSJed Brown }
30780ab5e31SHong Zhang }
3089566063dSJacob Faibussowitsch PetscCall(TSSetMaxTime(ts, user.ftime));
3099566063dSJacob Faibussowitsch PetscCall(TSSetTimeStep(ts, 0.001));
3109566063dSJacob Faibussowitsch PetscCall(TSSetExactFinalTime(ts, TS_EXACTFINALTIME_MATCHSTEP));
3119566063dSJacob Faibussowitsch if (monitor) PetscCall(TSMonitorSet(ts, Monitor, &user, NULL));
312c4762a1bSJed Brown
313c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
314c4762a1bSJed Brown Set initial conditions
315c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3169566063dSJacob Faibussowitsch PetscCall(VecGetArray(user.U, &x_ptr));
317c4762a1bSJed Brown x_ptr[0] = 2.0;
318c4762a1bSJed Brown x_ptr[1] = -2.0 / 3.0 + 10.0 / (81.0 * user.mu) - 292.0 / (2187.0 * user.mu * user.mu);
3199566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(user.U, &x_ptr));
3209566063dSJacob Faibussowitsch PetscCall(TSSetTimeStep(ts, 0.001));
321c4762a1bSJed Brown
322c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
323c4762a1bSJed Brown Save trajectory of solution so that TSAdjointSolve() may be used
324c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3259566063dSJacob Faibussowitsch PetscCall(TSSetSaveTrajectory(ts));
326c4762a1bSJed Brown
327c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
328c4762a1bSJed Brown Set runtime options
329c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3309566063dSJacob Faibussowitsch PetscCall(TSSetFromOptions(ts));
331c4762a1bSJed Brown
3329566063dSJacob Faibussowitsch PetscCall(TSSolve(ts, user.U));
3339566063dSJacob Faibussowitsch PetscCall(TSGetSolveTime(ts, &user.ftime));
3349566063dSJacob Faibussowitsch PetscCall(TSGetStepNumber(ts, &user.steps));
335c4762a1bSJed Brown
336c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
337c4762a1bSJed Brown Adjoint model starts here
338c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3399566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(user.A, &user.lambda[0], NULL));
340c4762a1bSJed Brown /* Set initial conditions for the adjoint integration */
3419566063dSJacob Faibussowitsch PetscCall(VecGetArray(user.lambda[0], &y_ptr));
3429371c9d4SSatish Balay y_ptr[0] = 1.0;
3439371c9d4SSatish Balay y_ptr[1] = 0.0;
3449566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(user.lambda[0], &y_ptr));
3459566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(user.A, &user.lambda[1], NULL));
3469566063dSJacob Faibussowitsch PetscCall(VecGetArray(user.lambda[1], &y_ptr));
3479371c9d4SSatish Balay y_ptr[0] = 0.0;
3489371c9d4SSatish Balay y_ptr[1] = 1.0;
3499566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(user.lambda[1], &y_ptr));
350c4762a1bSJed Brown
3519566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(user.Jacp, &user.mup[0], NULL));
3529566063dSJacob Faibussowitsch PetscCall(VecGetArray(user.mup[0], &x_ptr));
353c4762a1bSJed Brown x_ptr[0] = 0.0;
3549566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(user.mup[0], &x_ptr));
3559566063dSJacob Faibussowitsch PetscCall(MatCreateVecs(user.Jacp, &user.mup[1], NULL));
3569566063dSJacob Faibussowitsch PetscCall(VecGetArray(user.mup[1], &x_ptr));
357c4762a1bSJed Brown x_ptr[0] = 0.0;
3589566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(user.mup[1], &x_ptr));
359c4762a1bSJed Brown
3609566063dSJacob Faibussowitsch PetscCall(TSSetCostGradients(ts, 2, user.lambda, user.mup));
361c4762a1bSJed Brown
3629566063dSJacob Faibussowitsch PetscCall(TSAdjointSolve(ts));
363c4762a1bSJed Brown
3649566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\n sensitivity wrt initial conditions: d[y(tf)]/d[y0] d[y(tf)]/d[z0]\n"));
3659566063dSJacob Faibussowitsch PetscCall(VecView(user.lambda[0], PETSC_VIEWER_STDOUT_WORLD));
3669566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\n sensitivity wrt initial conditions: d[z(tf)]/d[y0] d[z(tf)]/d[z0]\n"));
3679566063dSJacob Faibussowitsch PetscCall(VecView(user.lambda[1], PETSC_VIEWER_STDOUT_WORLD));
368c4762a1bSJed Brown
3699566063dSJacob Faibussowitsch PetscCall(VecGetArray(user.mup[0], &x_ptr));
3709566063dSJacob Faibussowitsch PetscCall(VecGetArray(user.lambda[0], &y_ptr));
371c4762a1bSJed Brown derp = y_ptr[1] * (-10.0 / (81.0 * user.mu * user.mu) + 2.0 * 292.0 / (2187.0 * user.mu * user.mu * user.mu)) + x_ptr[0];
3729566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(user.mup[0], &x_ptr));
3739566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(user.lambda[0], &y_ptr));
3749566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\n sensitivity wrt parameters: d[y(tf)]/d[mu]\n%g\n", (double)PetscRealPart(derp)));
375c4762a1bSJed Brown
3769566063dSJacob Faibussowitsch PetscCall(VecGetArray(user.mup[1], &x_ptr));
3779566063dSJacob Faibussowitsch PetscCall(VecGetArray(user.lambda[1], &y_ptr));
378c4762a1bSJed Brown derp = y_ptr[1] * (-10.0 / (81.0 * user.mu * user.mu) + 2.0 * 292.0 / (2187.0 * user.mu * user.mu * user.mu)) + x_ptr[0];
3799566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(user.mup[1], &x_ptr));
3809566063dSJacob Faibussowitsch PetscCall(VecRestoreArray(user.lambda[1], &y_ptr));
3819566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "\n sensivitity wrt parameters: d[z(tf)]/d[mu]\n%g\n", (double)PetscRealPart(derp)));
382c4762a1bSJed Brown
383c4762a1bSJed Brown /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
384c4762a1bSJed Brown Free work space. All PETSc objects should be destroyed when they
385c4762a1bSJed Brown are no longer needed.
386c4762a1bSJed Brown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
3879566063dSJacob Faibussowitsch PetscCall(MatDestroy(&user.A));
38880ab5e31SHong Zhang PetscCall(MatDestroy(&user.B));
3899566063dSJacob Faibussowitsch PetscCall(MatDestroy(&user.Jacp));
39080ab5e31SHong Zhang PetscCall(MatDestroy(&user.Jacprhs));
3919566063dSJacob Faibussowitsch PetscCall(VecDestroy(&user.U));
3929566063dSJacob Faibussowitsch PetscCall(VecDestroy(&user.lambda[0]));
3939566063dSJacob Faibussowitsch PetscCall(VecDestroy(&user.lambda[1]));
3949566063dSJacob Faibussowitsch PetscCall(VecDestroy(&user.mup[0]));
3959566063dSJacob Faibussowitsch PetscCall(VecDestroy(&user.mup[1]));
3969566063dSJacob Faibussowitsch PetscCall(TSDestroy(&ts));
397c4762a1bSJed Brown
3989566063dSJacob Faibussowitsch PetscCall(PetscFinalize());
399b122ec5aSJacob Faibussowitsch return 0;
400c4762a1bSJed Brown }
401c4762a1bSJed Brown
402c4762a1bSJed Brown /*TEST
403c4762a1bSJed Brown
404c4762a1bSJed Brown test:
405c4762a1bSJed Brown requires: revolve
406188af4bfSBarry Smith args: -monitor 0 -ts_type theta -ts_theta_endpoint -ts_theta_theta 0.5 -viewer_binary_skip_info -ts_time_step 0.001 -mu 100000
407c4762a1bSJed Brown
408c4762a1bSJed Brown test:
409c4762a1bSJed Brown suffix: 2
410188af4bfSBarry Smith args: -ts_type cn -ts_time_step 0.001 -mu 100000 -ts_max_steps 15 -ts_trajectory_type memory -ts_trajectory_solution_only
411c4762a1bSJed Brown
412c4762a1bSJed Brown test:
413c4762a1bSJed Brown suffix: 3
414188af4bfSBarry Smith args: -ts_type cn -ts_time_step 0.001 -mu 100000 -ts_max_steps 15 -ts_trajectory_type memory -ts_trajectory_solution_only 0
415c4762a1bSJed Brown output_file: output/ex20adj_2.out
416c4762a1bSJed Brown
417c4762a1bSJed Brown test:
418c4762a1bSJed Brown suffix: 4
419188af4bfSBarry Smith args: -ts_type cn -ts_time_step 0.001 -mu 100000 -ts_max_steps 15 -ts_trajectory_type memory -ts_trajectory_stride 5 -ts_trajectory_solution_only -ts_trajectory_save_stack
420c4762a1bSJed Brown output_file: output/ex20adj_2.out
421c4762a1bSJed Brown
422c4762a1bSJed Brown test:
423c4762a1bSJed Brown suffix: 5
424188af4bfSBarry Smith args: -ts_type cn -ts_time_step 0.001 -mu 100000 -ts_max_steps 15 -ts_trajectory_type memory -ts_trajectory_stride 5 -ts_trajectory_solution_only 0 -ts_trajectory_save_stack
425c4762a1bSJed Brown output_file: output/ex20adj_2.out
426c4762a1bSJed Brown
427c4762a1bSJed Brown test:
428c4762a1bSJed Brown suffix: 6
429188af4bfSBarry Smith args: -ts_type cn -ts_time_step 0.001 -mu 100000 -ts_max_steps 15 -ts_trajectory_type memory -ts_trajectory_stride 5 -ts_trajectory_solution_only -ts_trajectory_save_stack 0
430c4762a1bSJed Brown output_file: output/ex20adj_2.out
431c4762a1bSJed Brown
432c4762a1bSJed Brown test:
433c4762a1bSJed Brown suffix: 7
434188af4bfSBarry Smith args: -ts_type cn -ts_time_step 0.001 -mu 100000 -ts_max_steps 15 -ts_trajectory_type memory -ts_trajectory_stride 5 -ts_trajectory_solution_only 0 -ts_trajectory_save_stack 0
435c4762a1bSJed Brown output_file: output/ex20adj_2.out
436c4762a1bSJed Brown
437c4762a1bSJed Brown test:
438c4762a1bSJed Brown suffix: 8
43960f0b76eSHong Zhang requires: revolve !cams
440188af4bfSBarry Smith args: -ts_type cn -ts_time_step 0.001 -mu 100000 -ts_max_steps 15 -ts_trajectory_type memory -ts_trajectory_max_cps_ram 5 -ts_trajectory_solution_only -ts_trajectory_monitor
441c4762a1bSJed Brown output_file: output/ex20adj_3.out
442c4762a1bSJed Brown
443c4762a1bSJed Brown test:
444c4762a1bSJed Brown suffix: 9
44560f0b76eSHong Zhang requires: revolve !cams
446188af4bfSBarry Smith args: -ts_type cn -ts_time_step 0.001 -mu 100000 -ts_max_steps 15 -ts_trajectory_type memory -ts_trajectory_max_cps_ram 5 -ts_trajectory_solution_only 0 -ts_trajectory_monitor
447c4762a1bSJed Brown output_file: output/ex20adj_4.out
448c4762a1bSJed Brown
449c4762a1bSJed Brown test:
450c4762a1bSJed Brown requires: revolve
451c4762a1bSJed Brown suffix: 10
452188af4bfSBarry Smith args: -ts_type cn -ts_time_step 0.001 -mu 100000 -ts_max_steps 15 -ts_trajectory_type memory -ts_trajectory_max_cps_ram 5 -ts_trajectory_revolve_online -ts_trajectory_solution_only
453c4762a1bSJed Brown output_file: output/ex20adj_2.out
454c4762a1bSJed Brown
455c4762a1bSJed Brown test:
456c4762a1bSJed Brown requires: revolve
457c4762a1bSJed Brown suffix: 11
458188af4bfSBarry Smith args: -ts_type cn -ts_time_step 0.001 -mu 100000 -ts_max_steps 15 -ts_trajectory_type memory -ts_trajectory_max_cps_ram 5 -ts_trajectory_revolve_online -ts_trajectory_solution_only 0
459c4762a1bSJed Brown output_file: output/ex20adj_2.out
460c4762a1bSJed Brown
461c4762a1bSJed Brown test:
462c4762a1bSJed Brown suffix: 12
463c4762a1bSJed Brown requires: revolve
464188af4bfSBarry Smith args: -ts_type cn -ts_time_step 0.001 -mu 100000 -ts_max_steps 15 -ts_trajectory_type memory -ts_trajectory_max_cps_ram 3 -ts_trajectory_max_cps_disk 8 -ts_trajectory_solution_only
465c4762a1bSJed Brown output_file: output/ex20adj_2.out
466c4762a1bSJed Brown
467c4762a1bSJed Brown test:
468c4762a1bSJed Brown suffix: 13
469c4762a1bSJed Brown requires: revolve
470188af4bfSBarry Smith args: -ts_type cn -ts_time_step 0.001 -mu 100000 -ts_max_steps 15 -ts_trajectory_type memory -ts_trajectory_max_cps_ram 3 -ts_trajectory_max_cps_disk 8 -ts_trajectory_solution_only 0
471c4762a1bSJed Brown output_file: output/ex20adj_2.out
472c4762a1bSJed Brown
473c4762a1bSJed Brown test:
474c4762a1bSJed Brown suffix: 14
475c4762a1bSJed Brown requires: revolve
476188af4bfSBarry Smith args: -ts_type cn -ts_time_step 0.001 -mu 100000 -ts_max_steps 15 -ts_trajectory_type memory -ts_trajectory_max_cps_ram 3 -ts_trajectory_stride 5 -ts_trajectory_solution_only -ts_trajectory_save_stack
477c4762a1bSJed Brown output_file: output/ex20adj_2.out
478c4762a1bSJed Brown
479c4762a1bSJed Brown test:
480c4762a1bSJed Brown suffix: 15
481c4762a1bSJed Brown requires: revolve
482188af4bfSBarry Smith args: -ts_type cn -ts_time_step 0.001 -mu 100000 -ts_max_steps 15 -ts_trajectory_type memory -ts_trajectory_max_cps_ram 3 -ts_trajectory_stride 5 -ts_trajectory_solution_only -ts_trajectory_save_stack 0
483c4762a1bSJed Brown output_file: output/ex20adj_2.out
484c4762a1bSJed Brown
485c4762a1bSJed Brown test:
486c4762a1bSJed Brown suffix: 16
487c4762a1bSJed Brown requires: revolve
488188af4bfSBarry Smith args: -ts_type cn -ts_time_step 0.001 -mu 100000 -ts_max_steps 15 -ts_trajectory_type memory -ts_trajectory_max_cps_ram 3 -ts_trajectory_stride 5 -ts_trajectory_solution_only 0 -ts_trajectory_save_stack
489c4762a1bSJed Brown output_file: output/ex20adj_2.out
490c4762a1bSJed Brown
491c4762a1bSJed Brown test:
492c4762a1bSJed Brown suffix: 17
493c4762a1bSJed Brown requires: revolve
494188af4bfSBarry Smith args: -ts_type cn -ts_time_step 0.001 -mu 100000 -ts_max_steps 15 -ts_trajectory_type memory -ts_trajectory_max_cps_ram 3 -ts_trajectory_stride 5 -ts_trajectory_solution_only 0 -ts_trajectory_save_stack 0
495c4762a1bSJed Brown output_file: output/ex20adj_2.out
496c4762a1bSJed Brown
497c4762a1bSJed Brown test:
498c4762a1bSJed Brown suffix: 18
499c4762a1bSJed Brown requires: revolve
500188af4bfSBarry Smith args: -ts_type cn -ts_time_step 0.001 -mu 100000 -ts_max_steps 15 -ts_trajectory_type memory -ts_trajectory_max_cps_ram 3 -ts_trajectory_max_cps_disk 8 -ts_trajectory_stride 5 -ts_trajectory_solution_only -ts_trajectory_save_stack
501c4762a1bSJed Brown output_file: output/ex20adj_2.out
502c4762a1bSJed Brown
503c4762a1bSJed Brown test:
504c4762a1bSJed Brown suffix: 19
505c4762a1bSJed Brown requires: revolve
506188af4bfSBarry Smith args: -ts_type cn -ts_time_step 0.001 -mu 100000 -ts_max_steps 15 -ts_trajectory_type memory -ts_trajectory_max_cps_ram 3 -ts_trajectory_max_cps_disk 8 -ts_trajectory_stride 5 -ts_trajectory_solution_only 0 -ts_trajectory_save_stack
507c4762a1bSJed Brown output_file: output/ex20adj_2.out
508c4762a1bSJed Brown
509c4762a1bSJed Brown test:
510c4762a1bSJed Brown suffix: 20
511c4762a1bSJed Brown requires: revolve
512188af4bfSBarry Smith args: -ts_type cn -ts_time_step 0.001 -mu 100000 -ts_max_steps 15 -ts_trajectory_type memory -ts_trajectory_max_cps_ram 3 -ts_trajectory_max_cps_disk 8 -ts_trajectory_solution_only 0
513c4762a1bSJed Brown output_file: output/ex20adj_2.out
514c4762a1bSJed Brown
515c4762a1bSJed Brown test:
516c4762a1bSJed Brown suffix: 21
517c4762a1bSJed Brown requires: revolve
518188af4bfSBarry Smith args: -ts_type cn -ts_time_step 0.001 -mu 100000 -ts_max_steps 15 -ts_trajectory_type memory -ts_trajectory_max_cps_ram 3 -ts_trajectory_max_cps_disk 8 -ts_trajectory_stride 5 -ts_trajectory_solution_only 0 -ts_trajectory_save_stack 0
519c4762a1bSJed Brown output_file: output/ex20adj_2.out
520c4762a1bSJed Brown
521c4762a1bSJed Brown test:
522c4762a1bSJed Brown suffix: 22
523188af4bfSBarry Smith args: -ts_type beuler -ts_time_step 0.001 -mu 100000 -ts_max_steps 15 -ts_trajectory_type memory -ts_trajectory_solution_only
524c4762a1bSJed Brown output_file: output/ex20adj_2.out
525cc4f23bcSHong Zhang
526cc4f23bcSHong Zhang test:
527cc4f23bcSHong Zhang suffix: 23
528cc4f23bcSHong Zhang requires: cams
529188af4bfSBarry Smith args: -ts_type cn -ts_time_step 0.001 -mu 100000 -ts_max_steps 15 -ts_trajectory_type memory -ts_trajectory_max_units_ram 5 -ts_trajectory_solution_only -ts_trajectory_monitor -ts_trajectory_memory_type cams
53060f0b76eSHong Zhang output_file: output/ex20adj_5.out
531cc4f23bcSHong Zhang
532cc4f23bcSHong Zhang test:
533cc4f23bcSHong Zhang suffix: 24
534cc4f23bcSHong Zhang requires: cams
535188af4bfSBarry Smith args: -ts_type cn -ts_time_step 0.001 -mu 100000 -ts_max_steps 15 -ts_trajectory_type memory -ts_trajectory_max_units_ram 5 -ts_trajectory_solution_only 0 -ts_trajectory_monitor -ts_trajectory_memory_type cams
53660f0b76eSHong Zhang output_file: output/ex20adj_6.out
537cc4f23bcSHong Zhang
53880ab5e31SHong Zhang test:
53980ab5e31SHong Zhang suffix: 25
54080ab5e31SHong Zhang args: -imexform -ts_max_steps 15 -ts_trajectory_type memory
54180ab5e31SHong Zhang output_file: output/ex20adj_imex.out
542c4762a1bSJed Brown TEST*/
543