Actual source code: ex9opt.c
petsc-3.8.4 2018-03-24
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: }