1c4762a1bSJed Brown static char help[] = "Demonstrates adjoint sensitivity analysis for Reaction-Diffusion Equations.\n"; 2c4762a1bSJed Brown 3c4762a1bSJed Brown /* 4c4762a1bSJed Brown See ex5.c for details on the equation. 5c4762a1bSJed Brown This code demonestrates the TSAdjoint/TAO interface to solve an inverse initial value problem built on a system of 6c4762a1bSJed Brown time-dependent partial differential equations. 7c4762a1bSJed Brown In this problem, the initial value for the PDE is unknown, but the output (the final solution of the PDE) is known. 8c4762a1bSJed Brown We want to determine the initial value that can produce the given output. 9c4762a1bSJed Brown We formulate the problem as a nonlinear optimization problem that minimizes the discrepency between the simulated 10c4762a1bSJed Brown result and given reference solution, calculate the gradient of the objective function with the discrete adjoint 11c4762a1bSJed Brown solver, and solve the optimization problem with TAO. 12c4762a1bSJed Brown 13c4762a1bSJed Brown Runtime options: 14c4762a1bSJed Brown -forwardonly - run only the forward simulation 15c4762a1bSJed Brown -implicitform - provide IFunction and IJacobian to TS, if not set, RHSFunction and RHSJacobian will be used 16c4762a1bSJed Brown */ 17c4762a1bSJed Brown 1860f0b76eSHong Zhang #include "reaction_diffusion.h" 19c4762a1bSJed Brown #include <petscdm.h> 20c4762a1bSJed Brown #include <petscdmda.h> 21c4762a1bSJed Brown #include <petsctao.h> 22c4762a1bSJed Brown 23c4762a1bSJed Brown /* User-defined routines */ 24c4762a1bSJed Brown extern PetscErrorCode FormFunctionAndGradient(Tao,Vec,PetscReal*,Vec,void*); 25c4762a1bSJed Brown 26c4762a1bSJed Brown /* 27c4762a1bSJed Brown Set terminal condition for the adjoint variable 28c4762a1bSJed Brown */ 29c4762a1bSJed Brown PetscErrorCode InitializeLambda(DM da,Vec lambda,Vec U,AppCtx *appctx) 30c4762a1bSJed Brown { 31c4762a1bSJed Brown char filename[PETSC_MAX_PATH_LEN]=""; 32c4762a1bSJed Brown PetscViewer viewer; 33c4762a1bSJed Brown Vec Uob; 34c4762a1bSJed Brown 35362febeeSStefano Zampini PetscFunctionBegin; 36*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(U,&Uob)); 37*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSNPrintf(filename,sizeof filename,"ex5opt.ob")); 38*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerBinaryOpen(PETSC_COMM_WORLD,filename,FILE_MODE_READ,&viewer)); 39*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecLoad(Uob,viewer)); 40*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerDestroy(&viewer)); 41*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecAYPX(Uob,-1.,U)); 42*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecScale(Uob,2.0)); 43*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecAXPY(lambda,1.,Uob)); 44*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&Uob)); 45c4762a1bSJed Brown PetscFunctionReturn(0); 46c4762a1bSJed Brown } 47c4762a1bSJed Brown 48c4762a1bSJed Brown /* 49c4762a1bSJed Brown Set up a viewer that dumps data into a binary file 50c4762a1bSJed Brown */ 51c4762a1bSJed Brown PetscErrorCode OutputBIN(DM da, const char *filename, PetscViewer *viewer) 52c4762a1bSJed Brown { 53362febeeSStefano Zampini PetscFunctionBegin; 54*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerCreate(PetscObjectComm((PetscObject)da),viewer)); 55*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerSetType(*viewer,PETSCVIEWERBINARY)); 56*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFileSetMode(*viewer,FILE_MODE_WRITE)); 57*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerFileSetName(*viewer,filename)); 58c4762a1bSJed Brown PetscFunctionReturn(0); 59c4762a1bSJed Brown } 60c4762a1bSJed Brown 61c4762a1bSJed Brown /* 62c4762a1bSJed Brown Generate a reference solution and save it to a binary file 63c4762a1bSJed Brown */ 64c4762a1bSJed Brown PetscErrorCode GenerateOBs(TS ts,Vec U,AppCtx *appctx) 65c4762a1bSJed Brown { 66c4762a1bSJed Brown char filename[PETSC_MAX_PATH_LEN] = ""; 67c4762a1bSJed Brown PetscViewer viewer; 68c4762a1bSJed Brown DM da; 69c4762a1bSJed Brown 70362febeeSStefano Zampini PetscFunctionBegin; 71*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetDM(ts,&da)); 72*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSolve(ts,U)); 73*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSNPrintf(filename,sizeof filename,"ex5opt.ob")); 74*5f80ce2aSJacob Faibussowitsch CHKERRQ(OutputBIN(da,filename,&viewer)); 75*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecView(U,viewer)); 76*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerDestroy(&viewer)); 77c4762a1bSJed Brown PetscFunctionReturn(0); 78c4762a1bSJed Brown } 79c4762a1bSJed Brown 80c4762a1bSJed Brown PetscErrorCode InitialConditions(DM da,Vec U) 81c4762a1bSJed Brown { 82c4762a1bSJed Brown PetscInt i,j,xs,ys,xm,ym,Mx,My; 83c4762a1bSJed Brown Field **u; 84c4762a1bSJed Brown PetscReal hx,hy,x,y; 85c4762a1bSJed Brown 86c4762a1bSJed Brown PetscFunctionBegin; 87*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetInfo(da,PETSC_IGNORE,&Mx,&My,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE)); 88c4762a1bSJed Brown 89c4762a1bSJed Brown hx = 2.5/(PetscReal)Mx; 90c4762a1bSJed Brown hy = 2.5/(PetscReal)My; 91c4762a1bSJed Brown 92*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecGetArray(da,U,&u)); 93c4762a1bSJed Brown /* Get local grid boundaries */ 94*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetCorners(da,&xs,&ys,NULL,&xm,&ym,NULL)); 95c4762a1bSJed Brown 96c4762a1bSJed Brown /* Compute function over the locally owned part of the grid */ 97c4762a1bSJed Brown for (j=ys; j<ys+ym; j++) { 98c4762a1bSJed Brown y = j*hy; 99c4762a1bSJed Brown for (i=xs; i<xs+xm; i++) { 100c4762a1bSJed Brown x = i*hx; 101c4762a1bSJed Brown if ((1.0 <= x) && (x <= 1.5) && (1.0 <= y) && (y <= 1.5)) u[j][i].v = .25*PetscPowReal(PetscSinReal(4.0*PETSC_PI*x),2.0)*PetscPowReal(PetscSinReal(4.0*PETSC_PI*y),2.0); 102c4762a1bSJed Brown else u[j][i].v = 0.0; 103c4762a1bSJed Brown 104c4762a1bSJed Brown u[j][i].u = 1.0 - 2.0*u[j][i].v; 105c4762a1bSJed Brown } 106c4762a1bSJed Brown } 107c4762a1bSJed Brown 108*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecRestoreArray(da,U,&u)); 109c4762a1bSJed Brown PetscFunctionReturn(0); 110c4762a1bSJed Brown } 111c4762a1bSJed Brown 112c4762a1bSJed Brown PetscErrorCode PerturbedInitialConditions(DM da,Vec U) 113c4762a1bSJed Brown { 114c4762a1bSJed Brown PetscInt i,j,xs,ys,xm,ym,Mx,My; 115c4762a1bSJed Brown Field **u; 116c4762a1bSJed Brown PetscReal hx,hy,x,y; 117c4762a1bSJed Brown 118c4762a1bSJed Brown PetscFunctionBegin; 119*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetInfo(da,PETSC_IGNORE,&Mx,&My,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE)); 120c4762a1bSJed Brown 121c4762a1bSJed Brown hx = 2.5/(PetscReal)Mx; 122c4762a1bSJed Brown hy = 2.5/(PetscReal)My; 123c4762a1bSJed Brown 124*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecGetArray(da,U,&u)); 125c4762a1bSJed Brown /* Get local grid boundaries */ 126*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetCorners(da,&xs,&ys,NULL,&xm,&ym,NULL)); 127c4762a1bSJed Brown 128c4762a1bSJed Brown /* Compute function over the locally owned part of the grid */ 129c4762a1bSJed Brown for (j=ys; j<ys+ym; j++) { 130c4762a1bSJed Brown y = j*hy; 131c4762a1bSJed Brown for (i=xs; i<xs+xm; i++) { 132c4762a1bSJed Brown x = i*hx; 133c4762a1bSJed Brown if ((1.0 <= x) && (x <= 1.5) && (1.0 <= y) && (y <= 1.5)) u[j][i].v = .25*PetscPowReal(PetscSinReal(4.0*PETSC_PI*0.5*x),2.0)*PetscPowReal(PetscSinReal(4.0*PETSC_PI*0.5*y),2.0); 134c4762a1bSJed Brown else u[j][i].v = 0.0; 135c4762a1bSJed Brown 136c4762a1bSJed Brown u[j][i].u = 1.0 - 2.0*u[j][i].v; 137c4762a1bSJed Brown } 138c4762a1bSJed Brown } 139c4762a1bSJed Brown 140*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecRestoreArray(da,U,&u)); 141c4762a1bSJed Brown PetscFunctionReturn(0); 142c4762a1bSJed Brown } 143c4762a1bSJed Brown 144c4762a1bSJed Brown PetscErrorCode PerturbedInitialConditions2(DM da,Vec U) 145c4762a1bSJed Brown { 146c4762a1bSJed Brown PetscInt i,j,xs,ys,xm,ym,Mx,My; 147c4762a1bSJed Brown Field **u; 148c4762a1bSJed Brown PetscReal hx,hy,x,y; 149c4762a1bSJed Brown 150c4762a1bSJed Brown PetscFunctionBegin; 151*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetInfo(da,PETSC_IGNORE,&Mx,&My,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE)); 152c4762a1bSJed Brown 153c4762a1bSJed Brown hx = 2.5/(PetscReal)Mx; 154c4762a1bSJed Brown hy = 2.5/(PetscReal)My; 155c4762a1bSJed Brown 156*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecGetArray(da,U,&u)); 157c4762a1bSJed Brown /* Get local grid boundaries */ 158*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetCorners(da,&xs,&ys,NULL,&xm,&ym,NULL)); 159c4762a1bSJed Brown 160c4762a1bSJed Brown /* Compute function over the locally owned part of the grid */ 161c4762a1bSJed Brown for (j=ys; j<ys+ym; j++) { 162c4762a1bSJed Brown y = j*hy; 163c4762a1bSJed Brown for (i=xs; i<xs+xm; i++) { 164c4762a1bSJed Brown x = i*hx; 16566baab88SBarry Smith if (PetscApproximateGTE(x,1.0) && PetscApproximateLTE(x,1.5) && PetscApproximateGTE(y,1.0) && PetscApproximateLTE(y,1.5)) u[j][i].v = PetscPowReal(PetscSinReal(4.0*PETSC_PI*(x-0.5)),2.0)*PetscPowReal(PetscSinReal(4.0*PETSC_PI*y),2.0)/4.0; 166c4762a1bSJed Brown else u[j][i].v = 0.0; 167c4762a1bSJed Brown 168c4762a1bSJed Brown u[j][i].u = 1.0 - 2.0*u[j][i].v; 169c4762a1bSJed Brown } 170c4762a1bSJed Brown } 171c4762a1bSJed Brown 172*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecRestoreArray(da,U,&u)); 173c4762a1bSJed Brown PetscFunctionReturn(0); 174c4762a1bSJed Brown } 175c4762a1bSJed Brown 176c4762a1bSJed Brown PetscErrorCode PerturbedInitialConditions3(DM da,Vec U) 177c4762a1bSJed Brown { 178c4762a1bSJed Brown PetscInt i,j,xs,ys,xm,ym,Mx,My; 179c4762a1bSJed Brown Field **u; 180c4762a1bSJed Brown PetscReal hx,hy,x,y; 181c4762a1bSJed Brown 182c4762a1bSJed Brown PetscFunctionBegin; 183*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetInfo(da,PETSC_IGNORE,&Mx,&My,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE,PETSC_IGNORE)); 184c4762a1bSJed Brown 185c4762a1bSJed Brown hx = 2.5/(PetscReal)Mx; 186c4762a1bSJed Brown hy = 2.5/(PetscReal)My; 187c4762a1bSJed Brown 188*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecGetArray(da,U,&u)); 189c4762a1bSJed Brown /* Get local grid boundaries */ 190*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAGetCorners(da,&xs,&ys,NULL,&xm,&ym,NULL)); 191c4762a1bSJed Brown 192c4762a1bSJed Brown /* Compute function over the locally owned part of the grid */ 193c4762a1bSJed Brown for (j=ys; j<ys+ym; j++) { 194c4762a1bSJed Brown y = j*hy; 195c4762a1bSJed Brown for (i=xs; i<xs+xm; i++) { 196c4762a1bSJed Brown x = i*hx; 197c4762a1bSJed Brown if ((0.5 <= x) && (x <= 2.0) && (0.5 <= y) && (y <= 2.0)) u[j][i].v = .25*PetscPowReal(PetscSinReal(4.0*PETSC_PI*x),2.0)*PetscPowReal(PetscSinReal(4.0*PETSC_PI*y),2.0); 198c4762a1bSJed Brown else u[j][i].v = 0.0; 199c4762a1bSJed Brown 200c4762a1bSJed Brown u[j][i].u = 1.0 - 2.0*u[j][i].v; 201c4762a1bSJed Brown } 202c4762a1bSJed Brown } 203c4762a1bSJed Brown 204*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDAVecRestoreArray(da,U,&u)); 205c4762a1bSJed Brown PetscFunctionReturn(0); 206c4762a1bSJed Brown } 207c4762a1bSJed Brown 208c4762a1bSJed Brown int main(int argc,char **argv) 209c4762a1bSJed Brown { 210c4762a1bSJed Brown PetscErrorCode ierr; 211c4762a1bSJed Brown DM da; 212c4762a1bSJed Brown AppCtx appctx; 213c4762a1bSJed Brown PetscBool forwardonly = PETSC_FALSE,implicitform = PETSC_FALSE; 214c4762a1bSJed Brown PetscInt perturbic = 1; 215c4762a1bSJed Brown 216c4762a1bSJed Brown ierr = PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr; 217*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetBool(NULL,NULL,"-forwardonly",&forwardonly,NULL)); 218*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetBool(NULL,NULL,"-implicitform",&implicitform,NULL)); 219*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscOptionsGetInt(NULL,NULL,"-perturbic",&perturbic,NULL)); 220c4762a1bSJed Brown 221c4762a1bSJed Brown appctx.D1 = 8.0e-5; 222c4762a1bSJed Brown appctx.D2 = 4.0e-5; 223c4762a1bSJed Brown appctx.gamma = .024; 224c4762a1bSJed Brown appctx.kappa = .06; 22560f0b76eSHong Zhang appctx.aijpc = PETSC_FALSE; 226c4762a1bSJed Brown 227c4762a1bSJed Brown /* Create distributed array (DMDA) to manage parallel grid and vectors */ 228*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDACreate2d(PETSC_COMM_WORLD,DM_BOUNDARY_PERIODIC,DM_BOUNDARY_PERIODIC,DMDA_STENCIL_STAR,64,64,PETSC_DECIDE,PETSC_DECIDE,2,1,NULL,NULL,&da)); 229*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetFromOptions(da)); 230*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMSetUp(da)); 231*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDASetFieldName(da,0,"u")); 232*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDASetFieldName(da,1,"v")); 233c4762a1bSJed Brown 234c4762a1bSJed Brown /* Extract global vectors from DMDA; then duplicate for remaining 235c4762a1bSJed Brown vectors that are the same types */ 236*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMCreateGlobalVector(da,&appctx.U)); 237c4762a1bSJed Brown 238c4762a1bSJed Brown /* Create timestepping solver context */ 239*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSCreate(PETSC_COMM_WORLD,&appctx.ts)); 240*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetType(appctx.ts,TSCN)); 241*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetDM(appctx.ts,da)); 242*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetProblemType(appctx.ts,TS_NONLINEAR)); 243*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetEquationType(appctx.ts,TS_EQ_ODE_EXPLICIT)); /* less Jacobian evaluations when adjoint BEuler is used, otherwise no effect */ 244c4762a1bSJed Brown if (!implicitform) { 245*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetRHSFunction(appctx.ts,NULL,RHSFunction,&appctx)); 246*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetRHSJacobian(appctx.ts,NULL,NULL,RHSJacobian,&appctx)); 247c4762a1bSJed Brown } else { 248*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetIFunction(appctx.ts,NULL,IFunction,&appctx)); 249*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetIJacobian(appctx.ts,NULL,NULL,IJacobian,&appctx)); 250c4762a1bSJed Brown } 251c4762a1bSJed Brown 252c4762a1bSJed Brown /* Set initial conditions */ 253*5f80ce2aSJacob Faibussowitsch CHKERRQ(InitialConditions(da,appctx.U)); 254*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetSolution(appctx.ts,appctx.U)); 255c4762a1bSJed Brown 256c4762a1bSJed Brown /* Set solver options */ 257*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetMaxTime(appctx.ts,2000.0)); 258*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetTimeStep(appctx.ts,0.5)); 259*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetExactFinalTime(appctx.ts,TS_EXACTFINALTIME_MATCHSTEP)); 260*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetFromOptions(appctx.ts)); 261c4762a1bSJed Brown 262*5f80ce2aSJacob Faibussowitsch CHKERRQ(GenerateOBs(appctx.ts,appctx.U,&appctx)); 263c4762a1bSJed Brown 264c4762a1bSJed Brown if (!forwardonly) { 265c4762a1bSJed Brown Tao tao; 266c4762a1bSJed Brown Vec P; 267c4762a1bSJed Brown Vec lambda[1]; 268956f8c0dSBarry Smith #if defined(PETSC_USE_LOG) 269c4762a1bSJed Brown PetscLogStage opt_stage; 270956f8c0dSBarry Smith #endif 271c4762a1bSJed Brown 272*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogStageRegister("Optimization",&opt_stage)); 273*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogStagePush(opt_stage)); 274c4762a1bSJed Brown if (perturbic == 1) { 275*5f80ce2aSJacob Faibussowitsch CHKERRQ(PerturbedInitialConditions(da,appctx.U)); 276c4762a1bSJed Brown } else if (perturbic == 2) { 277*5f80ce2aSJacob Faibussowitsch CHKERRQ(PerturbedInitialConditions2(da,appctx.U)); 278c4762a1bSJed Brown } else if (perturbic == 3) { 279*5f80ce2aSJacob Faibussowitsch CHKERRQ(PerturbedInitialConditions3(da,appctx.U)); 280c4762a1bSJed Brown } 281c4762a1bSJed Brown 282*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(appctx.U,&lambda[0])); 283*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetCostGradients(appctx.ts,1,lambda,NULL)); 284c4762a1bSJed Brown 285c4762a1bSJed Brown /* Have the TS save its trajectory needed by TSAdjointSolve() */ 286*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetSaveTrajectory(appctx.ts)); 287c4762a1bSJed Brown 288c4762a1bSJed Brown /* Create TAO solver and set desired solution method */ 289*5f80ce2aSJacob Faibussowitsch CHKERRQ(TaoCreate(PETSC_COMM_WORLD,&tao)); 290*5f80ce2aSJacob Faibussowitsch CHKERRQ(TaoSetType(tao,TAOBLMVM)); 291c4762a1bSJed Brown 292c4762a1bSJed Brown /* Set initial guess for TAO */ 293*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(appctx.U,&P)); 294*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(appctx.U,P)); 295*5f80ce2aSJacob Faibussowitsch CHKERRQ(TaoSetSolution(tao,P)); 296c4762a1bSJed Brown 297c4762a1bSJed Brown /* Set routine for function and gradient evaluation */ 298*5f80ce2aSJacob Faibussowitsch CHKERRQ(TaoSetObjectiveAndGradient(tao,NULL,FormFunctionAndGradient,&appctx)); 299c4762a1bSJed Brown 300c4762a1bSJed Brown /* Check for any TAO command line options */ 301*5f80ce2aSJacob Faibussowitsch CHKERRQ(TaoSetFromOptions(tao)); 302c4762a1bSJed Brown 303*5f80ce2aSJacob Faibussowitsch CHKERRQ(TaoSolve(tao)); 304*5f80ce2aSJacob Faibussowitsch CHKERRQ(TaoDestroy(&tao)); 305*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&lambda[0])); 306*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&P)); 307*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogStagePop()); 308c4762a1bSJed Brown } 309c4762a1bSJed Brown 310c4762a1bSJed Brown /* Free work space. All PETSc objects should be destroyed when they 311c4762a1bSJed Brown are no longer needed. */ 312*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&appctx.U)); 313*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSDestroy(&appctx.ts)); 314*5f80ce2aSJacob Faibussowitsch CHKERRQ(DMDestroy(&da)); 315c4762a1bSJed Brown ierr = PetscFinalize(); 316c4762a1bSJed Brown return ierr; 317c4762a1bSJed Brown } 318c4762a1bSJed Brown 319c4762a1bSJed Brown /* ------------------------ TAO callbacks ---------------------------- */ 320c4762a1bSJed Brown 321c4762a1bSJed Brown /* 322c4762a1bSJed Brown FormFunctionAndGradient - Evaluates the function and corresponding gradient. 323c4762a1bSJed Brown 324c4762a1bSJed Brown Input Parameters: 325c4762a1bSJed Brown tao - the Tao context 326c4762a1bSJed Brown P - the input vector 327a82e8c82SStefano Zampini ctx - optional user-defined context, as set by TaoSetObjectiveAndGradient() 328c4762a1bSJed Brown 329c4762a1bSJed Brown Output Parameters: 330c4762a1bSJed Brown f - the newly evaluated function 331c4762a1bSJed Brown G - the newly evaluated gradient 332c4762a1bSJed Brown */ 333c4762a1bSJed Brown PetscErrorCode FormFunctionAndGradient(Tao tao,Vec P,PetscReal *f,Vec G,void *ctx) 334c4762a1bSJed Brown { 335c4762a1bSJed Brown AppCtx *appctx = (AppCtx*)ctx; 336c4762a1bSJed Brown PetscReal soberr,timestep; 337c4762a1bSJed Brown Vec *lambda; 338c4762a1bSJed Brown Vec SDiff; 339c4762a1bSJed Brown DM da; 340c4762a1bSJed Brown char filename[PETSC_MAX_PATH_LEN]=""; 341c4762a1bSJed Brown PetscViewer viewer; 342c4762a1bSJed Brown 343c4762a1bSJed Brown PetscFunctionBeginUser; 344*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetTime(appctx->ts,0.0)); 345*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetTimeStep(appctx->ts,×tep)); 346c4762a1bSJed Brown if (timestep<0) { 347*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetTimeStep(appctx->ts,-timestep)); 348c4762a1bSJed Brown } 349*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetStepNumber(appctx->ts,0)); 350*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSetFromOptions(appctx->ts)); 351c4762a1bSJed Brown 352*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDuplicate(P,&SDiff)); 353*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(P,appctx->U)); 354*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetDM(appctx->ts,&da)); 355c4762a1bSJed Brown *f = 0; 356c4762a1bSJed Brown 357*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSSolve(appctx->ts,appctx->U)); 358*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscSNPrintf(filename,sizeof filename,"ex5opt.ob")); 359*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerBinaryOpen(PETSC_COMM_WORLD,filename,FILE_MODE_READ,&viewer)); 360*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecLoad(SDiff,viewer)); 361*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscViewerDestroy(&viewer)); 362*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecAYPX(SDiff,-1.,appctx->U)); 363*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDot(SDiff,SDiff,&soberr)); 364c4762a1bSJed Brown *f += soberr; 365c4762a1bSJed Brown 366*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSGetCostGradients(appctx->ts,NULL,&lambda,NULL)); 367*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecSet(lambda[0],0.0)); 368*5f80ce2aSJacob Faibussowitsch CHKERRQ(InitializeLambda(da,lambda[0],appctx->U,appctx)); 369*5f80ce2aSJacob Faibussowitsch CHKERRQ(TSAdjointSolve(appctx->ts)); 370c4762a1bSJed Brown 371*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecCopy(lambda[0],G)); 372c4762a1bSJed Brown 373*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecDestroy(&SDiff)); 374c4762a1bSJed Brown PetscFunctionReturn(0); 375c4762a1bSJed Brown } 376c4762a1bSJed Brown 377c4762a1bSJed Brown /*TEST 378c4762a1bSJed Brown 379c4762a1bSJed Brown build: 38060f0b76eSHong Zhang depends: reaction_diffusion.c 381c4762a1bSJed Brown requires: !complex !single 382c4762a1bSJed Brown 383c4762a1bSJed Brown test: 384c4762a1bSJed Brown args: -ts_max_steps 5 -ts_type rk -ts_rk_type 3 -ts_trajectory_type memory -tao_monitor -tao_view -tao_gatol 1e-6 385c4762a1bSJed Brown output_file: output/ex5opt_ic_1.out 386c4762a1bSJed Brown 387c4762a1bSJed Brown TEST*/ 388