xref: /petsc/src/ts/tutorials/optimal_control/ex1.c (revision 4e278199b78715991f5c71ebbd945c1489263e6c)
1 #include <petsctao.h>
2 #include <petscts.h>
3 
4 typedef struct _n_aircraft *Aircraft;
5 struct _n_aircraft {
6   TS        ts,quadts;
7   Vec       V,W;    /* control variables V and W */
8   PetscInt  nsteps; /* number of time steps */
9   PetscReal ftime;
10   Mat       A,H;
11   Mat       Jacp,DRDU,DRDP;
12   Vec       U,Lambda[1],Mup[1],Lambda2[1],Mup2[1],Dir;
13   Vec       rhshp1[1],rhshp2[1],rhshp3[1],rhshp4[1],inthp1[1],inthp2[1],inthp3[1],inthp4[1];
14   PetscReal lv,lw;
15   PetscBool mf,eh;
16 };
17 
18 PetscErrorCode FormObjFunctionGradient(Tao,Vec,PetscReal *,Vec,void *);
19 PetscErrorCode FormObjHessian(Tao,Vec,Mat,Mat,void *);
20 PetscErrorCode ComputeObjHessianWithSOA(Vec,PetscScalar[],Aircraft);
21 PetscErrorCode MatrixFreeObjHessian(Tao,Vec,Mat,Mat,void *);
22 PetscErrorCode MyMatMult(Mat,Vec,Vec);
23 
24 static PetscErrorCode RHSFunction(TS ts,PetscReal t,Vec U,Vec F,void *ctx)
25 {
26   Aircraft          actx = (Aircraft)ctx;
27   const PetscScalar *u,*v,*w;
28   PetscScalar       *f;
29   PetscInt          step;
30   PetscErrorCode    ierr;
31 
32   PetscFunctionBeginUser;
33   ierr = TSGetStepNumber(ts,&step);CHKERRQ(ierr);
34   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
35   ierr = VecGetArrayRead(actx->V,&v);CHKERRQ(ierr);
36   ierr = VecGetArrayRead(actx->W,&w);CHKERRQ(ierr);
37   ierr = VecGetArray(F,&f);CHKERRQ(ierr);
38   f[0] = v[step]*PetscCosReal(w[step]);
39   f[1] = v[step]*PetscSinReal(w[step]);
40   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
41   ierr = VecRestoreArrayRead(actx->V,&v);CHKERRQ(ierr);
42   ierr = VecRestoreArrayRead(actx->W,&w);CHKERRQ(ierr);
43   ierr = VecRestoreArray(F,&f);CHKERRQ(ierr);
44   PetscFunctionReturn(0);
45 }
46 
47 static PetscErrorCode RHSJacobianP(TS ts,PetscReal t,Vec U,Mat A,void *ctx)
48 {
49   Aircraft          actx = (Aircraft)ctx;
50   const PetscScalar *u,*v,*w;
51   PetscInt          step,rows[2] = {0,1},rowcol[2];
52   PetscScalar       Jp[2][2];
53   PetscErrorCode    ierr;
54 
55   PetscFunctionBeginUser;
56   ierr = MatZeroEntries(A);CHKERRQ(ierr);
57   ierr = TSGetStepNumber(ts,&step);CHKERRQ(ierr);
58   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
59   ierr = VecGetArrayRead(actx->V,&v);CHKERRQ(ierr);
60   ierr = VecGetArrayRead(actx->W,&w);CHKERRQ(ierr);
61 
62   Jp[0][0] = PetscCosReal(w[step]);
63   Jp[0][1] = -v[step]*PetscSinReal(w[step]);
64   Jp[1][0] = PetscSinReal(w[step]);
65   Jp[1][1] = v[step]*PetscCosReal(w[step]);
66 
67   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
68   ierr = VecRestoreArrayRead(actx->V,&v);CHKERRQ(ierr);
69   ierr = VecRestoreArrayRead(actx->W,&w);CHKERRQ(ierr);
70 
71   rowcol[0] = 2*step;
72   rowcol[1] = 2*step+1;
73   ierr      = MatSetValues(A,2,rows,2,rowcol,&Jp[0][0],INSERT_VALUES);CHKERRQ(ierr);
74 
75   ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
76   ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
77   PetscFunctionReturn(0);
78 }
79 
80 static PetscErrorCode RHSHessianProductUU(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV,void *ctx)
81 {
82   PetscFunctionBeginUser;
83   PetscFunctionReturn(0);
84 }
85 
86 static PetscErrorCode RHSHessianProductUP(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV,void *ctx)
87 {
88   PetscFunctionBeginUser;
89   PetscFunctionReturn(0);
90 }
91 
92 static PetscErrorCode RHSHessianProductPU(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV,void *ctx)
93 {
94   PetscFunctionBeginUser;
95   PetscFunctionReturn(0);
96 }
97 
98 static PetscErrorCode RHSHessianProductPP(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV,void *ctx)
99 {
100   Aircraft          actx = (Aircraft)ctx;
101   const PetscScalar *v,*w,*vl,*vr,*u;
102   PetscScalar       *vhv;
103   PetscScalar       dJpdP[2][2][2]={{{0}}};
104   PetscInt          step,i,j,k;
105   PetscErrorCode    ierr;
106 
107   PetscFunctionBeginUser;
108   ierr = TSGetStepNumber(ts,&step);CHKERRQ(ierr);
109   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
110   ierr = VecGetArrayRead(actx->V,&v);CHKERRQ(ierr);
111   ierr = VecGetArrayRead(actx->W,&w);CHKERRQ(ierr);
112   ierr = VecGetArrayRead(Vl[0],&vl);CHKERRQ(ierr);
113   ierr = VecGetArrayRead(Vr,&vr);CHKERRQ(ierr);
114   ierr = VecSet(VHV[0],0.0);CHKERRQ(ierr);
115   ierr = VecGetArray(VHV[0],&vhv);CHKERRQ(ierr);
116 
117   dJpdP[0][0][1] = -PetscSinReal(w[step]);
118   dJpdP[0][1][0] = -PetscSinReal(w[step]);
119   dJpdP[0][1][1] = -v[step]*PetscCosReal(w[step]);
120   dJpdP[1][0][1] = PetscCosReal(w[step]);
121   dJpdP[1][1][0] = PetscCosReal(w[step]);
122   dJpdP[1][1][1] = -v[step]*PetscSinReal(w[step]);
123 
124   for (j=0; j<2; j++) {
125     vhv[2*step+j] = 0;
126     for (k=0; k<2; k++)
127       for (i=0; i<2; i++)
128         vhv[2*step+j] += vl[i]*dJpdP[i][j][k]*vr[2*step+k];
129   }
130   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
131   ierr = VecRestoreArrayRead(Vl[0],&vl);CHKERRQ(ierr);
132   ierr = VecRestoreArrayRead(Vr,&vr);CHKERRQ(ierr);
133   ierr = VecRestoreArray(VHV[0],&vhv);CHKERRQ(ierr);
134   PetscFunctionReturn(0);
135 }
136 
137 /* Vl in NULL,updates to VHV must be added */
138 static PetscErrorCode IntegrandHessianProductUU(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV,void *ctx)
139 {
140   Aircraft          actx = (Aircraft)ctx;
141   const PetscScalar *v,*w,*vr,*u;
142   PetscScalar       *vhv;
143   PetscScalar       dRudU[2][2]={{0}};
144   PetscInt          step,j,k;
145   PetscErrorCode    ierr;
146 
147   PetscFunctionBeginUser;
148   ierr = TSGetStepNumber(ts,&step);CHKERRQ(ierr);
149   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
150   ierr = VecGetArrayRead(actx->V,&v);CHKERRQ(ierr);
151   ierr = VecGetArrayRead(actx->W,&w);CHKERRQ(ierr);
152   ierr = VecGetArrayRead(Vr,&vr);CHKERRQ(ierr);
153   ierr = VecGetArray(VHV[0],&vhv);CHKERRQ(ierr);
154 
155   dRudU[0][0] = 2.0;
156   dRudU[1][1] = 2.0;
157 
158   for (j=0; j<2; j++) {
159     vhv[j] = 0;
160     for (k=0; k<2; k++)
161         vhv[j] += dRudU[j][k]*vr[k];
162   }
163   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
164   ierr = VecRestoreArrayRead(Vr,&vr);CHKERRQ(ierr);
165   ierr = VecRestoreArray(VHV[0],&vhv);CHKERRQ(ierr);
166   PetscFunctionReturn(0);
167 }
168 
169 static PetscErrorCode IntegrandHessianProductUP(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV,void *ctx)
170 {
171   PetscFunctionBeginUser;
172   PetscFunctionReturn(0);
173 }
174 
175 static PetscErrorCode IntegrandHessianProductPU(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV,void *ctx)
176 {
177   PetscFunctionBeginUser;
178   PetscFunctionReturn(0);
179 }
180 
181 static PetscErrorCode IntegrandHessianProductPP(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV,void *ctx)
182 {
183   PetscFunctionBeginUser;
184   PetscFunctionReturn(0);
185 }
186 
187 static PetscErrorCode CostIntegrand(TS ts,PetscReal t,Vec U,Vec R,void *ctx)
188 {
189   Aircraft          actx = (Aircraft)ctx;
190   PetscScalar       *r;
191   PetscReal         dx,dy;
192   const PetscScalar *u;
193   PetscErrorCode    ierr;
194 
195   PetscFunctionBegin;
196   ierr = VecGetArrayRead(U,&u);CHKERRQ(ierr);
197   ierr = VecGetArray(R,&r);CHKERRQ(ierr);
198   dx   = u[0] - actx->lv*t*PetscCosReal(actx->lw);
199   dy   = u[1] - actx->lv*t*PetscSinReal(actx->lw);
200   r[0] = dx*dx+dy*dy;
201   ierr = VecRestoreArray(R,&r);CHKERRQ(ierr);
202   ierr = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
203   PetscFunctionReturn(0);
204 }
205 
206 static PetscErrorCode DRDUJacobianTranspose(TS ts,PetscReal t,Vec U,Mat DRDU,Mat B,void *ctx)
207 {
208   Aircraft          actx = (Aircraft)ctx;
209   PetscScalar       drdu[2][1];
210   const PetscScalar *u;
211   PetscReal         dx,dy;
212   PetscInt          row[] = {0,1},col[] = {0};
213   PetscErrorCode    ierr;
214 
215   PetscFunctionBegin;
216   ierr    = VecGetArrayRead(U,&u);CHKERRQ(ierr);
217   dx      = u[0] - actx->lv*t*PetscCosReal(actx->lw);
218   dy      = u[1] - actx->lv*t*PetscSinReal(actx->lw);
219   drdu[0][0] = 2.*dx;
220   drdu[1][0] = 2.*dy;
221   ierr    = MatSetValues(DRDU,2,row,1,col,&drdu[0][0],INSERT_VALUES);CHKERRQ(ierr);
222   ierr    = VecRestoreArrayRead(U,&u);CHKERRQ(ierr);
223   ierr    = MatAssemblyBegin(DRDU,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
224   ierr    = MatAssemblyEnd(DRDU,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
225   PetscFunctionReturn(0);
226 }
227 
228 static PetscErrorCode DRDPJacobianTranspose(TS ts,PetscReal t,Vec U,Mat DRDP,void *ctx)
229 {
230   PetscErrorCode ierr;
231 
232   PetscFunctionBegin;
233   ierr = MatZeroEntries(DRDP);CHKERRQ(ierr);
234   ierr = MatAssemblyBegin(DRDP,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
235   ierr = MatAssemblyEnd(DRDP,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
236   PetscFunctionReturn(0);
237 }
238 
239 int main(int argc,char **argv)
240 {
241   Vec                P,PL,PU;
242   struct _n_aircraft aircraft;
243   PetscMPIInt        size;
244   Tao                tao;
245   KSP                ksp;
246   PC                 pc;
247   PetscScalar        *u,*p;
248   PetscInt           i;
249   PetscErrorCode     ierr;
250 
251   /* Initialize program */
252   ierr = PetscInitialize(&argc,&argv,NULL,NULL);if (ierr) return ierr;
253   ierr = MPI_Comm_size(PETSC_COMM_WORLD,&size);CHKERRMPI(ierr);
254   if (size != 1) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_WRONG_MPI_SIZE,"This is a uniprocessor example only!");
255 
256   /* Parameter settings */
257   aircraft.ftime = 1.;   /* time interval in hour */
258   aircraft.nsteps = 10; /* number of steps */
259   aircraft.lv = 2.0; /* leader speed in kmph */
260   aircraft.lw = PETSC_PI/4.; /* leader heading angle */
261 
262   ierr = PetscOptionsGetReal(NULL,NULL,"-ftime",&aircraft.ftime,NULL);CHKERRQ(ierr);
263   ierr = PetscOptionsGetInt(NULL,NULL,"-nsteps",&aircraft.nsteps,NULL);CHKERRQ(ierr);
264   ierr = PetscOptionsHasName(NULL,NULL,"-matrixfree",&aircraft.mf);CHKERRQ(ierr);
265   ierr = PetscOptionsHasName(NULL,NULL,"-exacthessian",&aircraft.eh);CHKERRQ(ierr);
266 
267   /* Create TAO solver and set desired solution method */
268   ierr = TaoCreate(PETSC_COMM_WORLD,&tao);CHKERRQ(ierr);
269   ierr = TaoSetType(tao,TAOBQNLS);CHKERRQ(ierr);
270 
271   /* Create necessary matrix and vectors, solve same ODE on every process */
272   ierr = MatCreate(PETSC_COMM_WORLD,&aircraft.A);CHKERRQ(ierr);
273   ierr = MatSetSizes(aircraft.A,PETSC_DECIDE,PETSC_DECIDE,2,2);CHKERRQ(ierr);
274   ierr = MatSetFromOptions(aircraft.A);CHKERRQ(ierr);
275   ierr = MatSetUp(aircraft.A);CHKERRQ(ierr);
276   ierr = MatAssemblyBegin(aircraft.A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
277   ierr = MatAssemblyEnd(aircraft.A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
278   ierr = MatShift(aircraft.A,1);CHKERRQ(ierr);
279   ierr = MatShift(aircraft.A,-1);CHKERRQ(ierr);
280 
281   ierr = MatCreate(PETSC_COMM_WORLD,&aircraft.Jacp);CHKERRQ(ierr);
282   ierr = MatSetSizes(aircraft.Jacp,PETSC_DECIDE,PETSC_DECIDE,2,2*aircraft.nsteps);CHKERRQ(ierr);
283   ierr = MatSetFromOptions(aircraft.Jacp);CHKERRQ(ierr);
284   ierr = MatSetUp(aircraft.Jacp);CHKERRQ(ierr);
285   ierr = MatCreateDense(PETSC_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,2*aircraft.nsteps,1,NULL,&aircraft.DRDP);CHKERRQ(ierr);
286   ierr = MatSetUp(aircraft.DRDP);CHKERRQ(ierr);
287   ierr = MatCreateDense(PETSC_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,2,1,NULL,&aircraft.DRDU);CHKERRQ(ierr);
288   ierr = MatSetUp(aircraft.DRDU);CHKERRQ(ierr);
289 
290   /* Create timestepping solver context */
291   ierr = TSCreate(PETSC_COMM_WORLD,&aircraft.ts);CHKERRQ(ierr);
292   ierr = TSSetType(aircraft.ts,TSRK);CHKERRQ(ierr);
293   ierr = TSSetRHSFunction(aircraft.ts,NULL,RHSFunction,&aircraft);CHKERRQ(ierr);
294   ierr = TSSetRHSJacobian(aircraft.ts,aircraft.A,aircraft.A,TSComputeRHSJacobianConstant,&aircraft);CHKERRQ(ierr);
295   ierr = TSSetRHSJacobianP(aircraft.ts,aircraft.Jacp,RHSJacobianP,&aircraft);CHKERRQ(ierr);
296   ierr = TSSetExactFinalTime(aircraft.ts,TS_EXACTFINALTIME_MATCHSTEP);CHKERRQ(ierr);
297   ierr = TSSetEquationType(aircraft.ts,TS_EQ_ODE_EXPLICIT);CHKERRQ(ierr); /* less Jacobian evaluations when adjoint BEuler is used, otherwise no effect */
298 
299   /* Set initial conditions */
300   ierr = MatCreateVecs(aircraft.A,&aircraft.U,NULL);CHKERRQ(ierr);
301   ierr = TSSetSolution(aircraft.ts,aircraft.U);CHKERRQ(ierr);
302   ierr = VecGetArray(aircraft.U,&u);CHKERRQ(ierr);
303   u[0] = 1.5;
304   u[1] = 0;
305   ierr = VecRestoreArray(aircraft.U,&u);CHKERRQ(ierr);
306   ierr = VecCreate(PETSC_COMM_WORLD,&aircraft.V);CHKERRQ(ierr);
307   ierr = VecSetSizes(aircraft.V,PETSC_DECIDE,aircraft.nsteps);CHKERRQ(ierr);
308   ierr = VecSetUp(aircraft.V);CHKERRQ(ierr);
309   ierr = VecDuplicate(aircraft.V,&aircraft.W);CHKERRQ(ierr);
310   ierr = VecSet(aircraft.V,1.);CHKERRQ(ierr);
311   ierr = VecSet(aircraft.W,PETSC_PI/4.);CHKERRQ(ierr);
312 
313   /* Save trajectory of solution so that TSAdjointSolve() may be used */
314   ierr = TSSetSaveTrajectory(aircraft.ts);CHKERRQ(ierr);
315 
316   /* Set sensitivity context */
317   ierr = TSCreateQuadratureTS(aircraft.ts,PETSC_FALSE,&aircraft.quadts);CHKERRQ(ierr);
318   ierr = TSSetRHSFunction(aircraft.quadts,NULL,(TSRHSFunction)CostIntegrand,&aircraft);CHKERRQ(ierr);
319   ierr = TSSetRHSJacobian(aircraft.quadts,aircraft.DRDU,aircraft.DRDU,(TSRHSJacobian)DRDUJacobianTranspose,&aircraft);CHKERRQ(ierr);
320   ierr = TSSetRHSJacobianP(aircraft.quadts,aircraft.DRDP,(TSRHSJacobianP)DRDPJacobianTranspose,&aircraft);CHKERRQ(ierr);
321   ierr = MatCreateVecs(aircraft.A,&aircraft.Lambda[0],NULL);CHKERRQ(ierr);
322   ierr = MatCreateVecs(aircraft.Jacp,&aircraft.Mup[0],NULL);CHKERRQ(ierr);
323   if (aircraft.eh) {
324     ierr = MatCreateVecs(aircraft.A,&aircraft.rhshp1[0],NULL);CHKERRQ(ierr);
325     ierr = MatCreateVecs(aircraft.A,&aircraft.rhshp2[0],NULL);CHKERRQ(ierr);
326     ierr = MatCreateVecs(aircraft.Jacp,&aircraft.rhshp3[0],NULL);CHKERRQ(ierr);
327     ierr = MatCreateVecs(aircraft.Jacp,&aircraft.rhshp4[0],NULL);CHKERRQ(ierr);
328     ierr = MatCreateVecs(aircraft.DRDU,&aircraft.inthp1[0],NULL);CHKERRQ(ierr);
329     ierr = MatCreateVecs(aircraft.DRDU,&aircraft.inthp2[0],NULL);CHKERRQ(ierr);
330     ierr = MatCreateVecs(aircraft.DRDP,&aircraft.inthp3[0],NULL);CHKERRQ(ierr);
331     ierr = MatCreateVecs(aircraft.DRDP,&aircraft.inthp4[0],NULL);CHKERRQ(ierr);
332     ierr = MatCreateVecs(aircraft.Jacp,&aircraft.Dir,NULL);CHKERRQ(ierr);
333     ierr = TSSetRHSHessianProduct(aircraft.ts,aircraft.rhshp1,RHSHessianProductUU,aircraft.rhshp2,RHSHessianProductUP,aircraft.rhshp3,RHSHessianProductPU,aircraft.rhshp4,RHSHessianProductPP,&aircraft);CHKERRQ(ierr);
334     ierr = TSSetRHSHessianProduct(aircraft.quadts,aircraft.inthp1,IntegrandHessianProductUU,aircraft.inthp2,IntegrandHessianProductUP,aircraft.inthp3,IntegrandHessianProductPU,aircraft.inthp4,IntegrandHessianProductPP,&aircraft);CHKERRQ(ierr);
335     ierr = MatCreateVecs(aircraft.A,&aircraft.Lambda2[0],NULL);CHKERRQ(ierr);
336     ierr = MatCreateVecs(aircraft.Jacp,&aircraft.Mup2[0],NULL);CHKERRQ(ierr);
337   }
338   ierr = TSSetFromOptions(aircraft.ts);CHKERRQ(ierr);
339   ierr = TSSetMaxTime(aircraft.ts,aircraft.ftime);CHKERRQ(ierr);
340   ierr = TSSetTimeStep(aircraft.ts,aircraft.ftime/aircraft.nsteps);CHKERRQ(ierr);
341 
342   /* Set initial solution guess */
343   ierr = MatCreateVecs(aircraft.Jacp,&P,NULL);CHKERRQ(ierr);
344   ierr = VecGetArray(P,&p);CHKERRQ(ierr);
345   for (i=0; i<aircraft.nsteps; i++) {
346     p[2*i] = 2.0;
347     p[2*i+1] = PETSC_PI/2.0;
348   }
349   ierr = VecRestoreArray(P,&p);CHKERRQ(ierr);
350   ierr = VecDuplicate(P,&PU);CHKERRQ(ierr);
351   ierr = VecDuplicate(P,&PL);CHKERRQ(ierr);
352   ierr = VecGetArray(PU,&p);CHKERRQ(ierr);
353   for (i=0; i<aircraft.nsteps; i++) {
354     p[2*i] = 2.0;
355     p[2*i+1] = PETSC_PI;
356   }
357   ierr = VecRestoreArray(PU,&p);CHKERRQ(ierr);
358   ierr = VecGetArray(PL,&p);CHKERRQ(ierr);
359   for (i=0; i<aircraft.nsteps; i++) {
360     p[2*i] = 0.0;
361     p[2*i+1] = -PETSC_PI;
362   }
363   ierr = VecRestoreArray(PL,&p);CHKERRQ(ierr);
364 
365   ierr = TaoSetInitialVector(tao,P);CHKERRQ(ierr);
366   ierr = TaoSetVariableBounds(tao,PL,PU);CHKERRQ(ierr);
367   /* Set routine for function and gradient evaluation */
368   ierr = TaoSetObjectiveAndGradientRoutine(tao,FormObjFunctionGradient,(void *)&aircraft);CHKERRQ(ierr);
369 
370   if (aircraft.eh) {
371     if (aircraft.mf) {
372       ierr = MatCreateShell(PETSC_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,2*aircraft.nsteps,2*aircraft.nsteps,(void*)&aircraft,&aircraft.H);CHKERRQ(ierr);
373       ierr = MatShellSetOperation(aircraft.H,MATOP_MULT,(void(*)(void))MyMatMult);CHKERRQ(ierr);
374       ierr = MatSetOption(aircraft.H,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
375       ierr = TaoSetHessianRoutine(tao,aircraft.H,aircraft.H,MatrixFreeObjHessian,(void*)&aircraft);CHKERRQ(ierr);
376     } else {
377       ierr = MatCreateDense(MPI_COMM_WORLD,PETSC_DETERMINE,PETSC_DETERMINE,2*aircraft.nsteps,2*aircraft.nsteps,NULL,&(aircraft.H));CHKERRQ(ierr);
378       ierr = MatSetOption(aircraft.H,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr);
379       ierr = TaoSetHessianRoutine(tao,aircraft.H,aircraft.H,FormObjHessian,(void *)&aircraft);CHKERRQ(ierr);
380     }
381   }
382 
383   /* Check for any TAO command line options */
384   ierr = TaoGetKSP(tao,&ksp);CHKERRQ(ierr);
385   if (ksp) {
386     ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr);
387     ierr = PCSetType(pc,PCNONE);CHKERRQ(ierr);
388   }
389   ierr = TaoSetFromOptions(tao);CHKERRQ(ierr);
390 
391   ierr = TaoSolve(tao);CHKERRQ(ierr);
392   ierr = VecView(P,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
393 
394   /* Free TAO data structures */
395   ierr = TaoDestroy(&tao);CHKERRQ(ierr);
396 
397   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
398      Free work space.  All PETSc objects should be destroyed when they
399      are no longer needed.
400    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
401   ierr = TSDestroy(&aircraft.ts);CHKERRQ(ierr);
402   ierr = MatDestroy(&aircraft.A);CHKERRQ(ierr);
403   ierr = VecDestroy(&aircraft.U);CHKERRQ(ierr);
404   ierr = VecDestroy(&aircraft.V);CHKERRQ(ierr);
405   ierr = VecDestroy(&aircraft.W);CHKERRQ(ierr);
406   ierr = VecDestroy(&P);CHKERRQ(ierr);
407   ierr = VecDestroy(&PU);CHKERRQ(ierr);
408   ierr = VecDestroy(&PL);CHKERRQ(ierr);
409   ierr = MatDestroy(&aircraft.Jacp);CHKERRQ(ierr);
410   ierr = MatDestroy(&aircraft.DRDU);CHKERRQ(ierr);
411   ierr = MatDestroy(&aircraft.DRDP);CHKERRQ(ierr);
412   ierr = VecDestroy(&aircraft.Lambda[0]);CHKERRQ(ierr);
413   ierr = VecDestroy(&aircraft.Mup[0]);CHKERRQ(ierr);
414   ierr = VecDestroy(&P);CHKERRQ(ierr);
415   if (aircraft.eh) {
416     ierr = VecDestroy(&aircraft.Lambda2[0]);CHKERRQ(ierr);
417     ierr = VecDestroy(&aircraft.Mup2[0]);CHKERRQ(ierr);
418     ierr = VecDestroy(&aircraft.Dir);CHKERRQ(ierr);
419     ierr = VecDestroy(&aircraft.rhshp1[0]);CHKERRQ(ierr);
420     ierr = VecDestroy(&aircraft.rhshp2[0]);CHKERRQ(ierr);
421     ierr = VecDestroy(&aircraft.rhshp3[0]);CHKERRQ(ierr);
422     ierr = VecDestroy(&aircraft.rhshp4[0]);CHKERRQ(ierr);
423     ierr = VecDestroy(&aircraft.inthp1[0]);CHKERRQ(ierr);
424     ierr = VecDestroy(&aircraft.inthp2[0]);CHKERRQ(ierr);
425     ierr = VecDestroy(&aircraft.inthp3[0]);CHKERRQ(ierr);
426     ierr = VecDestroy(&aircraft.inthp4[0]);CHKERRQ(ierr);
427     ierr = MatDestroy(&aircraft.H);CHKERRQ(ierr);
428   }
429   ierr = PetscFinalize();
430   return ierr;
431 }
432 
433 /*
434    FormObjFunctionGradient - Evaluates the function and corresponding gradient.
435 
436    Input Parameters:
437    tao - the Tao context
438    P   - the input vector
439    ctx - optional aircraft-defined context, as set by TaoSetObjectiveAndGradientRoutine()
440 
441    Output Parameters:
442    f   - the newly evaluated function
443    G   - the newly evaluated gradient
444 */
445 PetscErrorCode FormObjFunctionGradient(Tao tao,Vec P,PetscReal *f,Vec G,void *ctx)
446 {
447   Aircraft          actx = (Aircraft)ctx;
448   TS                ts = actx->ts;
449   Vec               Q;
450   const PetscScalar *p,*q;
451   PetscScalar       *u,*v,*w;
452   PetscInt          i;
453   PetscErrorCode    ierr;
454 
455   PetscFunctionBeginUser;
456   ierr = VecGetArrayRead(P,&p);CHKERRQ(ierr);
457   ierr = VecGetArray(actx->V,&v);CHKERRQ(ierr);
458   ierr = VecGetArray(actx->W,&w);CHKERRQ(ierr);
459   for (i=0; i<actx->nsteps; i++) {
460     v[i] = p[2*i];
461     w[i] = p[2*i+1];
462   }
463   ierr = VecRestoreArrayRead(P,&p);CHKERRQ(ierr);
464   ierr = VecRestoreArray(actx->V,&v);CHKERRQ(ierr);
465   ierr = VecRestoreArray(actx->W,&w);CHKERRQ(ierr);
466 
467   ierr = TSSetTime(ts,0.0);CHKERRQ(ierr);
468   ierr = TSSetStepNumber(ts,0);CHKERRQ(ierr);
469   ierr = TSSetFromOptions(ts);CHKERRQ(ierr);
470   ierr = TSSetTimeStep(ts,actx->ftime/actx->nsteps);CHKERRQ(ierr);
471 
472   /* reinitialize system state */
473   ierr = VecGetArray(actx->U,&u);CHKERRQ(ierr);
474   u[0] = 2.0;
475   u[1] = 0;
476   ierr = VecRestoreArray(actx->U,&u);CHKERRQ(ierr);
477 
478   /* reinitialize the integral value */
479   ierr = TSGetCostIntegral(ts,&Q);CHKERRQ(ierr);
480   ierr = VecSet(Q,0.0);CHKERRQ(ierr);
481 
482   ierr = TSSolve(ts,actx->U);CHKERRQ(ierr);
483 
484   /* Reset initial conditions for the adjoint integration */
485   ierr = VecSet(actx->Lambda[0],0.0);CHKERRQ(ierr);
486   ierr = VecSet(actx->Mup[0],0.0);CHKERRQ(ierr);
487   ierr = TSSetCostGradients(ts,1,actx->Lambda,actx->Mup);CHKERRQ(ierr);
488 
489   ierr = TSAdjointSolve(ts);CHKERRQ(ierr);
490   ierr = VecCopy(actx->Mup[0],G);CHKERRQ(ierr);
491   ierr = TSGetCostIntegral(ts,&Q);CHKERRQ(ierr);
492   ierr = VecGetArrayRead(Q,&q);CHKERRQ(ierr);
493   *f   = q[0];
494   ierr = VecRestoreArrayRead(Q,&q);CHKERRQ(ierr);
495   PetscFunctionReturn(0);
496 }
497 
498 PetscErrorCode FormObjHessian(Tao tao,Vec P,Mat H,Mat Hpre,void *ctx)
499 {
500   Aircraft          actx = (Aircraft)ctx;
501   const PetscScalar *p;
502   PetscScalar       *harr,*v,*w,one = 1.0;
503   PetscInt          ind[1];
504   PetscInt          *cols,i;
505   Vec               Dir;
506   PetscErrorCode    ierr;
507 
508   PetscFunctionBeginUser;
509   /* set up control parameters */
510   ierr = VecGetArrayRead(P,&p);CHKERRQ(ierr);
511   ierr = VecGetArray(actx->V,&v);CHKERRQ(ierr);
512   ierr = VecGetArray(actx->W,&w);CHKERRQ(ierr);
513   for (i=0; i<actx->nsteps; i++) {
514     v[i] = p[2*i];
515     w[i] = p[2*i+1];
516   }
517   ierr = VecRestoreArrayRead(P,&p);CHKERRQ(ierr);
518   ierr = VecRestoreArray(actx->V,&v);CHKERRQ(ierr);
519   ierr = VecRestoreArray(actx->W,&w);CHKERRQ(ierr);
520 
521   ierr = PetscMalloc1(2*actx->nsteps,&harr);CHKERRQ(ierr);
522   ierr = PetscMalloc1(2*actx->nsteps,&cols);CHKERRQ(ierr);
523   for (i=0; i<2*actx->nsteps; i++) cols[i] = i;
524   ierr = VecDuplicate(P,&Dir);CHKERRQ(ierr);
525   for (i=0; i<2*actx->nsteps; i++) {
526     ind[0] = i;
527     ierr   = VecSet(Dir,0.0);CHKERRQ(ierr);
528     ierr   = VecSetValues(Dir,1,ind,&one,INSERT_VALUES);CHKERRQ(ierr);
529     ierr   = VecAssemblyBegin(Dir);CHKERRQ(ierr);
530     ierr   = VecAssemblyEnd(Dir);CHKERRQ(ierr);
531     ierr   = ComputeObjHessianWithSOA(Dir,harr,actx);CHKERRQ(ierr);
532     ierr   = MatSetValues(H,1,ind,2*actx->nsteps,cols,harr,INSERT_VALUES);CHKERRQ(ierr);
533     ierr   = MatAssemblyBegin(H,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
534     ierr   = MatAssemblyEnd(H,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
535     if (H != Hpre) {
536       ierr   = MatAssemblyBegin(Hpre,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
537       ierr   = MatAssemblyEnd(Hpre,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
538     }
539   }
540   ierr = PetscFree(cols);CHKERRQ(ierr);
541   ierr = PetscFree(harr);CHKERRQ(ierr);
542   ierr = VecDestroy(&Dir);CHKERRQ(ierr);
543   PetscFunctionReturn(0);
544 }
545 
546 PetscErrorCode MatrixFreeObjHessian(Tao tao, Vec P, Mat H, Mat Hpre, void *ctx)
547 {
548   Aircraft          actx = (Aircraft)ctx;
549   PetscScalar       *v,*w;
550   const PetscScalar *p;
551   PetscInt          i;
552   PetscErrorCode    ierr;
553 
554   PetscFunctionBegin;
555   ierr = VecGetArrayRead(P,&p);CHKERRQ(ierr);
556   ierr = VecGetArray(actx->V,&v);CHKERRQ(ierr);
557   ierr = VecGetArray(actx->W,&w);CHKERRQ(ierr);
558   for (i=0; i<actx->nsteps; i++) {
559     v[i] = p[2*i];
560     w[i] = p[2*i+1];
561   }
562   ierr = VecRestoreArrayRead(P,&p);CHKERRQ(ierr);
563   ierr = VecRestoreArray(actx->V,&v);CHKERRQ(ierr);
564   ierr = VecRestoreArray(actx->W,&w);CHKERRQ(ierr);
565   PetscFunctionReturn(0);
566 }
567 
568 PetscErrorCode MyMatMult(Mat H_shell, Vec X, Vec Y)
569 {
570   PetscScalar    *y;
571   void           *ptr;
572   PetscErrorCode ierr;
573 
574   PetscFunctionBegin;
575   ierr = MatShellGetContext(H_shell,&ptr);CHKERRQ(ierr);
576   ierr = VecGetArray(Y,&y);CHKERRQ(ierr);
577   ierr = ComputeObjHessianWithSOA(X,y,(Aircraft)ptr);CHKERRQ(ierr);
578   ierr = VecRestoreArray(Y,&y);CHKERRQ(ierr);
579   PetscFunctionReturn(0);
580 }
581 
582 PetscErrorCode ComputeObjHessianWithSOA(Vec Dir,PetscScalar arr[],Aircraft actx)
583 {
584   TS                ts = actx->ts;
585   const PetscScalar *z_ptr;
586   PetscScalar       *u;
587   Vec               Q;
588   PetscInt          i;
589   PetscErrorCode    ierr;
590 
591   PetscFunctionBeginUser;
592   /* Reset TSAdjoint so that AdjointSetUp will be called again */
593   ierr = TSAdjointReset(ts);CHKERRQ(ierr);
594 
595   ierr = TSSetTime(ts,0.0);CHKERRQ(ierr);
596   ierr = TSSetStepNumber(ts,0);CHKERRQ(ierr);
597   ierr = TSSetFromOptions(ts);CHKERRQ(ierr);
598   ierr = TSSetTimeStep(ts,actx->ftime/actx->nsteps);CHKERRQ(ierr);
599   ierr = TSSetCostHessianProducts(actx->ts,1,actx->Lambda2,actx->Mup2,Dir);CHKERRQ(ierr);
600 
601   /* reinitialize system state */
602   ierr = VecGetArray(actx->U,&u);CHKERRQ(ierr);
603   u[0] = 2.0;
604   u[1] = 0;
605   ierr = VecRestoreArray(actx->U,&u);CHKERRQ(ierr);
606 
607   /* reinitialize the integral value */
608   ierr = TSGetCostIntegral(ts,&Q);CHKERRQ(ierr);
609   ierr = VecSet(Q,0.0);CHKERRQ(ierr);
610 
611   /* initialize tlm variable */
612   ierr = MatZeroEntries(actx->Jacp);CHKERRQ(ierr);
613   ierr = MatAssemblyBegin(actx->Jacp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
614   ierr = MatAssemblyEnd(actx->Jacp,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
615   ierr = TSAdjointSetForward(ts,actx->Jacp);CHKERRQ(ierr);
616 
617   ierr = TSSolve(ts,actx->U);CHKERRQ(ierr);
618 
619   /* Set terminal conditions for first- and second-order adjonts */
620   ierr = VecSet(actx->Lambda[0],0.0);CHKERRQ(ierr);
621   ierr = VecSet(actx->Mup[0],0.0);CHKERRQ(ierr);
622   ierr = VecSet(actx->Lambda2[0],0.0);CHKERRQ(ierr);
623   ierr = VecSet(actx->Mup2[0],0.0);CHKERRQ(ierr);
624   ierr = TSSetCostGradients(ts,1,actx->Lambda,actx->Mup);CHKERRQ(ierr);
625 
626   ierr = TSGetCostIntegral(ts,&Q);CHKERRQ(ierr);
627 
628   /* Reset initial conditions for the adjoint integration */
629   ierr = TSAdjointSolve(ts);CHKERRQ(ierr);
630 
631   /* initial condition does not depend on p, so that lambda is not needed to assemble G */
632   ierr = VecGetArrayRead(actx->Mup2[0],&z_ptr);CHKERRQ(ierr);
633   for (i=0; i<2*actx->nsteps; i++) arr[i] = z_ptr[i];
634   ierr = VecRestoreArrayRead(actx->Mup2[0],&z_ptr);CHKERRQ(ierr);
635 
636   /* Disable second-order adjoint mode */
637   ierr = TSAdjointReset(ts);CHKERRQ(ierr);
638   ierr = TSAdjointResetForward(ts);CHKERRQ(ierr);
639   PetscFunctionReturn(0);
640 }
641 
642 /*TEST
643     build:
644       requires: !complex !single
645 
646     test:
647       args:  -ts_adapt_type none -ts_type rk -ts_rk_type 3 -viewer_binary_skip_info -tao_monitor -tao_gatol 1e-7
648 
649     test:
650       suffix: 2
651       args:  -ts_adapt_type none -ts_type rk -ts_rk_type 3 -viewer_binary_skip_info -tao_monitor -tao_view -tao_type bntr -tao_bnk_pc_type none -exacthessian
652 
653     test:
654       suffix: 3
655       args:  -ts_adapt_type none -ts_type rk -ts_rk_type 3 -viewer_binary_skip_info -tao_monitor -tao_view -tao_type bntr -tao_bnk_pc_type none -exacthessian -matrixfree
656 TEST*/
657 
658