Actual source code: ex9opt.c

petsc-3.8.3 2017-12-09
Report Typos and Errors

  2: static char help[] = "Basic equation for generator stability analysis.\n";


\begin{eqnarray}
\frac{d \theta}{dt} = \omega_b (\omega - \omega_s)
\frac{2 H}{\omega_s}\frac{d \omega}{dt} & = & P_m - P_max \sin(\theta) -D(\omega - \omega_s)\\
\end{eqnarray}



Ensemble of initial conditions
./ex2 -ensemble -ts_monitor_draw_solution_phase -1,-3,3,3 -ts_adapt_dt_max .01 -ts_monitor -ts_type rosw -pc_type lu -ksp_type preonly

Fault at .1 seconds
./ex2 -ts_monitor_draw_solution_phase .42,.95,.6,1.05 -ts_adapt_dt_max .01 -ts_monitor -ts_type rosw -pc_type lu -ksp_type preonly

Initial conditions same as when fault is ended
./ex2 -u 0.496792,1.00932 -ts_monitor_draw_solution_phase .42,.95,.6,1.05 -ts_adapt_dt_max .01 -ts_monitor -ts_type rosw -pc_type lu -ksp_type preonly


 25: /*
 26:    Include "petscts.h" so that we can use TS solvers.  Note that this
 27:    file automatically includes:
 28:      petscsys.h       - base PETSc routines   petscvec.h - vectors
 29:      petscmat.h - matrices
 30:      petscis.h     - index sets            petscksp.h - Krylov subspace methods
 31:      petscviewer.h - viewers               petscpc.h  - preconditioners
 32:      petscksp.h   - linear solvers
 33: */
 34: #include <petsctao.h>
 35: #include <petscts.h>

 37: typedef struct {
 38:   PetscScalar H,D,omega_b,omega_s,Pmax,Pm,E,V,X,u_s,c;
 39:   PetscInt    beta;
 40:   PetscReal   tf,tcl;
 41: } AppCtx;

 43: PetscErrorCode FormFunction(Tao,Vec,PetscReal*,void*);
 44: PetscErrorCode FormGradient(Tao,Vec,Vec,void*);

 46: /*
 47:      Defines the ODE passed to the ODE solver
 48: */
 49: static PetscErrorCode RHSFunction(TS ts,PetscReal t,Vec U,Vec F,AppCtx *ctx)
 50: {
 51:   PetscErrorCode    ierr;
 52:   PetscScalar       *f,Pmax;
 53:   const PetscScalar *u;

 56:   /*  The next three lines allow us to access the entries of the vectors directly */
 57:   VecGetArrayRead(U,&u);
 58:   VecGetArray(F,&f);
 59:   if ((t > ctx->tf) && (t < ctx->tcl)) Pmax = 0.0; /* A short-circuit on the generator terminal that drives the electrical power output (Pmax*sin(delta)) to 0 */
 60:   else Pmax = ctx->Pmax;

 62:   f[0] = ctx->omega_b*(u[1] - ctx->omega_s);
 63:   f[1] = (-Pmax*PetscSinScalar(u[0]) - ctx->D*(u[1] - ctx->omega_s) + ctx->Pm)*ctx->omega_s/(2.0*ctx->H);

 65:   VecRestoreArrayRead(U,&u);
 66:   VecRestoreArray(F,&f);
 67:   return(0);
 68: }

 70: /*
 71:      Defines the Jacobian of the ODE passed to the ODE solver. See TSSetIJacobian() for the meaning of a and the Jacobian.
 72: */
 73: static PetscErrorCode RHSJacobian(TS ts,PetscReal t,Vec U,Mat A,Mat B,AppCtx *ctx)
 74: {
 75:   PetscErrorCode    ierr;
 76:   PetscInt          rowcol[] = {0,1};
 77:   PetscScalar       J[2][2],Pmax;
 78:   const PetscScalar *u;

 81:   VecGetArrayRead(U,&u);
 82:   if ((t > ctx->tf) && (t < ctx->tcl)) Pmax = 0.0; /* A short-circuit on the generator terminal that drives the electrical power output (Pmax*sin(delta)) to 0 */
 83:   else Pmax = ctx->Pmax;

 85:   J[0][0] = 0;                                  J[0][1] = ctx->omega_b;
 86:   J[1][1] = -ctx->D*ctx->omega_s/(2.0*ctx->H);  J[1][0] = -Pmax*PetscCosScalar(u[0])*ctx->omega_s/(2.0*ctx->H);

 88:   MatSetValues(B,2,rowcol,2,rowcol,&J[0][0],INSERT_VALUES);
 89:   VecRestoreArrayRead(U,&u);

 91:   MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
 92:   MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);
 93:   if (A != B) {
 94:     MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);
 95:     MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);
 96:   }
 97:   return(0);
 98: }

100: static PetscErrorCode RHSJacobianP(TS ts,PetscReal t,Vec X,Mat A,void *ctx0)
101: {
103:   PetscInt       row[] = {0,1},col[]={0};
104:   PetscScalar    J[2][1];
105:   AppCtx         *ctx=(AppCtx*)ctx0;

108:   J[0][0] = 0;
109:   J[1][0] = ctx->omega_s/(2.0*ctx->H);
110:   MatSetValues(A,2,row,1,col,&J[0][0],INSERT_VALUES);
111:   MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
112:   MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);
113:   return(0);
114: }

116: static PetscErrorCode CostIntegrand(TS ts,PetscReal t,Vec U,Vec R,AppCtx *ctx)
117: {
118:   PetscErrorCode    ierr;
119:   PetscScalar       *r;
120:   const PetscScalar *u;

123:   VecGetArrayRead(U,&u);
124:   VecGetArray(R,&r);
125:   r[0] = ctx->c*PetscPowScalarInt(PetscMax(0., u[0]-ctx->u_s),ctx->beta);
126:   VecRestoreArray(R,&r);
127:   VecRestoreArrayRead(U,&u);
128:   return(0);
129: }

131: static PetscErrorCode DRDYFunction(TS ts,PetscReal t,Vec U,Vec *drdy,AppCtx *ctx)
132: {
133:   PetscErrorCode    ierr;
134:   PetscScalar       *ry;
135:   const PetscScalar *u;

138:   VecGetArrayRead(U,&u);
139:   VecGetArray(drdy[0],&ry);
140:   ry[0] = ctx->c*ctx->beta*PetscPowScalarInt(PetscMax(0., u[0]-ctx->u_s),ctx->beta-1);
141:   VecRestoreArray(drdy[0],&ry);
142:   VecRestoreArrayRead(U,&u);
143:   return(0);
144: }

146: static PetscErrorCode DRDPFunction(TS ts,PetscReal t,Vec U,Vec *drdp,AppCtx *ctx)
147: {
149:   PetscScalar    *rp;

152:   VecGetArray(drdp[0],&rp);
153:   rp[0] = 0.;
154:   VecRestoreArray(drdp[0],&rp);
155:   return(0);
156: }

158: PetscErrorCode ComputeSensiP(Vec lambda,Vec mu,AppCtx *ctx)
159: {
160:   PetscErrorCode    ierr;
161:   PetscScalar       *y,sensip;
162:   const PetscScalar *x;

165:   VecGetArrayRead(lambda,&x);
166:   VecGetArray(mu,&y);
167:   sensip = 1./PetscSqrtScalar(1.-(ctx->Pm/ctx->Pmax)*(ctx->Pm/ctx->Pmax))/ctx->Pmax*x[0]+y[0];
168:   /*PetscPrintf(PETSC_COMM_WORLD,"\n sensitivity wrt parameter pm: %g \n",(double)sensip);*/
169:   y[0] = sensip;
170:   VecRestoreArray(mu,&y);
171:   VecRestoreArrayRead(lambda,&x);
172:   return(0);
173: }

175: int main(int argc,char **argv)
176: {
177:   Vec                p;
178:   PetscScalar        *x_ptr;
179:   PetscErrorCode     ierr;
180:   PetscMPIInt        size;
181:   AppCtx             ctx;
182:   Vec                lowerb,upperb;
183:   Tao                tao;
184:   KSP                ksp;
185:   PC                 pc;

187:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
188:      Initialize program
189:      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
190:   PetscInitialize(&argc,&argv,NULL,help);if (ierr) return ierr;
192:   MPI_Comm_size(PETSC_COMM_WORLD,&size);
193:   if (size != 1) SETERRQ(PETSC_COMM_SELF,1,"This is a uniprocessor example only!");

195:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
196:     Set runtime options
197:     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
198:   PetscOptionsBegin(PETSC_COMM_WORLD,NULL,"Swing equation options","");
199:   {
200:     ctx.beta    = 2;
201:     ctx.c       = 10000.0;
202:     ctx.u_s     = 1.0;
203:     ctx.omega_s = 1.0;
204:     ctx.omega_b = 120.0*PETSC_PI;
205:     ctx.H       = 5.0;
206:     PetscOptionsScalar("-Inertia","","",ctx.H,&ctx.H,NULL);
207:     ctx.D       = 5.0;
208:     PetscOptionsScalar("-D","","",ctx.D,&ctx.D,NULL);
209: #if defined(PETSC_USE_REAL___FLOAT128)
210:     ctx.E       = 1.1378q;
211: #else
212:     ctx.E       = 1.1378;
213: #endif
214:     ctx.V       = 1.0;
215: #if defined(PETSC_USE_REAL___FLOAT128)
216:     ctx.X       = 0.545q;
217: #else
218:     ctx.X       = 0.545;
219: #endif
220:     ctx.Pmax    = ctx.E*ctx.V/ctx.X;;
221:     PetscOptionsScalar("-Pmax","","",ctx.Pmax,&ctx.Pmax,NULL);
222: #if defined(PETSC_USE_REAL___FLOAT128)
223:     ctx.Pm      = 1.0194q;
224: #else
225:     ctx.Pm      = 1.0194;
226: #endif
227:     PetscOptionsScalar("-Pm","","",ctx.Pm,&ctx.Pm,NULL);
228: #if defined(PETSC_USE_REAL___FLOAT128)
229:     ctx.tf      = 0.1q;
230:     ctx.tcl     = 0.2q;
231: #else
232:     ctx.tf      = 0.1;
233:     ctx.tcl     = 0.2;
234: #endif
235:     PetscOptionsReal("-tf","Time to start fault","",ctx.tf,&ctx.tf,NULL);
236:     PetscOptionsReal("-tcl","Time to end fault","",ctx.tcl,&ctx.tcl,NULL);

238:   }
239:   PetscOptionsEnd();

241:   /* Create TAO solver and set desired solution method */
242:   TaoCreate(PETSC_COMM_WORLD,&tao);
243:   TaoSetType(tao,TAOBLMVM);

245:   /*
246:      Optimization starts
247:   */
248:   /* Set initial solution guess */
249:   VecCreateSeq(PETSC_COMM_WORLD,1,&p);
250:   VecGetArray(p,&x_ptr);
251:   x_ptr[0]   = ctx.Pm;
252:   VecRestoreArray(p,&x_ptr);

254:   TaoSetInitialVector(tao,p);
255:   /* Set routine for function and gradient evaluation */
256:   TaoSetObjectiveRoutine(tao,FormFunction,(void *)&ctx);
257:   TaoSetGradientRoutine(tao,FormGradient,(void *)&ctx);

259:   /* Set bounds for the optimization */
260:   VecDuplicate(p,&lowerb);
261:   VecDuplicate(p,&upperb);
262:   VecGetArray(lowerb,&x_ptr);
263:   x_ptr[0] = 0.;
264:   VecRestoreArray(lowerb,&x_ptr);
265:   VecGetArray(upperb,&x_ptr);
266: #if defined(PETSC_USE_REAL___FLOAT128)
267:   x_ptr[0] = 1.1q;
268: #else
269:   x_ptr[0] = 1.1;
270: #endif
271:   VecRestoreArray(upperb,&x_ptr);
272:   TaoSetVariableBounds(tao,lowerb,upperb);

274:   /* Check for any TAO command line options */
275:   TaoSetFromOptions(tao);
276:   TaoGetKSP(tao,&ksp);
277:   if (ksp) {
278:     KSPGetPC(ksp,&pc);
279:     PCSetType(pc,PCNONE);
280:   }

282:   /* SOLVE THE APPLICATION */
283:   TaoSolve(tao);

285:   VecView(p,PETSC_VIEWER_STDOUT_WORLD);
286:   /* Free TAO data structures */
287:   TaoDestroy(&tao);
288:   VecDestroy(&p);
289:   VecDestroy(&lowerb);
290:   VecDestroy(&upperb);
291:   PetscFinalize();
292:   return ierr;
293: }

295: /* ------------------------------------------------------------------ */
296: /*
297:    FormFunction - Evaluates the function

299:    Input Parameters:
300:    tao - the Tao context
301:    X   - the input vector
302:    ptr - optional user-defined context, as set by TaoSetObjectiveAndGradientRoutine()

304:    Output Parameters:
305:    f   - the newly evaluated function
306: */
307: PetscErrorCode FormFunction(Tao tao,Vec P,PetscReal *f,void *ctx0)
308: {
309:   AppCtx         *ctx = (AppCtx*)ctx0;
310:   TS             ts;

312:   Vec            U;             /* solution will be stored here */
313:   Mat            A;             /* Jacobian matrix */
315:   PetscInt       n = 2;
316:   PetscScalar    *u;
317:   PetscScalar    *x_ptr;
318:   Vec            lambda[1],q,mu[1];

320:   VecGetArray(P,&x_ptr);
321:   ctx->Pm = x_ptr[0];
322:   VecRestoreArray(P,&x_ptr);
323:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
324:     Create necessary matrix and vectors
325:     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
326:   MatCreate(PETSC_COMM_WORLD,&A);
327:   MatSetSizes(A,n,n,PETSC_DETERMINE,PETSC_DETERMINE);
328:   MatSetType(A,MATDENSE);
329:   MatSetFromOptions(A);
330:   MatSetUp(A);

332:   MatCreateVecs(A,&U,NULL);
333:   MatCreateVecs(A,&lambda[0],NULL);
334:   MatCreateVecs(A,&mu[0],NULL);

336:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
337:      Create timestepping solver context
338:      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
339:   TSCreate(PETSC_COMM_WORLD,&ts);
340:   TSSetProblemType(ts,TS_NONLINEAR);
341:   TSSetType(ts,TSRK);
342:   TSSetRHSFunction(ts,NULL,(TSRHSFunction)RHSFunction,ctx);
343:   TSSetRHSJacobian(ts,A,A,(TSRHSJacobian)RHSJacobian,ctx);
344:   TSSetExactFinalTime(ts,TS_EXACTFINALTIME_MATCHSTEP);

346:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
347:      Set initial conditions
348:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
349:   VecGetArray(U,&u);
350:   u[0] = PetscAsinScalar(ctx->Pm/ctx->Pmax);
351:   u[1] = 1.0;
352:   VecRestoreArray(U,&u);
353:   TSSetSolution(ts,U);

355:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
356:     Save trajectory of solution so that TSAdjointSolve() may be used
357:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
358:   TSSetSaveTrajectory(ts);

360:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
361:      Set solver options
362:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
363:   TSSetMaxTime(ts,1.0);
364: #if defined(PETSC_USE_REAL___FLOAT128)
365:   TSSetTimeStep(ts,.01q);
366: #else
367:   TSSetTimeStep(ts,.01);
368: #endif
369:   TSSetFromOptions(ts);

371:   TSSetCostGradients(ts,1,lambda,mu);
372:   TSSetCostIntegrand(ts,1,NULL,(PetscErrorCode (*)(TS,PetscReal,Vec,Vec,void*))CostIntegrand,
373:                                         (PetscErrorCode (*)(TS,PetscReal,Vec,Vec*,void*))DRDYFunction,
374:                                         (PetscErrorCode (*)(TS,PetscReal,Vec,Vec*,void*))DRDPFunction,PETSC_TRUE,ctx);

376:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
377:      Solve nonlinear system
378:      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
379:   TSSolve(ts,U);
380:   TSGetCostIntegral(ts,&q);
381:   VecGetArray(q,&x_ptr);
382:   *f   = -ctx->Pm + x_ptr[0];
383:   VecRestoreArray(q,&x_ptr);

385:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
386:      Free work space.  All PETSc objects should be destroyed when they are no longer needed.
387:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
388:   MatDestroy(&A);
389:   VecDestroy(&U);
390:   VecDestroy(&lambda[0]);
391:   VecDestroy(&mu[0]);
392:   TSDestroy(&ts);

394:   return 0;
395: }


398: PetscErrorCode FormGradient(Tao tao,Vec P,Vec G,void *ctx0)
399: {
400:   AppCtx         *ctx = (AppCtx*)ctx0;
401:   TS             ts;

403:   Vec            U;             /* solution will be stored here */
404:   Mat            A;             /* Jacobian matrix */
405:   Mat            Jacp;          /* Jacobian matrix */
407:   PetscInt       n = 2;
408:   PetscReal      ftime;
409:   PetscInt       steps;
410:   PetscScalar    *u;
411:   PetscScalar    *x_ptr,*y_ptr;
412:   Vec            lambda[1],q,mu[1];

414:   VecGetArray(P,&x_ptr);
415:   ctx->Pm = x_ptr[0];
416:   VecRestoreArray(P,&x_ptr);

418:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
419:     Create necessary matrix and vectors
420:     - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
421:   MatCreate(PETSC_COMM_WORLD,&A);
422:   MatSetSizes(A,n,n,PETSC_DETERMINE,PETSC_DETERMINE);
423:   MatSetType(A,MATDENSE);
424:   MatSetFromOptions(A);
425:   MatSetUp(A);

427:   MatCreateVecs(A,&U,NULL);

429:   MatCreate(PETSC_COMM_WORLD,&Jacp);
430:   MatSetSizes(Jacp,PETSC_DECIDE,PETSC_DECIDE,2,1);
431:   MatSetFromOptions(Jacp);
432:   MatSetUp(Jacp);

434:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
435:      Create timestepping solver context
436:      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
437:   TSCreate(PETSC_COMM_WORLD,&ts);
438:   TSSetProblemType(ts,TS_NONLINEAR);
439:   TSSetType(ts,TSRK);
440:   TSSetRHSFunction(ts,NULL,(TSRHSFunction)RHSFunction,ctx);
441:   TSSetRHSJacobian(ts,A,A,(TSRHSJacobian)RHSJacobian,ctx);
442:   TSSetExactFinalTime(ts,TS_EXACTFINALTIME_MATCHSTEP);

444:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
445:      Set initial conditions
446:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
447:   VecGetArray(U,&u);
448:   u[0] = PetscAsinScalar(ctx->Pm/ctx->Pmax);
449:   u[1] = 1.0;
450:   VecRestoreArray(U,&u);
451:   TSSetSolution(ts,U);

453:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
454:     Save trajectory of solution so that TSAdjointSolve() may be used
455:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
456:   TSSetSaveTrajectory(ts);

458:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
459:      Set solver options
460:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
461:   TSSetMaxTime(ts,1.0);
462: #if defined(PETSC_USE_REAL___FLOAT128)
463:   TSSetTimeStep(ts,.01q);
464: #else
465:   TSSetTimeStep(ts,.01);
466: #endif
467:   TSSetFromOptions(ts);

469:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
470:      Solve nonlinear system
471:      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
472:   TSSolve(ts,U);

474:   TSGetSolveTime(ts,&ftime);
475:   TSGetStepNumber(ts,&steps);

477:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
478:      Adjoint model starts here
479:      - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
480:   MatCreateVecs(A,&lambda[0],NULL);
481:   /*   Set initial conditions for the adjoint integration */
482:   VecGetArray(lambda[0],&y_ptr);
483:   y_ptr[0] = 0.0; y_ptr[1] = 0.0;
484:   VecRestoreArray(lambda[0],&y_ptr);

486:   MatCreateVecs(Jacp,&mu[0],NULL);
487:   VecGetArray(mu[0],&x_ptr);
488:   x_ptr[0] = -1.0;
489:   VecRestoreArray(mu[0],&x_ptr);
490:   TSSetCostGradients(ts,1,lambda,mu);

492:   TSAdjointSetRHSJacobian(ts,Jacp,RHSJacobianP,ctx);

494:   TSSetCostIntegrand(ts,1,NULL,(PetscErrorCode (*)(TS,PetscReal,Vec,Vec,void*))CostIntegrand,
495:                                         (PetscErrorCode (*)(TS,PetscReal,Vec,Vec*,void*))DRDYFunction,
496:                                         (PetscErrorCode (*)(TS,PetscReal,Vec,Vec*,void*))DRDPFunction,PETSC_FALSE,ctx);

498:   TSAdjointSolve(ts);
499:   TSGetCostIntegral(ts,&q);
500:   ComputeSensiP(lambda[0],mu[0],ctx);

502:   VecCopy(mu[0],G);

504:   /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
505:      Free work space.  All PETSc objects should be destroyed when they are no longer needed.
506:    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
507:   MatDestroy(&A);
508:   MatDestroy(&Jacp);
509:   VecDestroy(&U);
510:   VecDestroy(&lambda[0]);
511:   VecDestroy(&mu[0]);
512:   TSDestroy(&ts);

514:   return 0;
515: }