xref: /petsc/src/ts/tutorials/power_grid/ex3opt.c (revision 5f80ce2ab25dff0f4601e710601cbbcecf323266)
1c4762a1bSJed Brown 
2c4762a1bSJed Brown static char help[] = "Finds optimal parameter P_m for the generator system while maintaining generator stability.\n";
3c4762a1bSJed Brown 
4c4762a1bSJed Brown /*F
5c4762a1bSJed Brown 
6c4762a1bSJed Brown \begin{eqnarray}
7c4762a1bSJed Brown                  \frac{d \theta}{dt} = \omega_b (\omega - \omega_s)
8c4762a1bSJed Brown                  \frac{2 H}{\omega_s}\frac{d \omega}{dt} & = & P_m - P_max \sin(\theta) -D(\omega - \omega_s)\\
9c4762a1bSJed Brown \end{eqnarray}
10c4762a1bSJed Brown 
11c4762a1bSJed Brown F*/
12c4762a1bSJed Brown 
13c4762a1bSJed Brown /*
14c4762a1bSJed Brown   This code demonstrates how to solve a ODE-constrained optimization problem with TAO, TSEvent, TSAdjoint and TS.
15c4762a1bSJed Brown   The problem features discontinuities and a cost function in integral form.
16c4762a1bSJed Brown   The gradient is computed with the discrete adjoint of an implicit theta method, see ex3adj.c for details.
17c4762a1bSJed Brown */
18c4762a1bSJed Brown 
19c4762a1bSJed Brown #include <petsctao.h>
20c4762a1bSJed Brown #include <petscts.h>
21c4762a1bSJed Brown #include "ex3.h"
22c4762a1bSJed Brown 
23c4762a1bSJed Brown PetscErrorCode FormFunctionGradient(Tao,Vec,PetscReal*,Vec,void*);
24c4762a1bSJed Brown 
25c4762a1bSJed Brown PetscErrorCode monitor(Tao tao,AppCtx *ctx)
26c4762a1bSJed Brown {
27c4762a1bSJed Brown   FILE               *fp;
28c4762a1bSJed Brown   PetscInt           iterate;
29c4762a1bSJed Brown   PetscReal          f,gnorm,cnorm,xdiff;
30c4762a1bSJed Brown   TaoConvergedReason reason;
31c4762a1bSJed Brown 
32c4762a1bSJed Brown   PetscFunctionBeginUser;
33*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TaoGetSolutionStatus(tao,&iterate,&f,&gnorm,&cnorm,&xdiff,&reason));
34c4762a1bSJed Brown 
35c4762a1bSJed Brown   fp = fopen("ex3opt_conv.out","a");
36*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFPrintf(PETSC_COMM_WORLD,fp,"%D %g\n",iterate,(double)gnorm));
37c4762a1bSJed Brown   fclose(fp);
38c4762a1bSJed Brown   PetscFunctionReturn(0);
39c4762a1bSJed Brown }
40c4762a1bSJed Brown 
41c4762a1bSJed Brown int main(int argc,char **argv)
42c4762a1bSJed Brown {
43c4762a1bSJed Brown   Vec                p;
44c4762a1bSJed Brown   PetscScalar        *x_ptr;
45c4762a1bSJed Brown   PetscErrorCode     ierr;
46c4762a1bSJed Brown   PetscMPIInt        size;
47c4762a1bSJed Brown   AppCtx             ctx;
48c4762a1bSJed Brown   Tao                tao;
49c4762a1bSJed Brown   KSP                ksp;
50c4762a1bSJed Brown   PC                 pc;
51c4762a1bSJed Brown   Vec                lambda[1],mu[1],lowerb,upperb;
52c4762a1bSJed Brown   PetscBool          printtofile;
53c4762a1bSJed Brown   PetscInt           direction[2];
54c4762a1bSJed Brown   PetscBool          terminate[2];
55c4762a1bSJed Brown   Mat                qgrad;         /* Forward sesivitiy */
56c4762a1bSJed Brown   Mat                sp;            /* Forward sensitivity matrix */
57c4762a1bSJed Brown 
58c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
59c4762a1bSJed Brown      Initialize program
60c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
61c4762a1bSJed Brown   ierr = PetscInitialize(&argc,&argv,NULL,help);if (ierr) return ierr;
62c4762a1bSJed Brown   PetscFunctionBeginUser;
63*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(PETSC_COMM_WORLD,&size));
643c633725SBarry Smith   PetscCheck(size == 1,PETSC_COMM_WORLD,PETSC_ERR_WRONG_MPI_SIZE,"This is a uniprocessor example only!");
65c4762a1bSJed Brown 
66c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
67c4762a1bSJed Brown     Set runtime options
68c4762a1bSJed Brown     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
69c4762a1bSJed Brown   ierr = PetscOptionsBegin(PETSC_COMM_WORLD,NULL,"Swing equation options","");CHKERRQ(ierr);
70c4762a1bSJed Brown   {
71c4762a1bSJed Brown     ctx.beta    = 2;
72c4762a1bSJed Brown     ctx.c       = 10000.0;
73c4762a1bSJed Brown     ctx.u_s     = 1.0;
74c4762a1bSJed Brown     ctx.omega_s = 1.0;
75c4762a1bSJed Brown     ctx.omega_b = 120.0*PETSC_PI;
76c4762a1bSJed Brown     ctx.H       = 5.0;
77*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsScalar("-Inertia","","",ctx.H,&ctx.H,NULL));
78c4762a1bSJed Brown     ctx.D       = 5.0;
79*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsScalar("-D","","",ctx.D,&ctx.D,NULL));
80c4762a1bSJed Brown     ctx.E       = 1.1378;
81c4762a1bSJed Brown     ctx.V       = 1.0;
82c4762a1bSJed Brown     ctx.X       = 0.545;
83c4762a1bSJed Brown     ctx.Pmax    = ctx.E*ctx.V/ctx.X;
84c4762a1bSJed Brown     ctx.Pmax_ini = ctx.Pmax;
85*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsScalar("-Pmax","","",ctx.Pmax,&ctx.Pmax,NULL));
86c4762a1bSJed Brown     ctx.Pm      = 1.06;
87*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsScalar("-Pm","","",ctx.Pm,&ctx.Pm,NULL));
88c4762a1bSJed Brown     ctx.tf      = 0.1;
89c4762a1bSJed Brown     ctx.tcl     = 0.2;
90*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsReal("-tf","Time to start fault","",ctx.tf,&ctx.tf,NULL));
91*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsReal("-tcl","Time to end fault","",ctx.tcl,&ctx.tcl,NULL));
92c4762a1bSJed Brown     printtofile = PETSC_FALSE;
93*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsBool("-printtofile","Print convergence results to file","",printtofile,&printtofile,NULL));
94c4762a1bSJed Brown     ctx.sa      = SA_ADJ;
95*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscOptionsEnum("-sa_method","Sensitivity analysis method (adj or tlm)","",SAMethods,(PetscEnum)ctx.sa,(PetscEnum*)&ctx.sa,NULL));
96c4762a1bSJed Brown   }
97c4762a1bSJed Brown   ierr = PetscOptionsEnd();CHKERRQ(ierr);
98c4762a1bSJed Brown 
99c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
100c4762a1bSJed Brown     Create necessary matrix and vectors
101c4762a1bSJed Brown     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
102*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreate(PETSC_COMM_WORLD,&ctx.Jac));
103*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetSizes(ctx.Jac,2,2,PETSC_DETERMINE,PETSC_DETERMINE));
104*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetType(ctx.Jac,MATDENSE));
105*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetFromOptions(ctx.Jac));
106*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetUp(ctx.Jac));
107*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreate(PETSC_COMM_WORLD,&ctx.Jacp));
108*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetSizes(ctx.Jacp,PETSC_DECIDE,PETSC_DECIDE,2,1));
109*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetFromOptions(ctx.Jacp));
110*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetUp(ctx.Jacp));
111*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreateVecs(ctx.Jac,&ctx.U,NULL));
112*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreateDense(PETSC_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,1,1,NULL,&ctx.DRDP));
113*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetUp(ctx.DRDP));
114*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreateDense(PETSC_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,2,1,NULL,&ctx.DRDU));
115*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetUp(ctx.DRDU));
116c4762a1bSJed Brown 
117c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
118c4762a1bSJed Brown      Create timestepping solver context
119c4762a1bSJed Brown      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
120*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSCreate(PETSC_COMM_WORLD,&ctx.ts));
121*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetProblemType(ctx.ts,TS_NONLINEAR));
122*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetType(ctx.ts,TSCN));
123*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetRHSFunction(ctx.ts,NULL,(TSRHSFunction)RHSFunction,&ctx));
124*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetRHSJacobian(ctx.ts,ctx.Jac,ctx.Jac,(TSRHSJacobian)RHSJacobian,&ctx));
125*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetRHSJacobianP(ctx.ts,ctx.Jacp,RHSJacobianP,&ctx));
126c4762a1bSJed Brown 
127c4762a1bSJed Brown   if (ctx.sa == SA_ADJ) {
128*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCreateVecs(ctx.Jac,&lambda[0],NULL));
129*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCreateVecs(ctx.Jacp,&mu[0],NULL));
130*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSSetSaveTrajectory(ctx.ts));
131*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSSetCostGradients(ctx.ts,1,lambda,mu));
132*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSCreateQuadratureTS(ctx.ts,PETSC_FALSE,&ctx.quadts));
133*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSSetRHSFunction(ctx.quadts,NULL,(TSRHSFunction)CostIntegrand,&ctx));
134*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSSetRHSJacobian(ctx.quadts,ctx.DRDU,ctx.DRDU,(TSRHSJacobian)DRDUJacobianTranspose,&ctx));
135*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSSetRHSJacobianP(ctx.quadts,ctx.DRDP,DRDPJacobianTranspose,&ctx));
136c4762a1bSJed Brown   }
137c4762a1bSJed Brown   if (ctx.sa == SA_TLM) {
138*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCreateDense(PETSC_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,1,1,NULL,&qgrad));
139*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatCreateDense(PETSC_COMM_WORLD,PETSC_DECIDE,PETSC_DECIDE,2,1,NULL,&sp));
140*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSForwardSetSensitivities(ctx.ts,1,sp));
141*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSCreateQuadratureTS(ctx.ts,PETSC_TRUE,&ctx.quadts));
142*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSForwardSetSensitivities(ctx.quadts,1,qgrad));
143*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSSetRHSFunction(ctx.quadts,NULL,(TSRHSFunction)CostIntegrand,&ctx));
144*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSSetRHSJacobian(ctx.quadts,ctx.DRDU,ctx.DRDU,(TSRHSJacobian)DRDUJacobianTranspose,&ctx));
145*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSSetRHSJacobianP(ctx.quadts,ctx.DRDP,DRDPJacobianTranspose,&ctx));
146c4762a1bSJed Brown   }
147c4762a1bSJed Brown 
148c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
149c4762a1bSJed Brown      Set solver options
150c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
151*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetMaxTime(ctx.ts,1.0));
152*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetExactFinalTime(ctx.ts,TS_EXACTFINALTIME_MATCHSTEP));
153*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetTimeStep(ctx.ts,0.03125));
154*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetFromOptions(ctx.ts));
155c4762a1bSJed Brown 
156c4762a1bSJed Brown   direction[0] = direction[1] = 1;
157c4762a1bSJed Brown   terminate[0] = terminate[1] = PETSC_FALSE;
158*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetEventHandler(ctx.ts,2,direction,terminate,EventFunction,PostEventFunction,&ctx));
159c4762a1bSJed Brown 
160c4762a1bSJed Brown   /* Create TAO solver and set desired solution method */
161*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TaoCreate(PETSC_COMM_WORLD,&tao));
162*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TaoSetType(tao,TAOBLMVM));
163c4762a1bSJed Brown   if (printtofile) {
164*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TaoSetMonitor(tao,(PetscErrorCode (*)(Tao, void*))monitor,(void *)&ctx,PETSC_NULL));
165c4762a1bSJed Brown   }
166c4762a1bSJed Brown   /*
167c4762a1bSJed Brown      Optimization starts
168c4762a1bSJed Brown   */
169c4762a1bSJed Brown   /* Set initial solution guess */
170*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCreateSeq(PETSC_COMM_WORLD,1,&p));
171*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(p,&x_ptr));
172c4762a1bSJed Brown   x_ptr[0] = ctx.Pm;
173*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(p,&x_ptr));
174c4762a1bSJed Brown 
175*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TaoSetSolution(tao,p));
176c4762a1bSJed Brown   /* Set routine for function and gradient evaluation */
177*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TaoSetObjectiveAndGradient(tao,NULL,FormFunctionGradient,(void *)&ctx));
178c4762a1bSJed Brown 
179c4762a1bSJed Brown   /* Set bounds for the optimization */
180*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDuplicate(p,&lowerb));
181*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDuplicate(p,&upperb));
182*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(lowerb,&x_ptr));
183c4762a1bSJed Brown   x_ptr[0] = 0.;
184*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(lowerb,&x_ptr));
185*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(upperb,&x_ptr));
186c4762a1bSJed Brown   x_ptr[0] = 1.1;
187*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(upperb,&x_ptr));
188*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TaoSetVariableBounds(tao,lowerb,upperb));
189c4762a1bSJed Brown 
190c4762a1bSJed Brown   /* Check for any TAO command line options */
191*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TaoSetFromOptions(tao));
192*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TaoGetKSP(tao,&ksp));
193c4762a1bSJed Brown   if (ksp) {
194*5f80ce2aSJacob Faibussowitsch     CHKERRQ(KSPGetPC(ksp,&pc));
195*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PCSetType(pc,PCNONE));
196c4762a1bSJed Brown   }
197c4762a1bSJed Brown 
198c4762a1bSJed Brown   /* SOLVE THE APPLICATION */
199*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TaoSolve(tao));
200c4762a1bSJed Brown 
201*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecView(p,PETSC_VIEWER_STDOUT_WORLD));
202c4762a1bSJed Brown 
203c4762a1bSJed Brown   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
204c4762a1bSJed Brown      Free work space.  All PETSc objects should be destroyed when they are no longer needed.
205c4762a1bSJed Brown    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
206*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&ctx.Jac));
207*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&ctx.Jacp));
208*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&ctx.DRDU));
209*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&ctx.DRDP));
210*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&ctx.U));
211c4762a1bSJed Brown   if (ctx.sa == SA_ADJ) {
212*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDestroy(&lambda[0]));
213*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecDestroy(&mu[0]));
214c4762a1bSJed Brown   }
215c4762a1bSJed Brown   if (ctx.sa == SA_TLM) {
216*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDestroy(&qgrad));
217*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDestroy(&sp));
218c4762a1bSJed Brown   }
219*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSDestroy(&ctx.ts));
220*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&p));
221*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&lowerb));
222*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&upperb));
223*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TaoDestroy(&tao));
224c4762a1bSJed Brown   ierr = PetscFinalize();
225c4762a1bSJed Brown   return ierr;
226c4762a1bSJed Brown }
227c4762a1bSJed Brown 
228c4762a1bSJed Brown /* ------------------------------------------------------------------ */
229c4762a1bSJed Brown /*
230c4762a1bSJed Brown    FormFunctionGradient - Evaluates the function and corresponding gradient.
231c4762a1bSJed Brown 
232c4762a1bSJed Brown    Input Parameters:
233c4762a1bSJed Brown    tao - the Tao context
234c4762a1bSJed Brown    X   - the input vector
235a82e8c82SStefano Zampini    ptr - optional user-defined context, as set by TaoSetObjectiveAndGradient()
236c4762a1bSJed Brown 
237c4762a1bSJed Brown    Output Parameters:
238c4762a1bSJed Brown    f   - the newly evaluated function
239c4762a1bSJed Brown    G   - the newly evaluated gradient
240c4762a1bSJed Brown */
241c4762a1bSJed Brown PetscErrorCode FormFunctionGradient(Tao tao,Vec P,PetscReal *f,Vec G,void *ctx0)
242c4762a1bSJed Brown {
243c4762a1bSJed Brown   AppCtx         *ctx = (AppCtx*)ctx0;
244c4762a1bSJed Brown   PetscInt       nadj;
245c4762a1bSJed Brown   PetscReal      ftime;
246c4762a1bSJed Brown   PetscInt       steps;
247c4762a1bSJed Brown   PetscScalar    *u;
248c4762a1bSJed Brown   PetscScalar    *x_ptr,*y_ptr;
249c4762a1bSJed Brown   Vec            q;
250c4762a1bSJed Brown   Mat            qgrad;
251c4762a1bSJed Brown 
252*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArrayRead(P,(const PetscScalar**)&x_ptr));
253c4762a1bSJed Brown   ctx->Pm = x_ptr[0];
254*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArrayRead(P,(const PetscScalar**)&x_ptr));
255c4762a1bSJed Brown 
256c4762a1bSJed Brown   /* reinitialize the solution vector */
257*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(ctx->U,&u));
258c4762a1bSJed Brown   u[0] = PetscAsinScalar(ctx->Pm/ctx->Pmax);
259c4762a1bSJed Brown   u[1] = 1.0;
260*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(ctx->U,&u));
261*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetSolution(ctx->ts,ctx->U));
262c4762a1bSJed Brown 
263c4762a1bSJed Brown   /* reset time */
264*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetTime(ctx->ts,0.0));
265c4762a1bSJed Brown 
266c4762a1bSJed Brown   /* reset step counter, this is critical for adjoint solver */
267*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetStepNumber(ctx->ts,0));
268c4762a1bSJed Brown 
269c4762a1bSJed Brown   /* reset step size, the step size becomes negative after TSAdjointSolve */
270*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSetTimeStep(ctx->ts,0.03125));
271c4762a1bSJed Brown 
272c4762a1bSJed Brown   /* reinitialize the integral value */
273*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSGetQuadratureTS(ctx->ts,NULL,&ctx->quadts));
274*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSGetSolution(ctx->quadts,&q));
275*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSet(q,0.0));
276c4762a1bSJed Brown 
277c4762a1bSJed Brown   if (ctx->sa == SA_TLM) { /* reset the forward sensitivities */
278c4762a1bSJed Brown     TS             quadts;
279c4762a1bSJed Brown     Mat            sp;
280c4762a1bSJed Brown     PetscScalar    val[2];
281c4762a1bSJed Brown     const PetscInt row[]={0,1},col[]={0};
282c4762a1bSJed Brown 
283*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSGetQuadratureTS(ctx->ts,NULL,&quadts));
284*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSForwardGetSensitivities(quadts,NULL,&qgrad));
285*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatZeroEntries(qgrad));
286*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSForwardGetSensitivities(ctx->ts,NULL,&sp));
287c4762a1bSJed Brown     val[0] = 1./PetscSqrtScalar(1.-(ctx->Pm/ctx->Pmax)*(ctx->Pm/ctx->Pmax))/ctx->Pmax;
288c4762a1bSJed Brown     val[1] = 0.0;
289*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatSetValues(sp,2,row,1,col,val,INSERT_VALUES));
290*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatAssemblyBegin(sp,MAT_FINAL_ASSEMBLY));
291*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatAssemblyEnd(sp,MAT_FINAL_ASSEMBLY));
292c4762a1bSJed Brown   }
293c4762a1bSJed Brown 
294c4762a1bSJed Brown   /* solve the ODE */
295*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSSolve(ctx->ts,ctx->U));
296*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSGetSolveTime(ctx->ts,&ftime));
297*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSGetStepNumber(ctx->ts,&steps));
298c4762a1bSJed Brown 
299c4762a1bSJed Brown   if (ctx->sa == SA_ADJ) {
300c4762a1bSJed Brown     Vec *lambda,*mu;
301c4762a1bSJed Brown     /* reset the terminal condition for adjoint */
302*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSGetCostGradients(ctx->ts,&nadj,&lambda,&mu));
303*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArray(lambda[0],&y_ptr));
304c4762a1bSJed Brown     y_ptr[0] = 0.0; y_ptr[1] = 0.0;
305*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(lambda[0],&y_ptr));
306*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArray(mu[0],&x_ptr));
307c4762a1bSJed Brown     x_ptr[0] = -1.0;
308*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(mu[0],&x_ptr));
309c4762a1bSJed Brown 
310c4762a1bSJed Brown     /* solve the adjont */
311*5f80ce2aSJacob Faibussowitsch     CHKERRQ(TSAdjointSolve(ctx->ts));
312c4762a1bSJed Brown 
313*5f80ce2aSJacob Faibussowitsch     CHKERRQ(ComputeSensiP(lambda[0],mu[0],ctx));
314*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecCopy(mu[0],G));
315c4762a1bSJed Brown   }
316c4762a1bSJed Brown 
317c4762a1bSJed Brown   if (ctx->sa == SA_TLM) {
318*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArray(G,&x_ptr));
319*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDenseGetArray(qgrad,&y_ptr));
320c4762a1bSJed Brown     x_ptr[0] = y_ptr[0]-1.;
321*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatDenseRestoreArray(qgrad,&y_ptr));
322*5f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(G,&x_ptr));
323c4762a1bSJed Brown   }
324c4762a1bSJed Brown 
325*5f80ce2aSJacob Faibussowitsch   CHKERRQ(TSGetSolution(ctx->quadts,&q));
326*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(q,&x_ptr));
327c4762a1bSJed Brown   *f   = -ctx->Pm + x_ptr[0];
328*5f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(q,&x_ptr));
329c4762a1bSJed Brown   return 0;
330c4762a1bSJed Brown }
331c4762a1bSJed Brown 
332c4762a1bSJed Brown /*TEST
333c4762a1bSJed Brown 
334c4762a1bSJed Brown    build:
335c4762a1bSJed Brown       requires: !complex !single
336c4762a1bSJed Brown 
337c4762a1bSJed Brown    test:
338c4762a1bSJed Brown       args: -viewer_binary_skip_info -ts_type cn -pc_type lu -tao_monitor
339c4762a1bSJed Brown 
340c4762a1bSJed Brown    test:
341c4762a1bSJed Brown       suffix: 2
342c4762a1bSJed Brown       output_file: output/ex3opt_1.out
343c4762a1bSJed Brown       args: -sa_method tlm -ts_type cn -pc_type lu -tao_monitor
344c4762a1bSJed Brown TEST*/
345