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 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 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 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 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 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 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 */ 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 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