Actual source code: ex20opt_ic.c
1: static char help[] = "Solves a ODE-constrained optimization problem -- finding the optimal initial conditions for the van der Pol equation.\n";
3: /*
4: Concepts: TS^time-dependent nonlinear problems
5: Concepts: TS^van der Pol equation DAE equivalent
6: Concepts: TS^Optimization using adjoint sensitivity analysis
7: Processors: 1
8: */
9: /*
10: Notes:
11: This code demonstrates how to solve an ODE-constrained optimization problem with TAO, TSAdjoint and TS.
12: The nonlinear problem is written in an ODE equivalent form.
13: The objective is to minimize the difference between observation and model prediction by finding optimal values for initial conditions.
14: The gradient is computed with the discrete adjoint of an implicit method or an explicit method, see ex20adj.c for details.
15: */
17: #include <petsctao.h>
18: #include <petscts.h>
20: typedef struct _n_User *User;
21: struct _n_User {
22: TS ts;
23: PetscReal mu;
24: PetscReal next_output;
26: /* Sensitivity analysis support */
27: PetscInt steps;
28: PetscReal ftime;
29: Mat A; /* Jacobian matrix for ODE */
30: Mat Jacp; /* JacobianP matrix for ODE*/
31: Mat H; /* Hessian matrix for optimization */
32: Vec U,Lambda[1],Mup[1]; /* first-order adjoint variables */
33: Vec Lambda2[2]; /* second-order adjoint variables */
34: Vec Ihp1[1]; /* working space for Hessian evaluations */
35: Vec Dir; /* direction vector */
36: PetscReal ob[2]; /* observation used by the cost function */
37: PetscBool implicitform; /* implicit ODE? */
38: };
39: PetscErrorCode Adjoint2(Vec,PetscScalar[],User);
41: /* ----------------------- Explicit form of the ODE -------------------- */
43: static PetscErrorCode RHSFunction(TS ts,PetscReal t,Vec U,Vec F,void *ctx)
44: {
45: User user = (User)ctx;
46: PetscScalar *f;
47: const PetscScalar *u;
50: VecGetArrayRead(U,&u);
51: VecGetArray(F,&f);
52: f[0] = u[1];
53: f[1] = user->mu*((1.-u[0]*u[0])*u[1]-u[0]);
54: VecRestoreArrayRead(U,&u);
55: VecRestoreArray(F,&f);
56: return 0;
57: }
59: static PetscErrorCode RHSJacobian(TS ts,PetscReal t,Vec U,Mat A,Mat B,void *ctx)
60: {
61: User user = (User)ctx;
62: PetscReal mu = user->mu;
63: PetscInt rowcol[] = {0,1};
64: PetscScalar J[2][2];
65: const PetscScalar *u;
68: VecGetArrayRead(U,&u);
69: J[0][0] = 0;
70: J[1][0] = -mu*(2.0*u[1]*u[0]+1.);
71: J[0][1] = 1.0;
72: J[1][1] = mu*(1.0-u[0]*u[0]);
73: MatSetValues(A,2,rowcol,2,rowcol,&J[0][0],INSERT_VALUES);
74: MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
75: MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);
76: if (A != B) {
77: MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);
78: MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);
79: }
80: VecRestoreArrayRead(U,&u);
81: return 0;
82: }
84: static PetscErrorCode RHSHessianProductUU(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV,void *ctx)
85: {
86: const PetscScalar *vl,*vr,*u;
87: PetscScalar *vhv;
88: PetscScalar dJdU[2][2][2]={{{0}}};
89: PetscInt i,j,k;
90: User user = (User)ctx;
93: VecGetArrayRead(U,&u);
94: VecGetArrayRead(Vl[0],&vl);
95: VecGetArrayRead(Vr,&vr);
96: VecGetArray(VHV[0],&vhv);
98: dJdU[1][0][0] = -2.*user->mu*u[1];
99: dJdU[1][1][0] = -2.*user->mu*u[0];
100: dJdU[1][0][1] = -2.*user->mu*u[0];
101: for (j=0;j<2;j++) {
102: vhv[j] = 0;
103: for (k=0;k<2;k++)
104: for (i=0;i<2;i++)
105: vhv[j] += vl[i]*dJdU[i][j][k]*vr[k];
106: }
107: VecRestoreArrayRead(U,&u);
108: VecRestoreArrayRead(Vl[0],&vl);
109: VecRestoreArrayRead(Vr,&vr);
110: VecRestoreArray(VHV[0],&vhv);
111: return 0;
112: }
114: /* ----------------------- Implicit form of the ODE -------------------- */
116: static PetscErrorCode IFunction(TS ts,PetscReal t,Vec U,Vec Udot,Vec F,void *ctx)
117: {
118: User user = (User)ctx;
119: const PetscScalar *u,*udot;
120: PetscScalar *f;
123: VecGetArrayRead(U,&u);
124: VecGetArrayRead(Udot,&udot);
125: VecGetArray(F,&f);
126: f[0] = udot[0] - u[1];
127: f[1] = udot[1] - user->mu*((1.0-u[0]*u[0])*u[1] - u[0]) ;
128: VecRestoreArrayRead(U,&u);
129: VecRestoreArrayRead(Udot,&udot);
130: VecRestoreArray(F,&f);
131: return 0;
132: }
134: static PetscErrorCode IJacobian(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal a,Mat A,Mat B,void *ctx)
135: {
136: User user = (User)ctx;
137: PetscInt rowcol[] = {0,1};
138: PetscScalar J[2][2];
139: const PetscScalar *u;
142: VecGetArrayRead(U,&u);
143: J[0][0] = a; J[0][1] = -1.0;
144: J[1][0] = user->mu*(1.0 + 2.0*u[0]*u[1]); J[1][1] = a - user->mu*(1.0-u[0]*u[0]);
145: MatSetValues(B,2,rowcol,2,rowcol,&J[0][0],INSERT_VALUES);
146: VecRestoreArrayRead(U,&u);
147: MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
148: MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);
149: if (A != B) {
150: MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);
151: MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);
152: }
153: return 0;
154: }
156: /* Monitor timesteps and use interpolation to output at integer multiples of 0.1 */
157: static PetscErrorCode Monitor(TS ts,PetscInt step,PetscReal t,Vec U,void *ctx)
158: {
159: const PetscScalar *u;
160: PetscReal tfinal, dt;
161: User user = (User)ctx;
162: Vec interpolatedU;
165: TSGetTimeStep(ts,&dt);
166: TSGetMaxTime(ts,&tfinal);
168: while (user->next_output <= t && user->next_output <= tfinal) {
169: VecDuplicate(U,&interpolatedU);
170: TSInterpolate(ts,user->next_output,interpolatedU);
171: VecGetArrayRead(interpolatedU,&u);
172: PetscCall(PetscPrintf(PETSC_COMM_WORLD,"[%g] %D TS %g (dt = %g) X %g %g\n",
173: (double)user->next_output,step,(double)t,(double)dt,(double)PetscRealPart(u[0]),
174: (double)PetscRealPart(u[1])));
175: VecRestoreArrayRead(interpolatedU,&u);
176: VecDestroy(&interpolatedU);
177: user->next_output += 0.1;
178: }
179: return 0;
180: }
182: static PetscErrorCode IHessianProductUU(TS ts,PetscReal t,Vec U,Vec *Vl,Vec Vr,Vec *VHV,void *ctx)
183: {
184: const PetscScalar *vl,*vr,*u;
185: PetscScalar *vhv;
186: PetscScalar dJdU[2][2][2]={{{0}}};
187: PetscInt i,j,k;
188: User user = (User)ctx;
191: VecGetArrayRead(U,&u);
192: VecGetArrayRead(Vl[0],&vl);
193: VecGetArrayRead(Vr,&vr);
194: VecGetArray(VHV[0],&vhv);
195: dJdU[1][0][0] = 2.*user->mu*u[1];
196: dJdU[1][1][0] = 2.*user->mu*u[0];
197: dJdU[1][0][1] = 2.*user->mu*u[0];
198: for (j=0;j<2;j++) {
199: vhv[j] = 0;
200: for (k=0;k<2;k++)
201: for (i=0;i<2;i++)
202: vhv[j] += vl[i]*dJdU[i][j][k]*vr[k];
203: }
204: VecRestoreArrayRead(U,&u);
205: VecRestoreArrayRead(Vl[0],&vl);
206: VecRestoreArrayRead(Vr,&vr);
207: VecRestoreArray(VHV[0],&vhv);
208: return 0;
209: }
211: /* ------------------ User-defined routines for TAO -------------------------- */
213: static PetscErrorCode FormFunctionGradient(Tao tao,Vec IC,PetscReal *f,Vec G,void *ctx)
214: {
215: User user_ptr = (User)ctx;
216: TS ts = user_ptr->ts;
217: const PetscScalar *x_ptr;
218: PetscScalar *y_ptr;
221: VecCopy(IC,user_ptr->U); /* set up the initial condition */
223: TSSetTime(ts,0.0);
224: TSSetStepNumber(ts,0);
225: TSSetTimeStep(ts,0.001); /* can be overwritten by command line options */
226: TSSetFromOptions(ts);
227: TSSolve(ts,user_ptr->U);
229: VecGetArrayRead(user_ptr->U,&x_ptr);
230: VecGetArray(user_ptr->Lambda[0],&y_ptr);
231: *f = (x_ptr[0]-user_ptr->ob[0])*(x_ptr[0]-user_ptr->ob[0])+(x_ptr[1]-user_ptr->ob[1])*(x_ptr[1]-user_ptr->ob[1]);
232: y_ptr[0] = 2.*(x_ptr[0]-user_ptr->ob[0]);
233: y_ptr[1] = 2.*(x_ptr[1]-user_ptr->ob[1]);
234: VecRestoreArray(user_ptr->Lambda[0],&y_ptr);
235: VecRestoreArrayRead(user_ptr->U,&x_ptr);
237: TSSetCostGradients(ts,1,user_ptr->Lambda,NULL);
238: TSAdjointSolve(ts);
239: VecCopy(user_ptr->Lambda[0],G);
240: return 0;
241: }
243: static PetscErrorCode FormHessian(Tao tao,Vec U,Mat H,Mat Hpre,void *ctx)
244: {
245: User user_ptr = (User)ctx;
246: PetscScalar harr[2];
247: PetscScalar *x_ptr;
248: const PetscInt rows[2] = {0,1};
249: PetscInt col;
252: VecCopy(U,user_ptr->U);
253: VecGetArray(user_ptr->Dir,&x_ptr);
254: x_ptr[0] = 1.;
255: x_ptr[1] = 0.;
256: VecRestoreArray(user_ptr->Dir,&x_ptr);
257: Adjoint2(user_ptr->U,harr,user_ptr);
258: col = 0;
259: MatSetValues(H,2,rows,1,&col,harr,INSERT_VALUES);
261: VecCopy(U,user_ptr->U);
262: VecGetArray(user_ptr->Dir,&x_ptr);
263: x_ptr[0] = 0.;
264: x_ptr[1] = 1.;
265: VecRestoreArray(user_ptr->Dir,&x_ptr);
266: Adjoint2(user_ptr->U,harr,user_ptr);
267: col = 1;
268: MatSetValues(H,2,rows,1,&col,harr,INSERT_VALUES);
270: MatAssemblyBegin(H,MAT_FINAL_ASSEMBLY);
271: MatAssemblyEnd(H,MAT_FINAL_ASSEMBLY);
272: if (H != Hpre) {
273: MatAssemblyBegin(Hpre,MAT_FINAL_ASSEMBLY);
274: MatAssemblyEnd(Hpre,MAT_FINAL_ASSEMBLY);
275: }
276: return 0;
277: }
279: static PetscErrorCode MatrixFreeHessian(Tao tao,Vec U,Mat H,Mat Hpre,void *ctx)
280: {
281: User user_ptr = (User)ctx;
284: VecCopy(U,user_ptr->U);
285: return 0;
286: }
288: /* ------------ Routines calculating second-order derivatives -------------- */
290: /*
291: Compute the Hessian-vector product for the cost function using Second-order adjoint
292: */
293: PetscErrorCode Adjoint2(Vec U,PetscScalar arr[],User ctx)
294: {
295: TS ts = ctx->ts;
296: PetscScalar *x_ptr,*y_ptr;
297: Mat tlmsen;
300: TSAdjointReset(ts);
302: TSSetTime(ts,0.0);
303: TSSetStepNumber(ts,0);
304: TSSetTimeStep(ts,0.001);
305: TSSetFromOptions(ts);
306: TSSetCostHessianProducts(ts,1,ctx->Lambda2,NULL,ctx->Dir);
307: TSAdjointSetForward(ts,NULL);
308: TSSolve(ts,U);
310: /* Set terminal conditions for first- and second-order adjonts */
311: VecGetArray(U,&x_ptr);
312: VecGetArray(ctx->Lambda[0],&y_ptr);
313: y_ptr[0] = 2.*(x_ptr[0]-ctx->ob[0]);
314: y_ptr[1] = 2.*(x_ptr[1]-ctx->ob[1]);
315: VecRestoreArray(ctx->Lambda[0],&y_ptr);
316: VecRestoreArray(U,&x_ptr);
317: TSForwardGetSensitivities(ts,NULL,&tlmsen);
318: MatDenseGetColumn(tlmsen,0,&x_ptr);
319: VecGetArray(ctx->Lambda2[0],&y_ptr);
320: y_ptr[0] = 2.*x_ptr[0];
321: y_ptr[1] = 2.*x_ptr[1];
322: VecRestoreArray(ctx->Lambda2[0],&y_ptr);
323: MatDenseRestoreColumn(tlmsen,&x_ptr);
325: TSSetCostGradients(ts,1,ctx->Lambda,NULL);
326: if (ctx->implicitform) {
327: TSSetIHessianProduct(ts,ctx->Ihp1,IHessianProductUU,NULL,NULL,NULL,NULL,NULL,NULL,ctx);
328: } else {
329: TSSetRHSHessianProduct(ts,ctx->Ihp1,RHSHessianProductUU,NULL,NULL,NULL,NULL,NULL,NULL,ctx);
330: }
331: TSAdjointSolve(ts);
333: VecGetArray(ctx->Lambda2[0],&x_ptr);
334: arr[0] = x_ptr[0];
335: arr[1] = x_ptr[1];
336: VecRestoreArray(ctx->Lambda2[0],&x_ptr);
338: TSAdjointReset(ts);
339: TSAdjointResetForward(ts);
340: return 0;
341: }
343: PetscErrorCode FiniteDiff(Vec U,PetscScalar arr[],User ctx)
344: {
345: Vec Up,G,Gp;
346: const PetscScalar eps = PetscRealConstant(1e-7);
347: PetscScalar *u;
348: Tao tao = NULL;
349: PetscReal f;
352: VecDuplicate(U,&Up);
353: VecDuplicate(U,&G);
354: VecDuplicate(U,&Gp);
356: FormFunctionGradient(tao,U,&f,G,ctx);
358: VecCopy(U,Up);
359: VecGetArray(Up,&u);
360: u[0] += eps;
361: VecRestoreArray(Up,&u);
362: FormFunctionGradient(tao,Up,&f,Gp,ctx);
363: VecAXPY(Gp,-1,G);
364: VecScale(Gp,1./eps);
365: VecGetArray(Gp,&u);
366: arr[0] = u[0];
367: arr[1] = u[1];
368: VecRestoreArray(Gp,&u);
370: VecCopy(U,Up);
371: VecGetArray(Up,&u);
372: u[1] += eps;
373: VecRestoreArray(Up,&u);
374: FormFunctionGradient(tao,Up,&f,Gp,ctx);
375: VecAXPY(Gp,-1,G);
376: VecScale(Gp,1./eps);
377: VecGetArray(Gp,&u);
378: arr[2] = u[0];
379: arr[3] = u[1];
380: VecRestoreArray(Gp,&u);
382: VecDestroy(&G);
383: VecDestroy(&Gp);
384: VecDestroy(&Up);
385: return 0;
386: }
388: static PetscErrorCode HessianProductMat(Mat mat,Vec svec,Vec y)
389: {
390: User user_ptr;
391: PetscScalar *y_ptr;
394: MatShellGetContext(mat,&user_ptr);
395: VecCopy(svec,user_ptr->Dir);
396: VecGetArray(y,&y_ptr);
397: Adjoint2(user_ptr->U,y_ptr,user_ptr);
398: VecRestoreArray(y,&y_ptr);
399: return 0;
400: }
402: int main(int argc,char **argv)
403: {
404: PetscBool monitor = PETSC_FALSE,mf = PETSC_TRUE;
405: PetscInt mode = 0;
406: PetscMPIInt size;
407: struct _n_User user;
408: Vec x; /* working vector for TAO */
409: PetscScalar *x_ptr,arr[4];
410: PetscScalar ic1 = 2.2,ic2 = -0.7; /* initial guess for TAO */
411: Tao tao;
412: KSP ksp;
413: PC pc;
415: /* Initialize program */
416: PetscInitialize(&argc,&argv,NULL,help);
417: MPI_Comm_size(PETSC_COMM_WORLD,&size);
420: /* Set runtime options */
421: user.next_output = 0.0;
422: user.mu = 1.0e3;
423: user.steps = 0;
424: user.ftime = 0.5;
425: user.implicitform = PETSC_TRUE;
427: PetscOptionsGetBool(NULL,NULL,"-monitor",&monitor,NULL);
428: PetscOptionsGetReal(NULL,NULL,"-mu",&user.mu,NULL);
429: PetscOptionsGetInt(NULL,NULL,"-mode",&mode,NULL);
430: PetscOptionsGetReal(NULL,NULL,"-ic1",&ic1,NULL);
431: PetscOptionsGetReal(NULL,NULL,"-ic2",&ic2,NULL);
432: PetscOptionsGetBool(NULL,NULL,"-my_tao_mf",&mf,NULL); /* matrix-free hessian for optimization */
433: PetscOptionsGetBool(NULL,NULL,"-implicitform",&user.implicitform,NULL);
435: /* Create necessary matrix and vectors, solve same ODE on every process */
436: MatCreate(PETSC_COMM_WORLD,&user.A);
437: MatSetSizes(user.A,PETSC_DECIDE,PETSC_DECIDE,2,2);
438: MatSetFromOptions(user.A);
439: MatSetUp(user.A);
440: MatCreateVecs(user.A,&user.U,NULL);
441: MatCreateVecs(user.A,&user.Dir,NULL);
442: MatCreateVecs(user.A,&user.Lambda[0],NULL);
443: MatCreateVecs(user.A,&user.Lambda2[0],NULL);
444: MatCreateVecs(user.A,&user.Ihp1[0],NULL);
446: /* Create timestepping solver context */
447: TSCreate(PETSC_COMM_WORLD,&user.ts);
448: TSSetEquationType(user.ts,TS_EQ_ODE_EXPLICIT); /* less Jacobian evaluations when adjoint BEuler is used, otherwise no effect */
449: if (user.implicitform) {
450: TSSetIFunction(user.ts,NULL,IFunction,&user);
451: TSSetIJacobian(user.ts,user.A,user.A,IJacobian,&user);
452: TSSetType(user.ts,TSCN);
453: } else {
454: TSSetRHSFunction(user.ts,NULL,RHSFunction,&user);
455: TSSetRHSJacobian(user.ts,user.A,user.A,RHSJacobian,&user);
456: TSSetType(user.ts,TSRK);
457: }
458: TSSetMaxTime(user.ts,user.ftime);
459: TSSetExactFinalTime(user.ts,TS_EXACTFINALTIME_MATCHSTEP);
461: if (monitor) {
462: TSMonitorSet(user.ts,Monitor,&user,NULL);
463: }
465: /* Set ODE initial conditions */
466: VecGetArray(user.U,&x_ptr);
467: x_ptr[0] = 2.0;
468: x_ptr[1] = -2.0/3.0 + 10.0/(81.0*user.mu) - 292.0/(2187.0*user.mu*user.mu);
469: VecRestoreArray(user.U,&x_ptr);
471: /* Set runtime options */
472: TSSetFromOptions(user.ts);
474: /* Obtain the observation */
475: TSSolve(user.ts,user.U);
476: VecGetArray(user.U,&x_ptr);
477: user.ob[0] = x_ptr[0];
478: user.ob[1] = x_ptr[1];
479: VecRestoreArray(user.U,&x_ptr);
481: VecDuplicate(user.U,&x);
482: VecGetArray(x,&x_ptr);
483: x_ptr[0] = ic1;
484: x_ptr[1] = ic2;
485: VecRestoreArray(x,&x_ptr);
487: /* Save trajectory of solution so that TSAdjointSolve() may be used */
488: TSSetSaveTrajectory(user.ts);
490: /* Compare finite difference and second-order adjoint. */
491: switch (mode) {
492: case 2 :
493: FiniteDiff(x,arr,&user);
494: PetscPrintf(PETSC_COMM_WORLD,"\n Finite difference approximation of the Hessian\n");
495: PetscPrintf(PETSC_COMM_WORLD,"%g %g\n%g %g\n",(double)arr[0],(double)arr[1],(double)arr[2],(double)arr[3]);
496: break;
497: case 1 : /* Compute the Hessian column by column */
498: VecCopy(x,user.U);
499: VecGetArray(user.Dir,&x_ptr);
500: x_ptr[0] = 1.;
501: x_ptr[1] = 0.;
502: VecRestoreArray(user.Dir,&x_ptr);
503: Adjoint2(user.U,arr,&user);
504: PetscPrintf(PETSC_COMM_WORLD,"\nFirst column of the Hessian\n");
505: PetscPrintf(PETSC_COMM_WORLD,"%g\n%g\n",(double)arr[0],(double)arr[1]);
506: VecCopy(x,user.U);
507: VecGetArray(user.Dir,&x_ptr);
508: x_ptr[0] = 0.;
509: x_ptr[1] = 1.;
510: VecRestoreArray(user.Dir,&x_ptr);
511: Adjoint2(user.U,arr,&user);
512: PetscPrintf(PETSC_COMM_WORLD,"\nSecond column of the Hessian\n");
513: PetscPrintf(PETSC_COMM_WORLD,"%g\n%g\n",(double)arr[0],(double)arr[1]);
514: break;
515: case 0 :
516: /* Create optimization context and set up */
517: TaoCreate(PETSC_COMM_WORLD,&tao);
518: TaoSetType(tao,TAOBLMVM);
519: TaoSetObjectiveAndGradient(tao,NULL,FormFunctionGradient,(void *)&user);
521: if (mf) {
522: MatCreateShell(PETSC_COMM_SELF,2,2,2,2,(void*)&user,&user.H);
523: MatShellSetOperation(user.H,MATOP_MULT,(void(*)(void))HessianProductMat);
524: MatSetOption(user.H,MAT_SYMMETRIC,PETSC_TRUE);
525: TaoSetHessian(tao,user.H,user.H,MatrixFreeHessian,(void *)&user);
526: } else { /* Create Hessian matrix */
527: MatCreate(PETSC_COMM_WORLD,&user.H);
528: MatSetSizes(user.H,PETSC_DECIDE,PETSC_DECIDE,2,2);
529: MatSetUp(user.H);
530: TaoSetHessian(tao,user.H,user.H,FormHessian,(void *)&user);
531: }
533: /* Not use any preconditioner */
534: TaoGetKSP(tao,&ksp);
535: if (ksp) {
536: KSPGetPC(ksp,&pc);
537: PCSetType(pc,PCNONE);
538: }
540: /* Set initial solution guess */
541: TaoSetSolution(tao,x);
542: TaoSetFromOptions(tao);
543: TaoSolve(tao);
544: TaoDestroy(&tao);
545: MatDestroy(&user.H);
546: break;
547: default:
548: break;
549: }
551: /* Free work space. All PETSc objects should be destroyed when they are no longer needed. */
552: MatDestroy(&user.A);
553: VecDestroy(&user.U);
554: VecDestroy(&user.Lambda[0]);
555: VecDestroy(&user.Lambda2[0]);
556: VecDestroy(&user.Ihp1[0]);
557: VecDestroy(&user.Dir);
558: TSDestroy(&user.ts);
559: VecDestroy(&x);
560: PetscFinalize();
561: return 0;
562: }
564: /*TEST
565: build:
566: requires: !complex !single
568: test:
569: args: -ts_type cn -viewer_binary_skip_info -tao_monitor -tao_view -mu 1000 -ts_dt 0.03125
570: output_file: output/ex20opt_ic_1.out
572: test:
573: suffix: 2
574: args: -ts_type beuler -viewer_binary_skip_info -tao_monitor -tao_view -mu 100 -ts_dt 0.01 -tao_type bntr -tao_bnk_pc_type none
575: output_file: output/ex20opt_ic_2.out
577: test:
578: suffix: 3
579: args: -ts_type cn -viewer_binary_skip_info -tao_monitor -tao_view -mu 100 -ts_dt 0.01 -tao_type bntr -tao_bnk_pc_type none
580: output_file: output/ex20opt_ic_3.out
582: test:
583: suffix: 4
584: args: -implicitform 0 -ts_dt 0.01 -ts_max_steps 2 -ts_rhs_jacobian_test_mult_transpose -mat_shell_test_mult_transpose_view -ts_rhs_jacobian_test_mult -mat_shell_test_mult_view -mode 1 -my_tao_mf
585: TEST*/