xref: /petsc/src/ts/tutorials/ex20adj.c (revision 4e8208cbcbc709572b8abe32f33c78b69c819375)
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