xref: /petsc/src/ts/tutorials/advection-diffusion-reaction/ex5opt_ic.c (revision 5f80ce2ab25dff0f4601e710601cbbcecf323266)
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,&timestep));
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