Actual source code: ex31.c

petsc-3.7.7 2017-09-25
Report Typos and Errors
  1: static char help[] = "Solves the ordinary differential equations (IVPs) using explicit and implicit time-integration methods.\n";

  3: /*

  5:   Concepts:   TS
  6:   Useful command line parameters:
  7:   -problem <hull1972a1>: choose which problem to solve (see references
  8:                       for complete listing of problems).
  9:   -ts_type <euler>: specify time-integrator
 10:   -ts_adapt_type <basic>: specify time-step adapting (none,basic,advanced)
 11:   -refinement_levels <1>: number of refinement levels for convergence analysis
 12:   -refinement_factor <2.0>: factor to refine time step size by for convergence analysis
 13:   -dt <0.01>: specify time step (initial time step for convergence analysis)

 15: */

 17: /*
 18: List of cases and their names in the code:-
 19:   From Hull, T.E., Enright, W.H., Fellen, B.M., and Sedgwick, A.E.,
 20:       "Comparing Numerical Methods for Ordinary Differential
 21:        Equations", SIAM J. Numer. Anal., 9(4), 1972, pp. 603 - 635
 22:     A1 -> "hull1972a1" (exact solution available)
 23:     A2 -> "hull1972a2" (exact solution available)
 24:     A3 -> "hull1972a3" (exact solution available)
 25:     A4 -> "hull1972a4" (exact solution available)
 26:     A5 -> "hull1972a5"
 27:     B1 -> "hull1972b1"
 28:     B2 -> "hull1972b2"
 29:     B3 -> "hull1972b3"
 30:     B4 -> "hull1972b4"
 31:     B5 -> "hull1972b5"
 32:     C1 -> "hull1972c1"
 33:     C2 -> "hull1972c2"
 34:     C3 -> "hull1972c3"
 35:     C4 -> "hull1972c4"
 36: */

 38: #include <petscts.h>
 39: #if defined(PETSC_HAVE_STRING_H)
 40: #include <string.h>             /* strcmp */
 41: #endif

 43: /* Function declarations */
 44: PetscErrorCode (*RHSFunction) (TS,PetscReal,Vec,Vec,void*);
 45: PetscErrorCode (*IFunction)   (TS,PetscReal,Vec,Vec,Vec,void*);
 46: PetscErrorCode (*IJacobian)   (TS,PetscReal,Vec,Vec,PetscReal,Mat,Mat,void*);

 50: /* Returns the size of the system of equations depending on problem specification */
 51: PetscInt GetSize(const char *p)
 52: {
 54:   if      ((!strcmp(p,"hull1972a1"))
 55:          ||(!strcmp(p,"hull1972a2"))
 56:          ||(!strcmp(p,"hull1972a3"))
 57:          ||(!strcmp(p,"hull1972a4"))
 58:          ||(!strcmp(p,"hull1972a5")) )  PetscFunctionReturn(1);
 59:   else if  (!strcmp(p,"hull1972b1")  )  PetscFunctionReturn(2);
 60:   else if ((!strcmp(p,"hull1972b2"))
 61:          ||(!strcmp(p,"hull1972b3"))
 62:          ||(!strcmp(p,"hull1972b4"))
 63:          ||(!strcmp(p,"hull1972b5")) )  PetscFunctionReturn(3);
 64:   else if ((!strcmp(p,"hull1972c1"))
 65:          ||(!strcmp(p,"hull1972c2"))
 66:          ||(!strcmp(p,"hull1972c3")) )  PetscFunctionReturn(10);
 67:   else if  (!strcmp(p,"hull1972c4")  )  PetscFunctionReturn(51);
 68:   else                                  PetscFunctionReturn(-1);
 69: }

 71: /****************************************************************/

 73: /* Problem specific functions */

 75: /* Hull, 1972, Problem A1 */

 79: PetscErrorCode RHSFunction_Hull1972A1(TS ts, PetscReal t, Vec Y, Vec F, void *s)
 80: {
 81:   PetscErrorCode    ierr;
 82:   PetscScalar       *f;
 83:   const PetscScalar *y;

 86:   VecGetArrayRead(Y,&y);
 87:   VecGetArray(F,&f);
 88:   f[0] = -y[0];
 89:   VecRestoreArrayRead(Y,&y);
 90:   VecRestoreArray(F,&f);
 91:   return(0);
 92: }

 96: PetscErrorCode IFunction_Hull1972A1(TS ts, PetscReal t, Vec Y, Vec Ydot, Vec F, void *s)
 97: {
 98:   PetscErrorCode    ierr;
 99:   const PetscScalar *y;
100:   PetscScalar       *f;

103:   VecGetArrayRead(Y,&y);
104:   VecGetArray(F,&f);
105:   f[0] = -y[0];
106:   VecRestoreArrayRead(Y,&y);
107:   VecRestoreArray(F,&f);
108:   /* Left hand side = ydot - f(y) */
109:   VecAYPX(F,-1.0,Ydot);
110:   return(0);
111: }

115: PetscErrorCode IJacobian_Hull1972A1(TS ts, PetscReal t, Vec Y, Vec Ydot, PetscReal a, Mat A, Mat B, void *s)
116: {
117:   PetscErrorCode    ierr;
118:   const PetscScalar *y;
119:   PetscInt          row = 0,col = 0;
120:   PetscScalar       value = a - 1.0;

123:   VecGetArrayRead(Y,&y);
124:   MatSetValues(A,1,&row,1,&col,&value,INSERT_VALUES);
125:   MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
126:   MatAssemblyEnd  (A,MAT_FINAL_ASSEMBLY);
127:   VecRestoreArrayRead(Y,&y);
128:   return(0);
129: }

131: /* Hull, 1972, Problem A2 */

135: PetscErrorCode RHSFunction_Hull1972A2(TS ts, PetscReal t, Vec Y, Vec F, void *s)
136: {
137:   PetscErrorCode    ierr;
138:   const PetscScalar *y;
139:   PetscScalar       *f;

142:   VecGetArrayRead(Y,&y);
143:   VecGetArray(F,&f);
144:   f[0] = -0.5*y[0]*y[0]*y[0];
145:   VecRestoreArrayRead(Y,&y);
146:   VecRestoreArray(F,&f);
147:   return(0);
148: }

152: PetscErrorCode IFunction_Hull1972A2(TS ts, PetscReal t, Vec Y, Vec Ydot, Vec F, void *s)
153: {
154:   PetscErrorCode    ierr;
155:   PetscScalar       *f;
156:   const PetscScalar *y;

159:   VecGetArrayRead(Y,&y);
160:   VecGetArray(F,&f);
161:   f[0] = -0.5*y[0]*y[0]*y[0];
162:   VecRestoreArrayRead(Y,&y);
163:   VecRestoreArray(F,&f);
164:   /* Left hand side = ydot - f(y) */
165:   VecAYPX(F,-1.0,Ydot);
166:   return(0);
167: }

171: PetscErrorCode IJacobian_Hull1972A2(TS ts, PetscReal t, Vec Y, Vec Ydot, PetscReal a, Mat A, Mat B, void *s)
172: {
173:   PetscErrorCode    ierr;
174:   const PetscScalar *y;
175:   PetscInt          row = 0,col = 0;
176:   PetscScalar       value;

179:   VecGetArrayRead(Y,&y);
180:   value = a + 0.5*3.0*y[0]*y[0];
181:   MatSetValues(A,1,&row,1,&col,&value,INSERT_VALUES);
182:   MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
183:   MatAssemblyEnd  (A,MAT_FINAL_ASSEMBLY);
184:   VecRestoreArrayRead(Y,&y);
185:   return(0);
186: }

188: /* Hull, 1972, Problem A3 */

192: PetscErrorCode RHSFunction_Hull1972A3(TS ts, PetscReal t, Vec Y, Vec F, void *s)
193: {
194:   PetscErrorCode    ierr;
195:   const PetscScalar *y;
196:   PetscScalar       *f;

199:   VecGetArrayRead(Y,&y);
200:   VecGetArray(F,&f);
201:   f[0] = y[0]*PetscCosReal(t);
202:   VecRestoreArrayRead(Y,&y);
203:   VecRestoreArray(F,&f);
204:   return(0);
205: }

209: PetscErrorCode IFunction_Hull1972A3(TS ts, PetscReal t, Vec Y, Vec Ydot, Vec F, void *s)
210: {
211:   PetscErrorCode    ierr;
212:   PetscScalar       *f;
213:   const PetscScalar *y;

216:   VecGetArrayRead(Y,&y);
217:   VecGetArray(F,&f);
218:   f[0] = y[0]*PetscCosReal(t);
219:   VecRestoreArrayRead(Y,&y);
220:   VecRestoreArray(F,&f);
221:   /* Left hand side = ydot - f(y) */
222:   VecAYPX(F,-1.0,Ydot);
223:   return(0);
224: }

228: PetscErrorCode IJacobian_Hull1972A3(TS ts, PetscReal t, Vec Y, Vec Ydot, PetscReal a, Mat A, Mat B, void *s)
229: {
230:   PetscErrorCode    ierr;
231:   const PetscScalar *y;
232:   PetscInt          row = 0,col = 0;
233:   PetscScalar       value = a - PetscCosReal(t);

236:   VecGetArrayRead(Y,&y);
237:   MatSetValues(A,1,&row,1,&col,&value,INSERT_VALUES);
238:   MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
239:   MatAssemblyEnd  (A,MAT_FINAL_ASSEMBLY);
240:   VecRestoreArrayRead(Y,&y);
241:   return(0);
242: }

244: /* Hull, 1972, Problem A4 */

248: PetscErrorCode RHSFunction_Hull1972A4(TS ts, PetscReal t, Vec Y, Vec F, void *s)
249: {
250:   PetscErrorCode    ierr;
251:   PetscScalar       *f;
252:   const PetscScalar *y;

255:   VecGetArrayRead(Y,&y);
256:   VecGetArray(F,&f);
257:   f[0] = (0.25*y[0])*(1.0-0.05*y[0]);
258:   VecRestoreArrayRead(Y,&y);
259:   VecRestoreArray(F,&f);
260:   return(0);
261: }

265: PetscErrorCode IFunction_Hull1972A4(TS ts, PetscReal t, Vec Y, Vec Ydot, Vec F, void *s)
266: {
267:   PetscErrorCode    ierr;
268:   PetscScalar       *f;
269:   const PetscScalar *y;

272:   VecGetArrayRead(Y,&y);
273:   VecGetArray(F,&f);
274:   f[0] = (0.25*y[0])*(1.0-0.05*y[0]);
275:   VecRestoreArrayRead(Y,&y);
276:   VecRestoreArray(F,&f);
277:   /* Left hand side = ydot - f(y) */
278:   VecAYPX(F,-1.0,Ydot);
279:   return(0);
280: }

284: PetscErrorCode IJacobian_Hull1972A4(TS ts, PetscReal t, Vec Y, Vec Ydot, PetscReal a, Mat A, Mat B, void *s)
285: {
286:   PetscErrorCode    ierr;
287:   const PetscScalar *y;
288:   PetscInt          row = 0,col = 0;
289:   PetscScalar       value;

292:   VecGetArrayRead(Y,&y);
293:   value = a - 0.25*(1.0-0.05*y[0]) + (0.25*y[0])*0.05;
294:   MatSetValues(A,1,&row,1,&col,&value,INSERT_VALUES);
295:   MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
296:   MatAssemblyEnd  (A,MAT_FINAL_ASSEMBLY);
297:   VecRestoreArrayRead(Y,&y);
298:   return(0);
299: }

301: /* Hull, 1972, Problem A5 */

305: PetscErrorCode RHSFunction_Hull1972A5(TS ts, PetscReal t, Vec Y, Vec F, void *s)
306: {
307:   PetscErrorCode    ierr;
308:   PetscScalar       *f;
309:   const PetscScalar *y;

312:   VecGetArrayRead(Y,&y);
313:   VecGetArray(F,&f);
314:   f[0] = (y[0]-t)/(y[0]+t);
315:   VecRestoreArrayRead(Y,&y);
316:   VecRestoreArray(F,&f);
317:   return(0);
318: }

322: PetscErrorCode IFunction_Hull1972A5(TS ts, PetscReal t, Vec Y, Vec Ydot, Vec F, void *s)
323: {
324:   PetscErrorCode    ierr;
325:   PetscScalar       *f;
326:   const PetscScalar *y;

329:   VecGetArrayRead(Y,&y);
330:   VecGetArray(F,&f);
331:   f[0] = (y[0]-t)/(y[0]+t);
332:   VecRestoreArrayRead(Y,&y);
333:   VecRestoreArray(F,&f);
334:   /* Left hand side = ydot - f(y) */
335:   VecAYPX(F,-1.0,Ydot);
336:   return(0);
337: }

341: PetscErrorCode IJacobian_Hull1972A5(TS ts, PetscReal t, Vec Y, Vec Ydot, PetscReal a, Mat A, Mat B, void *s)
342: {
343:   PetscErrorCode    ierr;
344:   const PetscScalar *y;
345:   PetscInt          row = 0,col = 0;
346:   PetscScalar       value;

349:   VecGetArrayRead(Y,&y);
350:   value = a - 2*t/((t+y[0])*(t+y[0]));
351:   MatSetValues(A,1,&row,1,&col,&value,INSERT_VALUES);
352:   MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
353:   MatAssemblyEnd  (A,MAT_FINAL_ASSEMBLY);
354:   VecRestoreArrayRead(Y,&y);
355:   return(0);
356: }

358: /* Hull, 1972, Problem B1 */

362: PetscErrorCode RHSFunction_Hull1972B1(TS ts, PetscReal t, Vec Y, Vec F, void *s)
363: {
364:   PetscErrorCode    ierr;
365:   PetscScalar       *f;
366:   const PetscScalar *y;

369:   VecGetArrayRead(Y,&y);
370:   VecGetArray(F,&f);
371:   f[0] = 2.0*(y[0] - y[0]*y[1]);
372:   f[1] = -(y[1]-y[0]*y[1]);
373:   VecRestoreArrayRead(Y,&y);
374:   VecRestoreArray(F,&f);
375:   return(0);
376: }

380: PetscErrorCode IFunction_Hull1972B1(TS ts, PetscReal t, Vec Y, Vec Ydot, Vec F, void *s)
381: {
382:   PetscErrorCode    ierr;
383:   PetscScalar       *f;
384:   const PetscScalar *y;

387:   VecGetArrayRead(Y,&y);
388:   VecGetArray(F,&f);
389:   f[0] = 2.0*(y[0] - y[0]*y[1]);
390:   f[1] = -(y[1]-y[0]*y[1]);
391:   VecRestoreArrayRead(Y,&y);
392:   VecRestoreArray(F,&f);
393:   /* Left hand side = ydot - f(y) */
394:   VecAYPX(F,-1.0,Ydot);
395:   return(0);
396: }

400: PetscErrorCode IJacobian_Hull1972B1(TS ts, PetscReal t, Vec Y, Vec Ydot, PetscReal a, Mat A, Mat B, void *s)
401: {
402:   PetscErrorCode    ierr;
403:   const PetscScalar *y;
404:   PetscInt          row[2] = {0,1};
405:   PetscScalar       value[2][2];

408:   VecGetArrayRead(Y,&y);
409:   value[0][0] = a - 2.0*(1.0-y[1]);    value[0][1] = 2.0*y[0];
410:   value[1][0] = -y[1];                 value[1][1] = a + 1.0 - y[0];
411:   MatSetValues(A,2,&row[0],2,&row[0],&value[0][0],INSERT_VALUES);
412:   MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
413:   MatAssemblyEnd  (A,MAT_FINAL_ASSEMBLY);
414:   VecRestoreArrayRead(Y,&y);
415:   return(0);
416: }

418: /* Hull, 1972, Problem B2 */

422: PetscErrorCode RHSFunction_Hull1972B2(TS ts, PetscReal t, Vec Y, Vec F, void *s)
423: {
424:   PetscErrorCode    ierr;
425:   PetscScalar       *f;
426:   const PetscScalar *y;

429:   VecGetArrayRead(Y,&y);
430:   VecGetArray(F,&f);
431:   f[0] = -y[0] + y[1];
432:   f[1] = y[0] - 2.0*y[1] + y[2];
433:   f[2] = y[1] - y[2];
434:   VecRestoreArrayRead(Y,&y);
435:   VecRestoreArray(F,&f);
436:   return(0);
437: }

441: PetscErrorCode IFunction_Hull1972B2(TS ts, PetscReal t, Vec Y, Vec Ydot, Vec F, void *s)
442: {
443:   PetscErrorCode    ierr;
444:   PetscScalar       *f;
445:   const PetscScalar *y;

448:   VecGetArrayRead(Y,&y);
449:   VecGetArray(F,&f);
450:   f[0] = -y[0] + y[1];
451:   f[1] = y[0] - 2.0*y[1] + y[2];
452:   f[2] = y[1] - y[2];
453:   VecRestoreArrayRead(Y,&y);
454:   VecRestoreArray(F,&f);
455:   /* Left hand side = ydot - f(y) */
456:   VecAYPX(F,-1.0,Ydot);
457:   return(0);
458: }

462: PetscErrorCode IJacobian_Hull1972B2(TS ts, PetscReal t, Vec Y, Vec Ydot, PetscReal a, Mat A, Mat B, void *s)
463: {
464:   PetscErrorCode    ierr;
465:   const PetscScalar *y;
466:   PetscInt          row[3] = {0,1,2};
467:   PetscScalar       value[3][3];

470:   VecGetArrayRead(Y,&y);
471:   value[0][0] = a + 1.0;  value[0][1] = -1.0;     value[0][2] = 0;
472:   value[1][0] = -1.0;     value[1][1] = a + 2.0;  value[1][2] = -1.0;
473:   value[2][0] = 0;        value[2][1] = -1.0;     value[2][2] = a + 1.0;
474:   MatSetValues(A,3,&row[0],3,&row[0],&value[0][0],INSERT_VALUES);
475:   MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
476:   MatAssemblyEnd  (A,MAT_FINAL_ASSEMBLY);
477:   VecRestoreArrayRead(Y,&y);
478:   return(0);
479: }

481: /* Hull, 1972, Problem B3 */

485: PetscErrorCode RHSFunction_Hull1972B3(TS ts, PetscReal t, Vec Y, Vec F, void *s)
486: {
487:   PetscErrorCode    ierr;
488:   PetscScalar       *f;
489:   const PetscScalar *y;

492:   VecGetArrayRead(Y,&y);
493:   VecGetArray(F,&f);
494:   f[0] = -y[0];
495:   f[1] = y[0] - y[1]*y[1];
496:   f[2] = y[1]*y[1];
497:   VecRestoreArrayRead(Y,&y);
498:   VecRestoreArray(F,&f);
499:   return(0);
500: }

504: PetscErrorCode IFunction_Hull1972B3(TS ts, PetscReal t, Vec Y, Vec Ydot, Vec F, void *s)
505: {
506:   PetscErrorCode    ierr;
507:   PetscScalar       *f;
508:   const PetscScalar *y;

511:   VecGetArrayRead(Y,&y);
512:   VecGetArray(F,&f);
513:   f[0] = -y[0];
514:   f[1] = y[0] - y[1]*y[1];
515:   f[2] = y[1]*y[1];
516:   VecRestoreArrayRead(Y,&y);
517:   VecRestoreArray(F,&f);
518:   /* Left hand side = ydot - f(y) */
519:   VecAYPX(F,-1.0,Ydot);
520:   return(0);
521: }

525: PetscErrorCode IJacobian_Hull1972B3(TS ts, PetscReal t, Vec Y, Vec Ydot, PetscReal a, Mat A, Mat B, void *s)
526: {
527:   PetscErrorCode    ierr;
528:   const PetscScalar *y;
529:   PetscInt          row[3] = {0,1,2};
530:   PetscScalar       value[3][3];

533:   VecGetArrayRead(Y,&y);
534:   value[0][0] = a + 1.0; value[0][1] = 0;             value[0][2] = 0;
535:   value[1][0] = -1.0;    value[1][1] = a + 2.0*y[1];  value[1][2] = 0;
536:   value[2][0] = 0;       value[2][1] = -2.0*y[1];     value[2][2] = a;
537:   MatSetValues(A,3,&row[0],3,&row[0],&value[0][0],INSERT_VALUES);
538:   MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
539:   MatAssemblyEnd  (A,MAT_FINAL_ASSEMBLY);
540:   VecRestoreArrayRead(Y,&y);
541:   return(0);
542: }

544: /* Hull, 1972, Problem B4 */

548: PetscErrorCode RHSFunction_Hull1972B4(TS ts, PetscReal t, Vec Y, Vec F, void *s)
549: {
550:   PetscErrorCode    ierr;
551:   PetscScalar       *f;
552:   const PetscScalar *y;

555:   VecGetArrayRead(Y,&y);
556:   VecGetArray(F,&f);
557:   f[0] = -y[1] - y[0]*y[2]/PetscSqrtScalar(y[0]*y[0]+y[1]*y[1]);
558:   f[1] =  y[0] - y[1]*y[2]/PetscSqrtScalar(y[0]*y[0]+y[1]*y[1]);
559:   f[2] = y[0]/PetscSqrtScalar(y[0]*y[0]+y[1]*y[1]);
560:   VecRestoreArrayRead(Y,&y);
561:   VecRestoreArray(F,&f);
562:   return(0);
563: }

567: PetscErrorCode IFunction_Hull1972B4(TS ts, PetscReal t, Vec Y, Vec Ydot, Vec F, void *s)
568: {
569:   PetscErrorCode    ierr;
570:   PetscScalar       *f;
571:   const PetscScalar *y;

574:   VecGetArrayRead(Y,&y);
575:   VecGetArray(F,&f);
576:   f[0] = -y[1] - y[0]*y[2]/PetscSqrtScalar(y[0]*y[0]+y[1]*y[1]);
577:   f[1] =  y[0] - y[1]*y[2]/PetscSqrtScalar(y[0]*y[0]+y[1]*y[1]);
578:   f[2] = y[0]/PetscSqrtScalar(y[0]*y[0]+y[1]*y[1]);
579:   VecRestoreArrayRead(Y,&y);
580:   VecRestoreArray(F,&f);
581:   /* Left hand side = ydot - f(y) */
582:   VecAYPX(F,-1.0,Ydot);
583:   return(0);
584: }

588: PetscErrorCode IJacobian_Hull1972B4(TS ts, PetscReal t, Vec Y, Vec Ydot, PetscReal a, Mat A, Mat B, void *s)
589: {
590:   PetscErrorCode    ierr;
591:   const PetscScalar *y;
592:   PetscInt          row[3] = {0,1,2};
593:   PetscScalar       value[3][3],fac,fac2;

596:   VecGetArrayRead(Y,&y);
597:   fac  = PetscPowScalar(y[0]*y[0]+y[1]*y[1],-1.5);
598:   fac2 = PetscPowScalar(y[0]*y[0]+y[1]*y[1],-0.5);
599:   value[0][0] = a + (y[1]*y[1]*y[2])*fac;
600:   value[0][1] = 1.0 - (y[0]*y[1]*y[2])*fac;
601:   value[0][2] = y[0]*fac2;
602:   value[1][0] = -1.0 - y[0]*y[1]*y[2]*fac;
603:   value[1][1] = a + y[0]*y[0]*y[2]*fac;
604:   value[1][2] = y[1]*fac2;
605:   value[2][0] = -y[1]*y[1]*fac;
606:   value[2][1] = y[0]*y[1]*fac;
607:   value[2][2] = a;
608:   MatSetValues(A,3,&row[0],3,&row[0],&value[0][0],INSERT_VALUES);
609:   MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
610:   MatAssemblyEnd  (A,MAT_FINAL_ASSEMBLY);
611:   VecRestoreArrayRead(Y,&y);
612:   return(0);
613: }

615: /* Hull, 1972, Problem B5 */

619: PetscErrorCode RHSFunction_Hull1972B5(TS ts, PetscReal t, Vec Y, Vec F, void *s)
620: {
621:   PetscErrorCode    ierr;
622:   PetscScalar       *f;
623:   const PetscScalar *y;

626:   VecGetArrayRead(Y,&y);
627:   VecGetArray(F,&f);
628:   f[0] = y[1]*y[2];
629:   f[1] = -y[0]*y[2];
630:   f[2] = -0.51*y[0]*y[1];
631:   VecRestoreArrayRead(Y,&y);
632:   VecRestoreArray(F,&f);
633:   return(0);
634: }

638: PetscErrorCode IFunction_Hull1972B5(TS ts, PetscReal t, Vec Y, Vec Ydot, Vec F, void *s)
639: {
640:   PetscErrorCode    ierr;
641:   PetscScalar       *f;
642:   const PetscScalar *y;

645:   VecGetArrayRead(Y,&y);
646:   VecGetArray(F,&f);
647:   f[0] = y[1]*y[2];
648:   f[1] = -y[0]*y[2];
649:   f[2] = -0.51*y[0]*y[1];
650:   VecRestoreArrayRead(Y,&y);
651:   VecRestoreArray(F,&f);
652:   /* Left hand side = ydot - f(y) */
653:   VecAYPX(F,-1.0,Ydot);
654:   return(0);
655: }

659: PetscErrorCode IJacobian_Hull1972B5(TS ts, PetscReal t, Vec Y, Vec Ydot, PetscReal a, Mat A, Mat B, void *s)
660: {
661:   PetscErrorCode    ierr;
662:   const PetscScalar *y;
663:   PetscInt          row[3] = {0,1,2};
664:   PetscScalar       value[3][3];

667:   VecGetArrayRead(Y,&y);
668:   value[0][0] = a;          value[0][1] = -y[2];      value[0][2] = -y[1];
669:   value[1][0] = y[2];       value[1][1] = a;          value[1][2] = y[0];
670:   value[2][0] = 0.51*y[1];  value[2][1] = 0.51*y[0];  value[2][2] = a;
671:   MatSetValues(A,3,&row[0],3,&row[0],&value[0][0],INSERT_VALUES);
672:   MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
673:   MatAssemblyEnd  (A,MAT_FINAL_ASSEMBLY);
674:   VecRestoreArrayRead(Y,&y);
675:   return(0);
676: }

678: /* Hull, 1972, Problem C1 */

682: PetscErrorCode RHSFunction_Hull1972C1(TS ts, PetscReal t, Vec Y, Vec F, void *s)
683: {
684:   PetscErrorCode    ierr;
685:   PetscScalar       *f;
686:   const PetscScalar *y;
687:   PetscInt          N,i;

690:   VecGetSize (Y,&N);
691:   VecGetArrayRead(Y,&y);
692:   VecGetArray(F,&f);
693:   f[0] = -y[0];
694:   for (i = 1; i < N-1; i++) {
695:     f[i] = y[i-1] - y[i];
696:   }
697:   f[N-1] = y[N-2];
698:   VecRestoreArrayRead(Y,&y);
699:   VecRestoreArray(F,&f);
700:   return(0);
701: }

705: PetscErrorCode IFunction_Hull1972C1(TS ts, PetscReal t, Vec Y, Vec Ydot, Vec F, void *s)
706: {
707:   PetscErrorCode    ierr;
708:   PetscScalar       *f;
709:   const PetscScalar *y;
710:   PetscInt          N,i;

713:   VecGetSize (Y,&N);
714:   VecGetArrayRead(Y,&y);
715:   VecGetArray(F,&f);
716:   f[0] = -y[0];
717:   for (i = 1; i < N-1; i++) {
718:     f[i] = y[i-1] - y[i];
719:   }
720:   f[N-1] = y[N-2];
721:   VecRestoreArrayRead(Y,&y);
722:   VecRestoreArray(F,&f);
723:   /* Left hand side = ydot - f(y) */
724:   VecAYPX(F,-1.0,Ydot);
725:   return(0);
726: }

730: PetscErrorCode IJacobian_Hull1972C1(TS ts, PetscReal t, Vec Y, Vec Ydot, PetscReal a, Mat A, Mat B, void *s)
731: {
732:   PetscErrorCode    ierr;
733:   const PetscScalar *y;
734:   PetscInt          N,i,col[2];
735:   PetscScalar       value[2];

738:   VecGetSize (Y,&N);
739:   VecGetArrayRead(Y,&y);
740:   i = 0;
741:   value[0] = a+1; col[0] = 0;
742:   value[1] =  0;  col[1] = 1;
743:   MatSetValues(A,1,&i,2,col,value,INSERT_VALUES);
744:   for (i = 0; i < N; i++) {
745:     value[0] =  -1; col[0] = i-1;
746:     value[1] = a+1; col[1] = i;
747:     MatSetValues(A,1,&i,2,col,value,INSERT_VALUES);
748:   }
749:   i = N-1;
750:   value[0] = -1;  col[0] = N-2;
751:   value[1] = a;   col[1] = N-1;
752:   MatSetValues(A,1,&i,2,col,value,INSERT_VALUES);
753:   MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
754:   MatAssemblyEnd  (A,MAT_FINAL_ASSEMBLY);
755:   VecRestoreArrayRead(Y,&y);
756:   return(0);
757: }

759: /* Hull, 1972, Problem C2 */

763: PetscErrorCode RHSFunction_Hull1972C2(TS ts, PetscReal t, Vec Y, Vec F, void *s)
764: {
765:   PetscErrorCode    ierr;
766:   const PetscScalar *y;
767:   PetscScalar       *f;
768:   PetscInt          N,i;

771:   VecGetSize (Y,&N);
772:   VecGetArrayRead(Y,&y);
773:   VecGetArray(F,&f);
774:   f[0] = -y[0];
775:   for (i = 1; i < N-1; i++) {
776:     f[i] = (PetscReal)i*y[i-1] - (PetscReal)(i+1)*y[i];
777:   }
778:   f[N-1] = (PetscReal)(N-1)*y[N-2];
779:   VecRestoreArrayRead(Y,&y);
780:   VecRestoreArray(F,&f);
781:   return(0);
782: }

786: PetscErrorCode IFunction_Hull1972C2(TS ts, PetscReal t, Vec Y, Vec Ydot, Vec F, void *s)
787: {
788:   PetscErrorCode    ierr;
789:   PetscScalar       *f;
790:   const PetscScalar *y;
791:   PetscInt          N,i;

794:   VecGetSize (Y,&N);
795:   VecGetArrayRead(Y,&y);
796:   VecGetArray(F,&f);
797:   f[0] = -y[0];
798:   for (i = 1; i < N-1; i++) {
799:     f[i] = (PetscReal)i*y[i-1] - (PetscReal)(i+1)*y[i];
800:   }
801:   f[N-1] = (PetscReal)(N-1)*y[N-2];
802:   VecRestoreArrayRead(Y,&y);
803:   VecRestoreArray(F,&f);
804:   /* Left hand side = ydot - f(y) */
805:   VecAYPX(F,-1.0,Ydot);
806:   return(0);
807: }

811: PetscErrorCode IJacobian_Hull1972C2(TS ts, PetscReal t, Vec Y, Vec Ydot, PetscReal a, Mat A, Mat B, void *s)
812: {
813:   PetscErrorCode    ierr;
814:   const PetscScalar *y;
815:   PetscInt          N,i,col[2];
816:   PetscScalar       value[2];

819:   VecGetSize (Y,&N);
820:   VecGetArrayRead(Y,&y);
821:   i = 0;
822:   value[0] = a+1;                 col[0] = 0;
823:   value[1] = 0;                   col[1] = 1;
824:   MatSetValues(A,1,&i,2,col,value,INSERT_VALUES);
825:   for (i = 0; i < N; i++) {
826:     value[0] = -(PetscReal) i;      col[0] = i-1;
827:     value[1] = a+(PetscReal)(i+1);  col[1] = i;
828:     MatSetValues(A,1,&i,2,col,value,INSERT_VALUES);
829:   }
830:   i = N-1;
831:   value[0] = -(PetscReal) (N-1);  col[0] = N-2;
832:   value[1] = a;                   col[1] = N-1;
833:   MatSetValues(A,1,&i,2,col,value,INSERT_VALUES);
834:   MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
835:   MatAssemblyEnd  (A,MAT_FINAL_ASSEMBLY);
836:   VecRestoreArrayRead(Y,&y);
837:   return(0);
838: }

840: /* Hull, 1972, Problem C3 and C4 */

844: PetscErrorCode RHSFunction_Hull1972C34(TS ts, PetscReal t, Vec Y, Vec F, void *s)
845: {
846:   PetscErrorCode    ierr;
847:   PetscScalar       *f;
848:   const PetscScalar *y;
849:   PetscInt          N,i;

852:   VecGetSize (Y,&N);
853:   VecGetArrayRead(Y,&y);
854:   VecGetArray(F,&f);
855:   f[0] = -2.0*y[0] + y[1];
856:   for (i = 1; i < N-1; i++) {
857:     f[i] = y[i-1] - 2.0*y[i] + y[i+1];
858:   }
859:   f[N-1] = y[N-2] - 2.0*y[N-1];
860:   VecRestoreArrayRead(Y,&y);
861:   VecRestoreArray(F,&f);
862:   return(0);
863: }

867: PetscErrorCode IFunction_Hull1972C34(TS ts, PetscReal t, Vec Y, Vec Ydot, Vec F, void *s)
868: {
869:   PetscErrorCode    ierr;
870:   PetscScalar       *f;
871:   const PetscScalar *y;
872:   PetscInt          N,i;

875:   VecGetSize (Y,&N);
876:   VecGetArrayRead(Y,&y);
877:   VecGetArray(F,&f);
878:   f[0] = -2.0*y[0] + y[1];
879:   for (i = 1; i < N-1; i++) {
880:     f[i] = y[i-1] - 2.0*y[i] + y[i+1];
881:   }
882:   f[N-1] = y[N-2] - 2.0*y[N-1];
883:   VecRestoreArrayRead(Y,&y);
884:   VecRestoreArray(F,&f);
885:   /* Left hand side = ydot - f(y) */
886:   VecAYPX(F,-1.0,Ydot);
887:   return(0);
888: }

892: PetscErrorCode IJacobian_Hull1972C34(TS ts, PetscReal t, Vec Y, Vec Ydot, PetscReal a, Mat A, Mat B, void *s)
893: {
894:   PetscErrorCode    ierr;
895:   const PetscScalar *y;
896:   PetscScalar       value[3];
897:   PetscInt          N,i,col[3];

900:   VecGetSize (Y,&N);
901:   VecGetArrayRead(Y,&y);
902:   for (i = 0; i < N; i++) {
903:     if (i == 0) {
904:       value[0] = a+2;  col[0] = i;
905:       value[1] =  -1;  col[1] = i+1;
906:       value[2] =  0;   col[2] = i+2;
907:     } else if (i == N-1) {
908:       value[0] =  0;   col[0] = i-2;
909:       value[1] =  -1;  col[1] = i-1;
910:       value[2] = a+2;  col[2] = i;
911:     } else {
912:       value[0] = -1;   col[0] = i-1;
913:       value[1] = a+2;  col[1] = i;
914:       value[2] = -1;   col[2] = i+1;
915:     }
916:     MatSetValues(A,1,&i,3,col,value,INSERT_VALUES);
917:   }
918:   MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);
919:   MatAssemblyEnd  (A,MAT_FINAL_ASSEMBLY);
920:   VecRestoreArrayRead(Y,&y);
921:   return(0);
922: }

924: /***************************************************************************/

928: /* Sets the initial solution for the IVP and sets up the function pointers*/
929: PetscErrorCode Initialize(Vec Y, void* s)
930: {
932:   char          *p = (char*) s;
933:   PetscScalar   *y;
934:   PetscInt      N = GetSize((const char *)s);
935:   PetscBool     flg;

938:   VecZeroEntries(Y);
939:   VecGetArray(Y,&y);
940:   if (!strcmp(p,"hull1972a1")) {
941:     y[0] = 1.0;
942:     RHSFunction = RHSFunction_Hull1972A1;
943:     IFunction   = IFunction_Hull1972A1;
944:     IJacobian   = IJacobian_Hull1972A1;
945:   } else if (!strcmp(p,"hull1972a2")) {
946:     y[0] = 1.0;
947:     RHSFunction = RHSFunction_Hull1972A2;
948:     IFunction   = IFunction_Hull1972A2;
949:     IJacobian   = IJacobian_Hull1972A2;
950:   } else if (!strcmp(p,"hull1972a3")) {
951:     y[0] = 1.0;
952:     RHSFunction = RHSFunction_Hull1972A3;
953:     IFunction   = IFunction_Hull1972A3;
954:     IJacobian   = IJacobian_Hull1972A3;
955:   } else if (!strcmp(p,"hull1972a4")) {
956:     y[0] = 1.0;
957:     RHSFunction = RHSFunction_Hull1972A4;
958:     IFunction   = IFunction_Hull1972A4;
959:     IJacobian   = IJacobian_Hull1972A4;
960:   } else if (!strcmp(p,"hull1972a5")) {
961:     y[0] = 4.0;
962:     RHSFunction = RHSFunction_Hull1972A5;
963:     IFunction   = IFunction_Hull1972A5;
964:     IJacobian   = IJacobian_Hull1972A5;
965:   } else if (!strcmp(p,"hull1972b1")) {
966:     y[0] = 1.0;
967:     y[1] = 3.0;
968:     RHSFunction = RHSFunction_Hull1972B1;
969:     IFunction   = IFunction_Hull1972B1;
970:     IJacobian   = IJacobian_Hull1972B1;
971:   } else if (!strcmp(p,"hull1972b2")) {
972:     y[0] = 2.0;
973:     y[1] = 0.0;
974:     y[2] = 1.0;
975:     RHSFunction = RHSFunction_Hull1972B2;
976:     IFunction   = IFunction_Hull1972B2;
977:     IJacobian   = IJacobian_Hull1972B2;
978:   } else if (!strcmp(p,"hull1972b3")) {
979:     y[0] = 1.0;
980:     y[1] = 0.0;
981:     y[2] = 0.0;
982:     RHSFunction = RHSFunction_Hull1972B3;
983:     IFunction   = IFunction_Hull1972B3;
984:     IJacobian   = IJacobian_Hull1972B3;
985:   } else if (!strcmp(p,"hull1972b4")) {
986:     y[0] = 3.0;
987:     y[1] = 0.0;
988:     y[2] = 0.0;
989:     RHSFunction = RHSFunction_Hull1972B4;
990:     IFunction   = IFunction_Hull1972B4;
991:     IJacobian   = IJacobian_Hull1972B4;
992:   } else if (!strcmp(p,"hull1972b5")) {
993:     y[0] = 0.0;
994:     y[1] = 1.0;
995:     y[2] = 1.0;
996:     RHSFunction = RHSFunction_Hull1972B5;
997:     IFunction   = IFunction_Hull1972B5;
998:     IJacobian   = IJacobian_Hull1972B5;
999:   } else if (!strcmp(p,"hull1972c1")) {
1000:     y[0] = 1.0;
1001:     RHSFunction = RHSFunction_Hull1972C1;
1002:     IFunction   = IFunction_Hull1972C1;
1003:     IJacobian   = IJacobian_Hull1972C1;
1004:   } else if (!strcmp(p,"hull1972c2")) {
1005:     y[0] = 1.0;
1006:     RHSFunction = RHSFunction_Hull1972C2;
1007:     IFunction   = IFunction_Hull1972C2;
1008:     IJacobian   = IJacobian_Hull1972C2;
1009:   } else if ((!strcmp(p,"hull1972c3"))
1010:            ||(!strcmp(p,"hull1972c4"))){
1011:     y[0] = 1.0;
1012:     RHSFunction = RHSFunction_Hull1972C34;
1013:     IFunction   = IFunction_Hull1972C34;
1014:     IJacobian   = IJacobian_Hull1972C34;
1015:   }
1016:   PetscOptionsGetScalarArray(NULL,NULL,"-yinit",y,&N,&flg);
1017:   if ((N != GetSize((const char*)s)) && flg) SETERRQ2(PETSC_COMM_WORLD,PETSC_ERR_ARG_SIZ,"Number of initial values %D does not match problem size %D.\n",N,GetSize((const char*)s));
1018:   VecRestoreArray(Y,&y);
1019:   return(0);
1020: }

1024: /* Calculates the exact solution to problems that have one */
1025: PetscErrorCode ExactSolution(Vec Y, void* s, PetscReal t, PetscBool *flag)
1026: {
1028:   char          *p = (char*) s;
1029:   PetscScalar   *y;

1032:   if (!strcmp(p,"hull1972a1")) {
1033:     VecGetArray(Y,&y);
1034:     y[0] = PetscExpReal(-t);
1035:     *flag = PETSC_TRUE;
1036:     VecRestoreArray(Y,&y);
1037:   } else if (!strcmp(p,"hull1972a2")) {
1038:     VecGetArray(Y,&y);
1039:     y[0] = 1.0/PetscSqrtReal(t+1);
1040:     *flag = PETSC_TRUE;
1041:     VecRestoreArray(Y,&y);
1042:   } else if (!strcmp(p,"hull1972a3")) {
1043:     VecGetArray(Y,&y);
1044:     y[0] = PetscExpReal(PetscSinReal(t));
1045:     *flag = PETSC_TRUE;
1046:     VecRestoreArray(Y,&y);
1047:   } else if (!strcmp(p,"hull1972a4")) {
1048:     VecGetArray(Y,&y);
1049:     y[0] = 20.0/(1+19.0*PetscExpReal(-t/4.0));
1050:     *flag = PETSC_TRUE;
1051:     VecRestoreArray(Y,&y);
1052:   } else {
1053:     VecSet(Y,0);
1054:     *flag = PETSC_FALSE;
1055:   }
1056:   return(0);
1057: }

1061: /* Solves the specified ODE and computes the error if exact solution is available */
1062: PetscErrorCode SolveODE(char* ptype, PetscReal dt, PetscReal tfinal, PetscInt maxiter, PetscReal *error, PetscBool *exact_flag)
1063: {
1064:   PetscErrorCode  ierr;             /* Error code                             */
1065:   TS              ts;               /* time-integrator                        */
1066:   Vec             Y;                /* Solution vector                        */
1067:   Vec             Yex;              /* Exact solution                         */
1068:   PetscInt        N;                /* Size of the system of equations        */
1069:   TSType          time_scheme;      /* Type of time-integration scheme        */
1070:   Mat             Jac = NULL;       /* Jacobian matrix                        */

1073:   N = GetSize((const char *)&ptype[0]);
1074:   if (N < 0) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_ARG_SIZ,"Illegal problem specification.\n");
1075:   VecCreate(PETSC_COMM_WORLD,&Y);
1076:   VecSetSizes(Y,N,PETSC_DECIDE);
1077:   VecSetUp(Y);
1078:   VecSet(Y,0);

1080:   /* Initialize the problem */
1081:   Initialize(Y,&ptype[0]);

1083:   /* Create and initialize the time-integrator                            */
1084:   TSCreate(PETSC_COMM_WORLD,&ts);
1085:   /* Default time integration options                                     */
1086:   TSSetType(ts,TSRK);
1087:   TSSetDuration(ts,maxiter,tfinal);
1088:   TSSetInitialTimeStep(ts,0.0,dt);
1089:   TSSetExactFinalTime(ts,TS_EXACTFINALTIME_MATCHSTEP);
1090:   /* Read command line options for time integration                       */
1091:   TSSetFromOptions(ts);
1092:   /* Set solution vector                                                  */
1093:   TSSetSolution(ts,Y);
1094:   /* Specify left/right-hand side functions                               */
1095:   TSGetType(ts,&time_scheme);
1096:   if ((!strcmp(time_scheme,TSEULER)) || (!strcmp(time_scheme,TSRK)) || (!strcmp(time_scheme,TSSSP))) {
1097:     /* Explicit time-integration -> specify right-hand side function ydot = f(y) */
1098:     TSSetRHSFunction(ts,NULL,RHSFunction,&ptype[0]);
1099:   } else if ((!strcmp(time_scheme,TSTHETA)) ||
1100:              (!strcmp(time_scheme,TSBEULER)) ||
1101:              (!strcmp(time_scheme,TSCN)) ||
1102:              (!strcmp(time_scheme,TSALPHA)) ||
1103:              (!strcmp(time_scheme,TSARKIMEX))) {
1104:     /* Implicit time-integration -> specify left-hand side function ydot-f(y) = 0 */
1105:     /* and its Jacobian function                                                 */
1106:     TSSetIFunction(ts,NULL,IFunction,&ptype[0]);
1107:     MatCreate(PETSC_COMM_WORLD,&Jac);
1108:     MatSetSizes(Jac,PETSC_DECIDE,PETSC_DECIDE,N,N);
1109:     MatSetFromOptions(Jac);
1110:     MatSetUp(Jac);
1111:     TSSetIJacobian(ts,Jac,Jac,IJacobian,&ptype[0]);
1112:   }

1114:   /* Solve */
1115:   TSSolve(ts,Y);

1117:   /* Exact solution */
1118:   VecDuplicate(Y,&Yex);
1119:   ExactSolution(Yex,&ptype[0],tfinal,exact_flag);

1121:   /* Calculate Error */
1122:   VecAYPX(Yex,-1.0,Y);
1123:   VecNorm(Yex,NORM_2,error);
1124:   *error = PetscSqrtReal(((*error)*(*error))/N);

1126:   /* Clean up and finalize */
1127:   MatDestroy(&Jac);
1128:   TSDestroy(&ts);
1129:   VecDestroy(&Yex);
1130:   VecDestroy(&Y);

1132:   return(0);
1133: }

1137: int main(int argc, char **argv)
1138: {
1139:   PetscErrorCode  ierr;                       /* Error code                                           */
1140:   char            ptype[256] = "hull1972a1";  /* Problem specification                                */
1141:   PetscInt        n_refine   = 1;             /* Number of refinement levels for convergence analysis */
1142:   PetscReal       refine_fac = 2.0;           /* Refinement factor for dt                             */
1143:   PetscReal       dt_initial = 0.01;          /* Initial default value of dt                          */
1144:   PetscReal       dt;
1145:   PetscReal       tfinal     = 20.0;          /* Final time for the time-integration                  */
1146:   PetscInt        maxiter    = 100000;        /* Maximum number of time-integration iterations        */
1147:   PetscReal       *error;                     /* Array to store the errors for convergence analysis   */
1148:   PetscMPIInt     size;                      /* No of processors                                     */
1149:   PetscBool       flag;                       /* Flag denoting availability of exact solution         */
1150:   PetscInt        r;

1152:   /* Initialize program */
1153:   PetscInitialize(&argc,&argv,(char*)0,help);

1155:   /* Check if running with only 1 proc */
1156:   MPI_Comm_size(PETSC_COMM_WORLD,&size);
1157:   if (size>1) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"Only for sequential runs");

1159:   PetscOptionsBegin(PETSC_COMM_WORLD,NULL,NULL,NULL);
1160:   PetscOptionsString("-problem","Problem specification","<hull1972a1>",ptype,ptype,sizeof(ptype),NULL);
1161:   PetscOptionsInt("-refinement_levels","Number of refinement levels for convergence analysis","<1>",n_refine,&n_refine,NULL);
1162:   PetscOptionsReal("-refinement_factor","Refinement factor for dt","<2.0>",refine_fac,&refine_fac,NULL);
1163:   PetscOptionsReal("-dt","Time step size (for convergence analysis, initial time step)","<0.01>",dt_initial,&dt_initial,NULL);
1164:   PetscOptionsReal("-final_time","Final time for the time-integration","<20.0>",tfinal,&tfinal,NULL);
1165:   PetscOptionsEnd();

1167:   PetscMalloc1(n_refine,&error);
1168:   for (r = 0,dt = dt_initial; r < n_refine; r++) {
1169:     error[r] = 0;
1170:     if (r > 0) dt /= refine_fac;

1172:     PetscPrintf(PETSC_COMM_WORLD,"Solving ODE \"%s\" with dt %f, final time %f and system size %D.\n",ptype,(double)dt,(double)tfinal,GetSize(&ptype[0]));
1173:     SolveODE(&ptype[0],dt,tfinal,maxiter,&error[r],&flag);
1174:     if (flag) {
1175:       /* If exact solution available for the specified ODE */
1176:       if (r > 0) {
1177:         PetscReal conv_rate = (PetscLogReal(error[r]) - PetscLogReal(error[r-1])) / (-PetscLogReal(refine_fac));
1178:         PetscPrintf(PETSC_COMM_WORLD,"Error = %E,\tConvergence rate = %f\n.",(double)error[r],(double)conv_rate);
1179:       } else {
1180:         PetscPrintf(PETSC_COMM_WORLD,"Error = %E.\n",error[r]);
1181:       }
1182:     }
1183:   }
1184:   PetscFree(error);

1186:   /* Exit */
1187:   PetscFinalize();
1188:   return(0);
1189: }