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