xref: /petsc/src/ts/tutorials/advection-diffusion-reaction/ex5opt_ic.c (revision b122ec5aa1bd4469eb4e0673542fb7de3f411254)
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;
365f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDuplicate(U,&Uob));
375f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSNPrintf(filename,sizeof filename,"ex5opt.ob"));
385f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerBinaryOpen(PETSC_COMM_WORLD,filename,FILE_MODE_READ,&viewer));
395f80ce2aSJacob Faibussowitsch   CHKERRQ(VecLoad(Uob,viewer));
405f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerDestroy(&viewer));
415f80ce2aSJacob Faibussowitsch   CHKERRQ(VecAYPX(Uob,-1.,U));
425f80ce2aSJacob Faibussowitsch   CHKERRQ(VecScale(Uob,2.0));
435f80ce2aSJacob Faibussowitsch   CHKERRQ(VecAXPY(lambda,1.,Uob));
445f80ce2aSJacob 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;
545f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerCreate(PetscObjectComm((PetscObject)da),viewer));
555f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerSetType(*viewer,PETSCVIEWERBINARY));
565f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerFileSetMode(*viewer,FILE_MODE_WRITE));
575f80ce2aSJacob 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;
715f80ce2aSJacob Faibussowitsch   CHKERRQ(TSGetDM(ts,&da));
725f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSolve(ts,U));
735f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSNPrintf(filename,sizeof filename,"ex5opt.ob"));
745f80ce2aSJacob Faibussowitsch   CHKERRQ(OutputBIN(da,filename,&viewer));
755f80ce2aSJacob Faibussowitsch   CHKERRQ(VecView(U,viewer));
765f80ce2aSJacob 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;
875f80ce2aSJacob 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 
925f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAVecGetArray(da,U,&u));
93c4762a1bSJed Brown   /* Get local grid boundaries */
945f80ce2aSJacob 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 
1085f80ce2aSJacob 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;
1195f80ce2aSJacob 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 
1245f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAVecGetArray(da,U,&u));
125c4762a1bSJed Brown   /* Get local grid boundaries */
1265f80ce2aSJacob 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 
1405f80ce2aSJacob 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;
1515f80ce2aSJacob 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 
1565f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAVecGetArray(da,U,&u));
157c4762a1bSJed Brown   /* Get local grid boundaries */
1585f80ce2aSJacob 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 
1725f80ce2aSJacob 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;
1835f80ce2aSJacob 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 
1885f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDAVecGetArray(da,U,&u));
189c4762a1bSJed Brown   /* Get local grid boundaries */
1905f80ce2aSJacob 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 
2045f80ce2aSJacob 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   DM             da;
211c4762a1bSJed Brown   AppCtx         appctx;
212c4762a1bSJed Brown   PetscBool      forwardonly = PETSC_FALSE,implicitform = PETSC_FALSE;
213c4762a1bSJed Brown   PetscInt       perturbic = 1;
214c4762a1bSJed Brown 
215*b122ec5aSJacob Faibussowitsch   CHKERRQ(PetscInitialize(&argc,&argv,(char*)0,help));
2165f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsGetBool(NULL,NULL,"-forwardonly",&forwardonly,NULL));
2175f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsGetBool(NULL,NULL,"-implicitform",&implicitform,NULL));
2185f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsGetInt(NULL,NULL,"-perturbic",&perturbic,NULL));
219c4762a1bSJed Brown 
220c4762a1bSJed Brown   appctx.D1    = 8.0e-5;
221c4762a1bSJed Brown   appctx.D2    = 4.0e-5;
222c4762a1bSJed Brown   appctx.gamma = .024;
223c4762a1bSJed Brown   appctx.kappa = .06;
22460f0b76eSHong Zhang   appctx.aijpc = PETSC_FALSE;
225c4762a1bSJed Brown 
226c4762a1bSJed Brown   /* Create distributed array (DMDA) to manage parallel grid and vectors */
2275f80ce2aSJacob 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));
2285f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetFromOptions(da));
2295f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetUp(da));
2305f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDASetFieldName(da,0,"u"));
2315f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDASetFieldName(da,1,"v"));
232c4762a1bSJed Brown 
233c4762a1bSJed Brown   /* Extract global vectors from DMDA; then duplicate for remaining
234c4762a1bSJed Brown      vectors that are the same types */
2355f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateGlobalVector(da,&appctx.U));
236c4762a1bSJed Brown 
237c4762a1bSJed Brown   /* Create timestepping solver context */
2385f80ce2aSJacob Faibussowitsch   CHKERRQ(TSCreate(PETSC_COMM_WORLD,&appctx.ts));
2395f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetType(appctx.ts,TSCN));
2405f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetDM(appctx.ts,da));
2415f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetProblemType(appctx.ts,TS_NONLINEAR));
2425f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetEquationType(appctx.ts,TS_EQ_ODE_EXPLICIT)); /* less Jacobian evaluations when adjoint BEuler is used, otherwise no effect */
243c4762a1bSJed Brown   if (!implicitform) {
2445f80ce2aSJacob Faibussowitsch     CHKERRQ(TSSetRHSFunction(appctx.ts,NULL,RHSFunction,&appctx));
2455f80ce2aSJacob Faibussowitsch     CHKERRQ(TSSetRHSJacobian(appctx.ts,NULL,NULL,RHSJacobian,&appctx));
246c4762a1bSJed Brown   } else {
2475f80ce2aSJacob Faibussowitsch     CHKERRQ(TSSetIFunction(appctx.ts,NULL,IFunction,&appctx));
2485f80ce2aSJacob Faibussowitsch     CHKERRQ(TSSetIJacobian(appctx.ts,NULL,NULL,IJacobian,&appctx));
249c4762a1bSJed Brown   }
250c4762a1bSJed Brown 
251c4762a1bSJed Brown   /* Set initial conditions */
2525f80ce2aSJacob Faibussowitsch   CHKERRQ(InitialConditions(da,appctx.U));
2535f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetSolution(appctx.ts,appctx.U));
254c4762a1bSJed Brown 
255c4762a1bSJed Brown   /* Set solver options */
2565f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetMaxTime(appctx.ts,2000.0));
2575f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetTimeStep(appctx.ts,0.5));
2585f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetExactFinalTime(appctx.ts,TS_EXACTFINALTIME_MATCHSTEP));
2595f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetFromOptions(appctx.ts));
260c4762a1bSJed Brown 
2615f80ce2aSJacob Faibussowitsch   CHKERRQ(GenerateOBs(appctx.ts,appctx.U,&appctx));
262c4762a1bSJed Brown 
263c4762a1bSJed Brown   if (!forwardonly) {
264c4762a1bSJed Brown     Tao           tao;
265c4762a1bSJed Brown     Vec           P;
266c4762a1bSJed Brown     Vec           lambda[1];
267956f8c0dSBarry Smith #if defined(PETSC_USE_LOG)
268c4762a1bSJed Brown     PetscLogStage opt_stage;
269956f8c0dSBarry Smith #endif
270c4762a1bSJed Brown 
2715f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogStageRegister("Optimization",&opt_stage));
2725f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogStagePush(opt_stage));
273c4762a1bSJed Brown     if (perturbic == 1) {
2745f80ce2aSJacob Faibussowitsch       CHKERRQ(PerturbedInitialConditions(da,appctx.U));
275c4762a1bSJed Brown     } else if (perturbic == 2) {
2765f80ce2aSJacob Faibussowitsch       CHKERRQ(PerturbedInitialConditions2(da,appctx.U));
277c4762a1bSJed Brown     } else if (perturbic == 3) {
2785f80ce2aSJacob Faibussowitsch       CHKERRQ(PerturbedInitialConditions3(da,appctx.U));
279c4762a1bSJed Brown     }
280c4762a1bSJed Brown 
2815f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDuplicate(appctx.U,&lambda[0]));
2825f80ce2aSJacob Faibussowitsch     CHKERRQ(TSSetCostGradients(appctx.ts,1,lambda,NULL));
283c4762a1bSJed Brown 
284c4762a1bSJed Brown     /* Have the TS save its trajectory needed by TSAdjointSolve() */
2855f80ce2aSJacob Faibussowitsch     CHKERRQ(TSSetSaveTrajectory(appctx.ts));
286c4762a1bSJed Brown 
287c4762a1bSJed Brown     /* Create TAO solver and set desired solution method */
2885f80ce2aSJacob Faibussowitsch     CHKERRQ(TaoCreate(PETSC_COMM_WORLD,&tao));
2895f80ce2aSJacob Faibussowitsch     CHKERRQ(TaoSetType(tao,TAOBLMVM));
290c4762a1bSJed Brown 
291c4762a1bSJed Brown     /* Set initial guess for TAO */
2925f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDuplicate(appctx.U,&P));
2935f80ce2aSJacob Faibussowitsch     CHKERRQ(VecCopy(appctx.U,P));
2945f80ce2aSJacob Faibussowitsch     CHKERRQ(TaoSetSolution(tao,P));
295c4762a1bSJed Brown 
296c4762a1bSJed Brown     /* Set routine for function and gradient evaluation */
2975f80ce2aSJacob Faibussowitsch     CHKERRQ(TaoSetObjectiveAndGradient(tao,NULL,FormFunctionAndGradient,&appctx));
298c4762a1bSJed Brown 
299c4762a1bSJed Brown     /* Check for any TAO command line options */
3005f80ce2aSJacob Faibussowitsch     CHKERRQ(TaoSetFromOptions(tao));
301c4762a1bSJed Brown 
3025f80ce2aSJacob Faibussowitsch     CHKERRQ(TaoSolve(tao));
3035f80ce2aSJacob Faibussowitsch     CHKERRQ(TaoDestroy(&tao));
3045f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDestroy(&lambda[0]));
3055f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDestroy(&P));
3065f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscLogStagePop());
307c4762a1bSJed Brown   }
308c4762a1bSJed Brown 
309c4762a1bSJed Brown   /* Free work space.  All PETSc objects should be destroyed when they
310c4762a1bSJed Brown      are no longer needed. */
3115f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&appctx.U));
3125f80ce2aSJacob Faibussowitsch   CHKERRQ(TSDestroy(&appctx.ts));
3135f80ce2aSJacob Faibussowitsch   CHKERRQ(DMDestroy(&da));
314*b122ec5aSJacob Faibussowitsch   CHKERRQ(PetscFinalize());
315*b122ec5aSJacob Faibussowitsch   return 0;
316c4762a1bSJed Brown }
317c4762a1bSJed Brown 
318c4762a1bSJed Brown /* ------------------------ TAO callbacks ---------------------------- */
319c4762a1bSJed Brown 
320c4762a1bSJed Brown /*
321c4762a1bSJed Brown    FormFunctionAndGradient - Evaluates the function and corresponding gradient.
322c4762a1bSJed Brown 
323c4762a1bSJed Brown    Input Parameters:
324c4762a1bSJed Brown    tao - the Tao context
325c4762a1bSJed Brown    P   - the input vector
326a82e8c82SStefano Zampini    ctx - optional user-defined context, as set by TaoSetObjectiveAndGradient()
327c4762a1bSJed Brown 
328c4762a1bSJed Brown    Output Parameters:
329c4762a1bSJed Brown    f   - the newly evaluated function
330c4762a1bSJed Brown    G   - the newly evaluated gradient
331c4762a1bSJed Brown */
332c4762a1bSJed Brown PetscErrorCode FormFunctionAndGradient(Tao tao,Vec P,PetscReal *f,Vec G,void *ctx)
333c4762a1bSJed Brown {
334c4762a1bSJed Brown   AppCtx         *appctx = (AppCtx*)ctx;
335c4762a1bSJed Brown   PetscReal      soberr,timestep;
336c4762a1bSJed Brown   Vec            *lambda;
337c4762a1bSJed Brown   Vec            SDiff;
338c4762a1bSJed Brown   DM             da;
339c4762a1bSJed Brown   char           filename[PETSC_MAX_PATH_LEN]="";
340c4762a1bSJed Brown   PetscViewer    viewer;
341c4762a1bSJed Brown 
342c4762a1bSJed Brown   PetscFunctionBeginUser;
3435f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetTime(appctx->ts,0.0));
3445f80ce2aSJacob Faibussowitsch   CHKERRQ(TSGetTimeStep(appctx->ts,&timestep));
345c4762a1bSJed Brown   if (timestep<0) {
3465f80ce2aSJacob Faibussowitsch     CHKERRQ(TSSetTimeStep(appctx->ts,-timestep));
347c4762a1bSJed Brown   }
3485f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetStepNumber(appctx->ts,0));
3495f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetFromOptions(appctx->ts));
350c4762a1bSJed Brown 
3515f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDuplicate(P,&SDiff));
3525f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCopy(P,appctx->U));
3535f80ce2aSJacob Faibussowitsch   CHKERRQ(TSGetDM(appctx->ts,&da));
354c4762a1bSJed Brown   *f = 0;
355c4762a1bSJed Brown 
3565f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSolve(appctx->ts,appctx->U));
3575f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSNPrintf(filename,sizeof filename,"ex5opt.ob"));
3585f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerBinaryOpen(PETSC_COMM_WORLD,filename,FILE_MODE_READ,&viewer));
3595f80ce2aSJacob Faibussowitsch   CHKERRQ(VecLoad(SDiff,viewer));
3605f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerDestroy(&viewer));
3615f80ce2aSJacob Faibussowitsch   CHKERRQ(VecAYPX(SDiff,-1.,appctx->U));
3625f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDot(SDiff,SDiff,&soberr));
363c4762a1bSJed Brown   *f += soberr;
364c4762a1bSJed Brown 
3655f80ce2aSJacob Faibussowitsch   CHKERRQ(TSGetCostGradients(appctx->ts,NULL,&lambda,NULL));
3665f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSet(lambda[0],0.0));
3675f80ce2aSJacob Faibussowitsch   CHKERRQ(InitializeLambda(da,lambda[0],appctx->U,appctx));
3685f80ce2aSJacob Faibussowitsch   CHKERRQ(TSAdjointSolve(appctx->ts));
369c4762a1bSJed Brown 
3705f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCopy(lambda[0],G));
371c4762a1bSJed Brown 
3725f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&SDiff));
373c4762a1bSJed Brown   PetscFunctionReturn(0);
374c4762a1bSJed Brown }
375c4762a1bSJed Brown 
376c4762a1bSJed Brown /*TEST
377c4762a1bSJed Brown 
378c4762a1bSJed Brown    build:
37960f0b76eSHong Zhang       depends: reaction_diffusion.c
380c4762a1bSJed Brown       requires: !complex !single
381c4762a1bSJed Brown 
382c4762a1bSJed Brown    test:
383c4762a1bSJed 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
384c4762a1bSJed Brown       output_file: output/ex5opt_ic_1.out
385c4762a1bSJed Brown 
386c4762a1bSJed Brown TEST*/
387