xref: /petsc/src/ts/adapt/interface/tsadapt.c (revision 030f984af8d8bb4c203755d35bded3c05b3d83ce)
1 
2 #include <petsc/private/tsimpl.h> /*I  "petscts.h" I*/
3 
4 PetscClassId TSADAPT_CLASSID;
5 
6 static PetscFunctionList TSAdaptList;
7 static PetscBool         TSAdaptPackageInitialized;
8 static PetscBool         TSAdaptRegisterAllCalled;
9 
10 PETSC_EXTERN PetscErrorCode TSAdaptCreate_None(TSAdapt);
11 PETSC_EXTERN PetscErrorCode TSAdaptCreate_Basic(TSAdapt);
12 PETSC_EXTERN PetscErrorCode TSAdaptCreate_DSP(TSAdapt);
13 PETSC_EXTERN PetscErrorCode TSAdaptCreate_CFL(TSAdapt);
14 PETSC_EXTERN PetscErrorCode TSAdaptCreate_GLEE(TSAdapt);
15 PETSC_EXTERN PetscErrorCode TSAdaptCreate_History(TSAdapt);
16 
17 /*@C
18    TSAdaptRegister -  adds a TSAdapt implementation
19 
20    Not Collective
21 
22    Input Parameters:
23 +  name_scheme - name of user-defined adaptivity scheme
24 -  routine_create - routine to create method context
25 
26    Notes:
27    TSAdaptRegister() may be called multiple times to add several user-defined families.
28 
29    Sample usage:
30 .vb
31    TSAdaptRegister("my_scheme",MySchemeCreate);
32 .ve
33 
34    Then, your scheme can be chosen with the procedural interface via
35 $     TSAdaptSetType(ts,"my_scheme")
36    or at runtime via the option
37 $     -ts_adapt_type my_scheme
38 
39    Level: advanced
40 
41 .seealso: TSAdaptRegisterAll()
42 @*/
43 PetscErrorCode  TSAdaptRegister(const char sname[],PetscErrorCode (*function)(TSAdapt))
44 {
45   PetscErrorCode ierr;
46 
47   PetscFunctionBegin;
48   ierr = TSAdaptInitializePackage();CHKERRQ(ierr);
49   ierr = PetscFunctionListAdd(&TSAdaptList,sname,function);CHKERRQ(ierr);
50   PetscFunctionReturn(0);
51 }
52 
53 /*@C
54   TSAdaptRegisterAll - Registers all of the adaptivity schemes in TSAdapt
55 
56   Not Collective
57 
58   Level: advanced
59 
60 .seealso: TSAdaptRegisterDestroy()
61 @*/
62 PetscErrorCode  TSAdaptRegisterAll(void)
63 {
64   PetscErrorCode ierr;
65 
66   PetscFunctionBegin;
67   if (TSAdaptRegisterAllCalled) PetscFunctionReturn(0);
68   TSAdaptRegisterAllCalled = PETSC_TRUE;
69   ierr = TSAdaptRegister(TSADAPTNONE,   TSAdaptCreate_None);CHKERRQ(ierr);
70   ierr = TSAdaptRegister(TSADAPTBASIC,  TSAdaptCreate_Basic);CHKERRQ(ierr);
71   ierr = TSAdaptRegister(TSADAPTDSP,    TSAdaptCreate_DSP);CHKERRQ(ierr);
72   ierr = TSAdaptRegister(TSADAPTCFL,    TSAdaptCreate_CFL);CHKERRQ(ierr);
73   ierr = TSAdaptRegister(TSADAPTGLEE,   TSAdaptCreate_GLEE);CHKERRQ(ierr);
74   ierr = TSAdaptRegister(TSADAPTHISTORY,TSAdaptCreate_History);CHKERRQ(ierr);
75   PetscFunctionReturn(0);
76 }
77 
78 /*@C
79   TSAdaptFinalizePackage - This function destroys everything in the TS package. It is
80   called from PetscFinalize().
81 
82   Level: developer
83 
84 .seealso: PetscFinalize()
85 @*/
86 PetscErrorCode  TSAdaptFinalizePackage(void)
87 {
88   PetscErrorCode ierr;
89 
90   PetscFunctionBegin;
91   ierr = PetscFunctionListDestroy(&TSAdaptList);CHKERRQ(ierr);
92   TSAdaptPackageInitialized = PETSC_FALSE;
93   TSAdaptRegisterAllCalled  = PETSC_FALSE;
94   PetscFunctionReturn(0);
95 }
96 
97 /*@C
98   TSAdaptInitializePackage - This function initializes everything in the TSAdapt package. It is
99   called from TSInitializePackage().
100 
101   Level: developer
102 
103 .seealso: PetscInitialize()
104 @*/
105 PetscErrorCode  TSAdaptInitializePackage(void)
106 {
107   PetscErrorCode ierr;
108 
109   PetscFunctionBegin;
110   if (TSAdaptPackageInitialized) PetscFunctionReturn(0);
111   TSAdaptPackageInitialized = PETSC_TRUE;
112   ierr = PetscClassIdRegister("TSAdapt",&TSADAPT_CLASSID);CHKERRQ(ierr);
113   ierr = TSAdaptRegisterAll();CHKERRQ(ierr);
114   ierr = PetscRegisterFinalize(TSAdaptFinalizePackage);CHKERRQ(ierr);
115   PetscFunctionReturn(0);
116 }
117 
118 /*@C
119   TSAdaptSetType - sets the approach used for the error adapter, currently there is only TSADAPTBASIC and TSADAPTNONE
120 
121   Logicially Collective on TSAdapt
122 
123   Input Parameter:
124 + adapt - the TS adapter, most likely obtained with TSGetAdapt()
125 - type - either  TSADAPTBASIC or TSADAPTNONE
126 
127   Options Database:
128 . -ts_adapt_type <basic or dsp or none> - to set the adapter type
129 
130   Level: intermediate
131 
132 .seealso: TSGetAdapt(), TSAdaptDestroy(), TSAdaptType, TSAdaptGetType()
133 @*/
134 PetscErrorCode  TSAdaptSetType(TSAdapt adapt,TSAdaptType type)
135 {
136   PetscBool      match;
137   PetscErrorCode ierr,(*r)(TSAdapt);
138 
139   PetscFunctionBegin;
140   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
141   PetscValidCharPointer(type,2);
142   ierr = PetscObjectTypeCompare((PetscObject)adapt,type,&match);CHKERRQ(ierr);
143   if (match) PetscFunctionReturn(0);
144   ierr = PetscFunctionListFind(TSAdaptList,type,&r);CHKERRQ(ierr);
145   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown TSAdapt type \"%s\" given",type);
146   if (adapt->ops->destroy) {ierr = (*adapt->ops->destroy)(adapt);CHKERRQ(ierr);}
147   ierr = PetscMemzero(adapt->ops,sizeof(struct _TSAdaptOps));CHKERRQ(ierr);
148   ierr = PetscObjectChangeTypeName((PetscObject)adapt,type);CHKERRQ(ierr);
149   ierr = (*r)(adapt);CHKERRQ(ierr);
150   PetscFunctionReturn(0);
151 }
152 
153 /*@C
154   TSAdaptGetType - gets the TS adapter method type (as a string).
155 
156   Not Collective
157 
158   Input Parameter:
159 . adapt - The TS adapter, most likely obtained with TSGetAdapt()
160 
161   Output Parameter:
162 . type - The name of TS adapter method
163 
164   Level: intermediate
165 
166 .seealso TSAdaptSetType()
167 @*/
168 PetscErrorCode TSAdaptGetType(TSAdapt adapt,TSAdaptType *type)
169 {
170   PetscFunctionBegin;
171   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
172   PetscValidPointer(type,2);
173   *type = ((PetscObject)adapt)->type_name;
174   PetscFunctionReturn(0);
175 }
176 
177 PetscErrorCode  TSAdaptSetOptionsPrefix(TSAdapt adapt,const char prefix[])
178 {
179   PetscErrorCode ierr;
180 
181   PetscFunctionBegin;
182   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
183   ierr = PetscObjectSetOptionsPrefix((PetscObject)adapt,prefix);CHKERRQ(ierr);
184   PetscFunctionReturn(0);
185 }
186 
187 /*@C
188   TSAdaptLoad - Loads a TSAdapt that has been stored in binary  with TSAdaptView().
189 
190   Collective on PetscViewer
191 
192   Input Parameters:
193 + newdm - the newly loaded TSAdapt, this needs to have been created with TSAdaptCreate() or
194            some related function before a call to TSAdaptLoad().
195 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or
196            HDF5 file viewer, obtained from PetscViewerHDF5Open()
197 
198    Level: intermediate
199 
200   Notes:
201    The type is determined by the data in the file, any type set into the TSAdapt before this call is ignored.
202 
203   Notes for advanced users:
204   Most users should not need to know the details of the binary storage
205   format, since TSAdaptLoad() and TSAdaptView() completely hide these details.
206   But for anyone who's interested, the standard binary matrix storage
207   format is
208 .vb
209      has not yet been determined
210 .ve
211 
212 .seealso: PetscViewerBinaryOpen(), TSAdaptView(), MatLoad(), VecLoad()
213 @*/
214 PetscErrorCode  TSAdaptLoad(TSAdapt adapt,PetscViewer viewer)
215 {
216   PetscErrorCode ierr;
217   PetscBool      isbinary;
218   char           type[256];
219 
220   PetscFunctionBegin;
221   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
222   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
223   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
224   if (!isbinary) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen()");
225 
226   ierr = PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);CHKERRQ(ierr);
227   ierr = TSAdaptSetType(adapt,type);CHKERRQ(ierr);
228   if (adapt->ops->load) {
229     ierr = (*adapt->ops->load)(adapt,viewer);CHKERRQ(ierr);
230   }
231   PetscFunctionReturn(0);
232 }
233 
234 PetscErrorCode  TSAdaptView(TSAdapt adapt,PetscViewer viewer)
235 {
236   PetscErrorCode ierr;
237   PetscBool      iascii,isbinary,isnone,isglee;
238 
239   PetscFunctionBegin;
240   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
241   if (!viewer) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)adapt),&viewer);CHKERRQ(ierr);}
242   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
243   PetscCheckSameComm(adapt,1,viewer,2);
244   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
245   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
246   if (iascii) {
247     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)adapt,viewer);CHKERRQ(ierr);
248     ierr = PetscObjectTypeCompare((PetscObject)adapt,TSADAPTNONE,&isnone);CHKERRQ(ierr);
249     ierr = PetscObjectTypeCompare((PetscObject)adapt,TSADAPTGLEE,&isglee);CHKERRQ(ierr);
250     if (!isnone) {
251       if (adapt->always_accept) {ierr = PetscViewerASCIIPrintf(viewer,"  always accepting steps\n");CHKERRQ(ierr);}
252       ierr = PetscViewerASCIIPrintf(viewer,"  safety factor %g\n",(double)adapt->safety);CHKERRQ(ierr);
253       ierr = PetscViewerASCIIPrintf(viewer,"  extra safety factor after step rejection %g\n",(double)adapt->reject_safety);CHKERRQ(ierr);
254       ierr = PetscViewerASCIIPrintf(viewer,"  clip fastest increase %g\n",(double)adapt->clip[1]);CHKERRQ(ierr);
255       ierr = PetscViewerASCIIPrintf(viewer,"  clip fastest decrease %g\n",(double)adapt->clip[0]);CHKERRQ(ierr);
256       ierr = PetscViewerASCIIPrintf(viewer,"  maximum allowed timestep %g\n",(double)adapt->dt_max);CHKERRQ(ierr);
257       ierr = PetscViewerASCIIPrintf(viewer,"  minimum allowed timestep %g\n",(double)adapt->dt_min);CHKERRQ(ierr);
258       ierr = PetscViewerASCIIPrintf(viewer,"  maximum solution absolute value to be ignored %g\n",(double)adapt->ignore_max);CHKERRQ(ierr);
259     }
260     if (isglee) {
261       if (adapt->glee_use_local) {
262         ierr = PetscViewerASCIIPrintf(viewer,"  GLEE uses local error control\n");CHKERRQ(ierr);
263       } else {
264         ierr = PetscViewerASCIIPrintf(viewer,"  GLEE uses global error control\n");CHKERRQ(ierr);
265       }
266     }
267     if (adapt->ops->view) {
268       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
269       ierr = (*adapt->ops->view)(adapt,viewer);CHKERRQ(ierr);
270       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
271     }
272   } else if (isbinary) {
273     char type[256];
274 
275     /* need to save FILE_CLASS_ID for adapt class */
276     ierr = PetscStrncpy(type,((PetscObject)adapt)->type_name,256);CHKERRQ(ierr);
277     ierr = PetscViewerBinaryWrite(viewer,type,256,PETSC_CHAR);CHKERRQ(ierr);
278   } else if (adapt->ops->view) {
279     ierr = (*adapt->ops->view)(adapt,viewer);CHKERRQ(ierr);
280   }
281   PetscFunctionReturn(0);
282 }
283 
284 /*@
285    TSAdaptReset - Resets a TSAdapt context.
286 
287    Collective on TS
288 
289    Input Parameter:
290 .  adapt - the TSAdapt context obtained from TSAdaptCreate()
291 
292    Level: developer
293 
294 .seealso: TSAdaptCreate(), TSAdaptDestroy()
295 @*/
296 PetscErrorCode  TSAdaptReset(TSAdapt adapt)
297 {
298   PetscErrorCode ierr;
299 
300   PetscFunctionBegin;
301   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
302   if (adapt->ops->reset) {ierr = (*adapt->ops->reset)(adapt);CHKERRQ(ierr);}
303   PetscFunctionReturn(0);
304 }
305 
306 PetscErrorCode  TSAdaptDestroy(TSAdapt *adapt)
307 {
308   PetscErrorCode ierr;
309 
310   PetscFunctionBegin;
311   if (!*adapt) PetscFunctionReturn(0);
312   PetscValidHeaderSpecific(*adapt,TSADAPT_CLASSID,1);
313   if (--((PetscObject)(*adapt))->refct > 0) {*adapt = NULL; PetscFunctionReturn(0);}
314 
315   ierr = TSAdaptReset(*adapt);CHKERRQ(ierr);
316 
317   if ((*adapt)->ops->destroy) {ierr = (*(*adapt)->ops->destroy)(*adapt);CHKERRQ(ierr);}
318   ierr = PetscViewerDestroy(&(*adapt)->monitor);CHKERRQ(ierr);
319   ierr = PetscHeaderDestroy(adapt);CHKERRQ(ierr);
320   PetscFunctionReturn(0);
321 }
322 
323 /*@
324    TSAdaptSetMonitor - Monitor the choices made by the adaptive controller
325 
326    Collective on TSAdapt
327 
328    Input Arguments:
329 +  adapt - adaptive controller context
330 -  flg - PETSC_TRUE to active a monitor, PETSC_FALSE to disable
331 
332    Options Database Keys:
333 .  -ts_adapt_monitor - to turn on monitoring
334 
335    Level: intermediate
336 
337 .seealso: TSAdaptChoose()
338 @*/
339 PetscErrorCode TSAdaptSetMonitor(TSAdapt adapt,PetscBool flg)
340 {
341   PetscErrorCode ierr;
342 
343   PetscFunctionBegin;
344   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
345   PetscValidLogicalCollectiveBool(adapt,flg,2);
346   if (flg) {
347     if (!adapt->monitor) {ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)adapt),"stdout",&adapt->monitor);CHKERRQ(ierr);}
348   } else {
349     ierr = PetscViewerDestroy(&adapt->monitor);CHKERRQ(ierr);
350   }
351   PetscFunctionReturn(0);
352 }
353 
354 /*@C
355    TSAdaptSetCheckStage - Set a callback to check convergence for a stage
356 
357    Logically collective on TSAdapt
358 
359    Input Arguments:
360 +  adapt - adaptive controller context
361 -  func - stage check function
362 
363    Arguments of func:
364 $  PetscErrorCode func(TSAdapt adapt,TS ts,PetscBool *accept)
365 
366 +  adapt - adaptive controller context
367 .  ts - time stepping context
368 -  accept - pending choice of whether to accept, can be modified by this routine
369 
370    Level: advanced
371 
372 .seealso: TSAdaptChoose()
373 @*/
374 PetscErrorCode TSAdaptSetCheckStage(TSAdapt adapt,PetscErrorCode (*func)(TSAdapt,TS,PetscReal,Vec,PetscBool*))
375 {
376   PetscFunctionBegin;
377   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
378   adapt->checkstage = func;
379   PetscFunctionReturn(0);
380 }
381 
382 /*@
383    TSAdaptSetAlwaysAccept - Set whether to always accept steps regardless of
384    any error or stability condition not meeting the prescribed goal.
385 
386    Logically collective on TSAdapt
387 
388    Input Arguments:
389 +  adapt - time step adaptivity context, usually gotten with TSGetAdapt()
390 -  flag - whether to always accept steps
391 
392    Options Database Keys:
393 .  -ts_adapt_always_accept - to always accept steps
394 
395    Level: intermediate
396 
397 .seealso: TSAdapt, TSAdaptChoose()
398 @*/
399 PetscErrorCode TSAdaptSetAlwaysAccept(TSAdapt adapt,PetscBool flag)
400 {
401   PetscFunctionBegin;
402   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
403   PetscValidLogicalCollectiveBool(adapt,flag,2);
404   adapt->always_accept = flag;
405   PetscFunctionReturn(0);
406 }
407 
408 /*@
409    TSAdaptSetSafety - Set safety factors
410 
411    Logically collective on TSAdapt
412 
413    Input Arguments:
414 +  adapt - adaptive controller context
415 .  safety - safety factor relative to target error/stability goal
416 -  reject_safety - extra safety factor to apply if the last step was rejected
417 
418    Options Database Keys:
419 +  -ts_adapt_safety <safety> - to set safety factor
420 -  -ts_adapt_reject_safety <reject_safety> - to set reject safety factor
421 
422    Level: intermediate
423 
424 .seealso: TSAdapt, TSAdaptGetSafety(), TSAdaptChoose()
425 @*/
426 PetscErrorCode TSAdaptSetSafety(TSAdapt adapt,PetscReal safety,PetscReal reject_safety)
427 {
428   PetscFunctionBegin;
429   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
430   PetscValidLogicalCollectiveReal(adapt,safety,2);
431   PetscValidLogicalCollectiveReal(adapt,reject_safety,3);
432   if (safety != PETSC_DEFAULT && safety < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Safety factor %g must be non negative",(double)safety);
433   if (safety != PETSC_DEFAULT && safety > 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Safety factor %g must be less than one",(double)safety);
434   if (reject_safety != PETSC_DEFAULT && reject_safety < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Reject safety factor %g must be non negative",(double)reject_safety);
435   if (reject_safety != PETSC_DEFAULT && reject_safety > 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Reject safety factor %g must be less than one",(double)reject_safety);
436   if (safety != PETSC_DEFAULT) adapt->safety = safety;
437   if (reject_safety != PETSC_DEFAULT) adapt->reject_safety = reject_safety;
438   PetscFunctionReturn(0);
439 }
440 
441 /*@
442    TSAdaptGetSafety - Get safety factors
443 
444    Not Collective
445 
446    Input Arguments:
447 .  adapt - adaptive controller context
448 
449    Ouput Arguments:
450 .  safety - safety factor relative to target error/stability goal
451 +  reject_safety - extra safety factor to apply if the last step was rejected
452 
453    Level: intermediate
454 
455 .seealso: TSAdapt, TSAdaptSetSafety(), TSAdaptChoose()
456 @*/
457 PetscErrorCode TSAdaptGetSafety(TSAdapt adapt,PetscReal *safety,PetscReal *reject_safety)
458 {
459   PetscFunctionBegin;
460   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
461   if (safety)        PetscValidRealPointer(safety,2);
462   if (reject_safety) PetscValidRealPointer(reject_safety,3);
463   if (safety)        *safety        = adapt->safety;
464   if (reject_safety) *reject_safety = adapt->reject_safety;
465   PetscFunctionReturn(0);
466 }
467 
468 /*@
469    TSAdaptSetMaxIgnore - Set error estimation threshold. Solution components below this threshold value will not be considered when computing error norms for time step adaptivity (in absolute value). A negative value (default) of the threshold leads to considering all solution components.
470 
471    Logically collective on TSAdapt
472 
473    Input Arguments:
474 +  adapt - adaptive controller context
475 -  max_ignore - threshold for solution components that are ignored during error estimation
476 
477    Options Database Keys:
478 .  -ts_adapt_max_ignore <max_ignore> - to set the threshold
479 
480    Level: intermediate
481 
482 .seealso: TSAdapt, TSAdaptGetMaxIgnore(), TSAdaptChoose()
483 @*/
484 PetscErrorCode TSAdaptSetMaxIgnore(TSAdapt adapt,PetscReal max_ignore)
485 {
486   PetscFunctionBegin;
487   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
488   PetscValidLogicalCollectiveReal(adapt,max_ignore,2);
489   adapt->ignore_max = max_ignore;
490   PetscFunctionReturn(0);
491 }
492 
493 /*@
494    TSAdaptGetMaxIgnore - Get error estimation threshold. Solution components below this threshold value will not be considered when computing error norms for time step adaptivity (in absolute value).
495 
496    Not Collective
497 
498    Input Arguments:
499 .  adapt - adaptive controller context
500 
501    Ouput Arguments:
502 .  max_ignore - threshold for solution components that are ignored during error estimation
503 
504    Level: intermediate
505 
506 .seealso: TSAdapt, TSAdaptSetMaxIgnore(), TSAdaptChoose()
507 @*/
508 PetscErrorCode TSAdaptGetMaxIgnore(TSAdapt adapt,PetscReal *max_ignore)
509 {
510   PetscFunctionBegin;
511   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
512   PetscValidRealPointer(max_ignore,2);
513   *max_ignore = adapt->ignore_max;
514   PetscFunctionReturn(0);
515 }
516 
517 /*@
518    TSAdaptSetClip - Sets the admissible decrease/increase factor in step size
519 
520    Logically collective on TSAdapt
521 
522    Input Arguments:
523 +  adapt - adaptive controller context
524 .  low - admissible decrease factor
525 -  high - admissible increase factor
526 
527    Options Database Keys:
528 .  -ts_adapt_clip <low>,<high> - to set admissible time step decrease and increase factors
529 
530    Level: intermediate
531 
532 .seealso: TSAdaptChoose(), TSAdaptGetClip(), TSAdaptSetScaleSolveFailed()
533 @*/
534 PetscErrorCode TSAdaptSetClip(TSAdapt adapt,PetscReal low,PetscReal high)
535 {
536   PetscFunctionBegin;
537   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
538   PetscValidLogicalCollectiveReal(adapt,low,2);
539   PetscValidLogicalCollectiveReal(adapt,high,3);
540   if (low  != PETSC_DEFAULT && low  < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Decrease factor %g must be non negative",(double)low);
541   if (low  != PETSC_DEFAULT && low  > 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Decrease factor %g must be less than one",(double)low);
542   if (high != PETSC_DEFAULT && high < 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Increase factor %g must be greater than one",(double)high);
543   if (low  != PETSC_DEFAULT) adapt->clip[0] = low;
544   if (high != PETSC_DEFAULT) adapt->clip[1] = high;
545   PetscFunctionReturn(0);
546 }
547 
548 /*@
549    TSAdaptGetClip - Gets the admissible decrease/increase factor in step size
550 
551    Not Collective
552 
553    Input Arguments:
554 .  adapt - adaptive controller context
555 
556    Ouput Arguments:
557 +  low - optional, admissible decrease factor
558 -  high - optional, admissible increase factor
559 
560    Level: intermediate
561 
562 .seealso: TSAdaptChoose(), TSAdaptSetClip(), TSAdaptSetScaleSolveFailed()
563 @*/
564 PetscErrorCode TSAdaptGetClip(TSAdapt adapt,PetscReal *low,PetscReal *high)
565 {
566   PetscFunctionBegin;
567   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
568   if (low)  PetscValidRealPointer(low,2);
569   if (high) PetscValidRealPointer(high,3);
570   if (low)  *low  = adapt->clip[0];
571   if (high) *high = adapt->clip[1];
572   PetscFunctionReturn(0);
573 }
574 
575 /*@
576    TSAdaptSetScaleSolveFailed - Scale step by this factor if solve fails
577 
578    Logically collective on TSAdapt
579 
580    Input Arguments:
581 +  adapt - adaptive controller context
582 -  scale - scale
583 
584    Options Database Keys:
585 .  -ts_adapt_scale_solve_failed <scale> - to set scale step by this factor if solve fails
586 
587    Level: intermediate
588 
589 .seealso: TSAdaptChoose(), TSAdaptGetScaleSolveFailed(), TSAdaptGetClip()
590 @*/
591 PetscErrorCode TSAdaptSetScaleSolveFailed(TSAdapt adapt,PetscReal scale)
592 {
593   PetscFunctionBegin;
594   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
595   PetscValidLogicalCollectiveReal(adapt,scale,2);
596   if (scale != PETSC_DEFAULT && scale <= 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Scale factor %g must be positive",(double)scale);
597   if (scale != PETSC_DEFAULT && scale  > 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Scale factor %g must be less than one",(double)scale);
598   if (scale != PETSC_DEFAULT) adapt->scale_solve_failed = scale;
599   PetscFunctionReturn(0);
600 }
601 
602 /*@
603    TSAdaptGetScaleSolveFailed - Gets the admissible decrease/increase factor in step size
604 
605    Not Collective
606 
607    Input Arguments:
608 .  adapt - adaptive controller context
609 
610    Ouput Arguments:
611 .  scale - scale factor
612 
613    Level: intermediate
614 
615 .seealso: TSAdaptChoose(), TSAdaptSetScaleSolveFailed(), TSAdaptSetClip()
616 @*/
617 PetscErrorCode TSAdaptGetScaleSolveFailed(TSAdapt adapt,PetscReal *scale)
618 {
619   PetscFunctionBegin;
620   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
621   if (scale)  PetscValidRealPointer(scale,2);
622   if (scale)  *scale  = adapt->scale_solve_failed;
623   PetscFunctionReturn(0);
624 }
625 
626 /*@
627    TSAdaptSetStepLimits - Set the minimum and maximum step sizes to be considered by the controller
628 
629    Logically collective on TSAdapt
630 
631    Input Arguments:
632 +  adapt - time step adaptivity context, usually gotten with TSGetAdapt()
633 .  hmin - minimum time step
634 -  hmax - maximum time step
635 
636    Options Database Keys:
637 +  -ts_adapt_dt_min <min> - to set minimum time step
638 -  -ts_adapt_dt_max <max> - to set maximum time step
639 
640    Level: intermediate
641 
642 .seealso: TSAdapt, TSAdaptGetStepLimits(), TSAdaptChoose()
643 @*/
644 PetscErrorCode TSAdaptSetStepLimits(TSAdapt adapt,PetscReal hmin,PetscReal hmax)
645 {
646 
647   PetscFunctionBegin;
648   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
649   PetscValidLogicalCollectiveReal(adapt,hmin,2);
650   PetscValidLogicalCollectiveReal(adapt,hmax,3);
651   if (hmin != PETSC_DEFAULT && hmin < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Minimum time step %g must be non negative",(double)hmin);
652   if (hmax != PETSC_DEFAULT && hmax < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Minimum time step %g must be non negative",(double)hmax);
653   if (hmin != PETSC_DEFAULT) adapt->dt_min = hmin;
654   if (hmax != PETSC_DEFAULT) adapt->dt_max = hmax;
655   hmin = adapt->dt_min;
656   hmax = adapt->dt_max;
657   if (hmax <= hmin) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Maximum time step %g must greater than minimum time step %g",(double)hmax,(double)hmin);
658   PetscFunctionReturn(0);
659 }
660 
661 /*@
662    TSAdaptGetStepLimits - Get the minimum and maximum step sizes to be considered by the controller
663 
664    Not Collective
665 
666    Input Arguments:
667 .  adapt - time step adaptivity context, usually gotten with TSGetAdapt()
668 
669    Output Arguments:
670 +  hmin - minimum time step
671 -  hmax - maximum time step
672 
673    Level: intermediate
674 
675 .seealso: TSAdapt, TSAdaptSetStepLimits(), TSAdaptChoose()
676 @*/
677 PetscErrorCode TSAdaptGetStepLimits(TSAdapt adapt,PetscReal *hmin,PetscReal *hmax)
678 {
679 
680   PetscFunctionBegin;
681   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
682   if (hmin) PetscValidRealPointer(hmin,2);
683   if (hmax) PetscValidRealPointer(hmax,3);
684   if (hmin) *hmin = adapt->dt_min;
685   if (hmax) *hmax = adapt->dt_max;
686   PetscFunctionReturn(0);
687 }
688 
689 /*
690    TSAdaptSetFromOptions - Sets various TSAdapt parameters from user options.
691 
692    Collective on TSAdapt
693 
694    Input Parameter:
695 .  adapt - the TSAdapt context
696 
697    Options Database Keys:
698 +  -ts_adapt_type <type> - algorithm to use for adaptivity
699 .  -ts_adapt_always_accept - always accept steps regardless of error/stability goals
700 .  -ts_adapt_safety <safety> - safety factor relative to target error/stability goal
701 .  -ts_adapt_reject_safety <safety> - extra safety factor to apply if the last step was rejected
702 .  -ts_adapt_clip <low,high> - admissible time step decrease and increase factors
703 .  -ts_adapt_dt_min <min> - minimum timestep to use
704 .  -ts_adapt_dt_max <max> - maximum timestep to use
705 .  -ts_adapt_scale_solve_failed <scale> - scale timestep by this factor if a solve fails
706 .  -ts_adapt_wnormtype <2 or infinity> - type of norm for computing error estimates
707 -  -ts_adapt_time_step_increase_delay - number of timesteps to delay increasing the time step after it has been decreased due to failed solver
708 
709    Level: advanced
710 
711    Notes:
712    This function is automatically called by TSSetFromOptions()
713 
714 .seealso: TSGetAdapt(), TSAdaptSetType(), TSAdaptSetAlwaysAccept(), TSAdaptSetSafety(),
715           TSAdaptSetClip(), TSAdaptSetScaleSolveFailed(), TSAdaptSetStepLimits(), TSAdaptSetMonitor()
716 */
717 PetscErrorCode  TSAdaptSetFromOptions(PetscOptionItems *PetscOptionsObject,TSAdapt adapt)
718 {
719   PetscErrorCode ierr;
720   char           type[256] = TSADAPTBASIC;
721   PetscReal      safety,reject_safety,clip[2],scale,hmin,hmax;
722   PetscBool      set,flg;
723   PetscInt       two;
724 
725   PetscFunctionBegin;
726   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,2);
727   /* This should use PetscOptionsBegin() if/when this becomes an object used outside of TS, but currently this
728    * function can only be called from inside TSSetFromOptions()  */
729   ierr = PetscOptionsHead(PetscOptionsObject,"TS Adaptivity options");CHKERRQ(ierr);
730   ierr = PetscOptionsFList("-ts_adapt_type","Algorithm to use for adaptivity","TSAdaptSetType",TSAdaptList,((PetscObject)adapt)->type_name ? ((PetscObject)adapt)->type_name : type,type,sizeof(type),&flg);CHKERRQ(ierr);
731   if (flg || !((PetscObject)adapt)->type_name) {
732     ierr = TSAdaptSetType(adapt,type);CHKERRQ(ierr);
733   }
734 
735   ierr = PetscOptionsBool("-ts_adapt_always_accept","Always accept the step","TSAdaptSetAlwaysAccept",adapt->always_accept,&flg,&set);CHKERRQ(ierr);
736   if (set) {ierr = TSAdaptSetAlwaysAccept(adapt,flg);CHKERRQ(ierr);}
737 
738   safety = adapt->safety; reject_safety = adapt->reject_safety;
739   ierr = PetscOptionsReal("-ts_adapt_safety","Safety factor relative to target error/stability goal","TSAdaptSetSafety",safety,&safety,&set);CHKERRQ(ierr);
740   ierr = PetscOptionsReal("-ts_adapt_reject_safety","Extra safety factor to apply if the last step was rejected","TSAdaptSetSafety",reject_safety,&reject_safety,&flg);CHKERRQ(ierr);
741   if (set || flg) {ierr = TSAdaptSetSafety(adapt,safety,reject_safety);CHKERRQ(ierr);}
742 
743   two = 2; clip[0] = adapt->clip[0]; clip[1] = adapt->clip[1];
744   ierr = PetscOptionsRealArray("-ts_adapt_clip","Admissible decrease/increase factor in step size","TSAdaptSetClip",clip,&two,&set);CHKERRQ(ierr);
745   if (set && (two != 2)) SETERRQ(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_OUTOFRANGE,"Must give exactly two values to -ts_adapt_clip");
746   if (set) {ierr = TSAdaptSetClip(adapt,clip[0],clip[1]);CHKERRQ(ierr);}
747 
748   hmin = adapt->dt_min; hmax = adapt->dt_max;
749   ierr = PetscOptionsReal("-ts_adapt_dt_min","Minimum time step considered","TSAdaptSetStepLimits",hmin,&hmin,&set);CHKERRQ(ierr);
750   ierr = PetscOptionsReal("-ts_adapt_dt_max","Maximum time step considered","TSAdaptSetStepLimits",hmax,&hmax,&flg);CHKERRQ(ierr);
751   if (set || flg) {ierr = TSAdaptSetStepLimits(adapt,hmin,hmax);CHKERRQ(ierr);}
752 
753   ierr = PetscOptionsReal("-ts_adapt_max_ignore","Adaptor ignores (absolute) solution values smaller than this value","",adapt->ignore_max,&adapt->ignore_max,&set);CHKERRQ(ierr);
754   ierr = PetscOptionsBool("-ts_adapt_glee_use_local","GLEE adaptor uses local error estimation for step control","",adapt->glee_use_local,&adapt->glee_use_local,&set);CHKERRQ(ierr);
755 
756   ierr = PetscOptionsReal("-ts_adapt_scale_solve_failed","Scale step by this factor if solve fails","TSAdaptSetScaleSolveFailed",adapt->scale_solve_failed,&scale,&set);CHKERRQ(ierr);
757   if (set) {ierr = TSAdaptSetScaleSolveFailed(adapt,scale);CHKERRQ(ierr);}
758 
759   ierr = PetscOptionsEnum("-ts_adapt_wnormtype","Type of norm computed for error estimation","",NormTypes,(PetscEnum)adapt->wnormtype,(PetscEnum*)&adapt->wnormtype,NULL);CHKERRQ(ierr);
760   if (adapt->wnormtype != NORM_2 && adapt->wnormtype != NORM_INFINITY) SETERRQ(PetscObjectComm((PetscObject)adapt),PETSC_ERR_SUP,"Only 2-norm and infinite norm supported");
761 
762   ierr = PetscOptionsInt("-ts_adapt_time_step_increase_delay","Number of timesteps to delay increasing the time step after it has been decreased due to failed solver","TSAdaptSetTimeStepIncreaseDelay",adapt->timestepjustdecreased_delay,&adapt->timestepjustdecreased_delay,NULL);CHKERRQ(ierr);
763 
764   ierr = PetscOptionsBool("-ts_adapt_monitor","Print choices made by adaptive controller","TSAdaptSetMonitor",adapt->monitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr);
765   if (set) {ierr = TSAdaptSetMonitor(adapt,flg);CHKERRQ(ierr);}
766 
767   if (adapt->ops->setfromoptions) {ierr = (*adapt->ops->setfromoptions)(PetscOptionsObject,adapt);CHKERRQ(ierr);}
768   ierr = PetscOptionsTail();CHKERRQ(ierr);
769   PetscFunctionReturn(0);
770 }
771 
772 /*@
773    TSAdaptCandidatesClear - clear any previously set candidate schemes
774 
775    Logically collective on TSAdapt
776 
777    Input Argument:
778 .  adapt - adaptive controller
779 
780    Level: developer
781 
782 .seealso: TSAdapt, TSAdaptCreate(), TSAdaptCandidateAdd(), TSAdaptChoose()
783 @*/
784 PetscErrorCode TSAdaptCandidatesClear(TSAdapt adapt)
785 {
786   PetscErrorCode ierr;
787 
788   PetscFunctionBegin;
789   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
790   ierr = PetscMemzero(&adapt->candidates,sizeof(adapt->candidates));CHKERRQ(ierr);
791   PetscFunctionReturn(0);
792 }
793 
794 /*@C
795    TSAdaptCandidateAdd - add a candidate scheme for the adaptive controller to select from
796 
797    Logically collective on TSAdapt
798 
799    Input Arguments:
800 +  adapt - time step adaptivity context, obtained with TSGetAdapt() or TSAdaptCreate()
801 .  name - name of the candidate scheme to add
802 .  order - order of the candidate scheme
803 .  stageorder - stage order of the candidate scheme
804 .  ccfl - stability coefficient relative to explicit Euler, used for CFL constraints
805 .  cost - relative measure of the amount of work required for the candidate scheme
806 -  inuse - indicates that this scheme is the one currently in use, this flag can only be set for one scheme
807 
808    Note:
809    This routine is not available in Fortran.
810 
811    Level: developer
812 
813 .seealso: TSAdaptCandidatesClear(), TSAdaptChoose()
814 @*/
815 PetscErrorCode TSAdaptCandidateAdd(TSAdapt adapt,const char name[],PetscInt order,PetscInt stageorder,PetscReal ccfl,PetscReal cost,PetscBool inuse)
816 {
817   PetscInt c;
818 
819   PetscFunctionBegin;
820   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
821   if (order < 1) SETERRQ1(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_OUTOFRANGE,"Classical order %D must be a positive integer",order);
822   if (inuse) {
823     if (adapt->candidates.inuse_set) SETERRQ(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_WRONGSTATE,"Cannot set the inuse method twice, maybe forgot to call TSAdaptCandidatesClear()");
824     adapt->candidates.inuse_set = PETSC_TRUE;
825   }
826   /* first slot if this is the current scheme, otherwise the next available slot */
827   c = inuse ? 0 : !adapt->candidates.inuse_set + adapt->candidates.n;
828 
829   adapt->candidates.name[c]       = name;
830   adapt->candidates.order[c]      = order;
831   adapt->candidates.stageorder[c] = stageorder;
832   adapt->candidates.ccfl[c]       = ccfl;
833   adapt->candidates.cost[c]       = cost;
834   adapt->candidates.n++;
835   PetscFunctionReturn(0);
836 }
837 
838 /*@C
839    TSAdaptCandidatesGet - Get the list of candidate orders of accuracy and cost
840 
841    Not Collective
842 
843    Input Arguments:
844 .  adapt - time step adaptivity context
845 
846    Output Arguments:
847 +  n - number of candidate schemes, always at least 1
848 .  order - the order of each candidate scheme
849 .  stageorder - the stage order of each candidate scheme
850 .  ccfl - the CFL coefficient of each scheme
851 -  cost - the relative cost of each scheme
852 
853    Level: developer
854 
855    Note:
856    The current scheme is always returned in the first slot
857 
858 .seealso: TSAdaptCandidatesClear(), TSAdaptCandidateAdd(), TSAdaptChoose()
859 @*/
860 PetscErrorCode TSAdaptCandidatesGet(TSAdapt adapt,PetscInt *n,const PetscInt **order,const PetscInt **stageorder,const PetscReal **ccfl,const PetscReal **cost)
861 {
862   PetscFunctionBegin;
863   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
864   if (n) *n = adapt->candidates.n;
865   if (order) *order = adapt->candidates.order;
866   if (stageorder) *stageorder = adapt->candidates.stageorder;
867   if (ccfl) *ccfl = adapt->candidates.ccfl;
868   if (cost) *cost = adapt->candidates.cost;
869   PetscFunctionReturn(0);
870 }
871 
872 /*@C
873    TSAdaptChoose - choose which method and step size to use for the next step
874 
875    Collective on TSAdapt
876 
877    Input Arguments:
878 +  adapt - adaptive contoller
879 -  h - current step size
880 
881    Output Arguments:
882 +  next_sc - optional, scheme to use for the next step
883 .  next_h - step size to use for the next step
884 -  accept - PETSC_TRUE to accept the current step, PETSC_FALSE to repeat the current step with the new step size
885 
886    Note:
887    The input value of parameter accept is retained from the last time step, so it will be PETSC_FALSE if the step is
888    being retried after an initial rejection.
889 
890    Level: developer
891 
892 .seealso: TSAdapt, TSAdaptCandidatesClear(), TSAdaptCandidateAdd()
893 @*/
894 PetscErrorCode TSAdaptChoose(TSAdapt adapt,TS ts,PetscReal h,PetscInt *next_sc,PetscReal *next_h,PetscBool *accept)
895 {
896   PetscErrorCode ierr;
897   PetscInt       ncandidates = adapt->candidates.n;
898   PetscInt       scheme = 0;
899   PetscReal      wlte = -1.0;
900   PetscReal      wltea = -1.0;
901   PetscReal      wlter = -1.0;
902 
903   PetscFunctionBegin;
904   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
905   PetscValidHeaderSpecific(ts,TS_CLASSID,2);
906   if (next_sc) PetscValidIntPointer(next_sc,4);
907   PetscValidPointer(next_h,5);
908   PetscValidBoolPointer(accept,6);
909   if (next_sc) *next_sc = 0;
910 
911   /* Do not mess with adaptivity while handling events*/
912   if (ts->event && ts->event->status != TSEVENT_NONE) {
913     *next_h = h;
914     *accept = PETSC_TRUE;
915     PetscFunctionReturn(0);
916   }
917 
918   ierr = (*adapt->ops->choose)(adapt,ts,h,&scheme,next_h,accept,&wlte,&wltea,&wlter);CHKERRQ(ierr);
919   if (scheme < 0 || (ncandidates > 0 && scheme >= ncandidates)) SETERRQ2(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_OUTOFRANGE,"Chosen scheme %D not in valid range 0..%D",scheme,ncandidates-1);
920   if (*next_h < 0) SETERRQ1(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_OUTOFRANGE,"Computed step size %g must be positive",(double)*next_h);
921   if (next_sc) *next_sc = scheme;
922 
923   if (*accept && ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP) {
924     /* Increase/reduce step size if end time of next step is close to or overshoots max time */
925     PetscReal t = ts->ptime + ts->time_step, h = *next_h;
926     PetscReal tend = t + h, tmax = ts->max_time, hmax = tmax - t;
927     PetscReal a = (PetscReal)(1.0 + adapt->matchstepfac[0]);
928     PetscReal b = adapt->matchstepfac[1];
929     if (t < tmax && tend > tmax) *next_h = hmax;
930     if (t < tmax && tend < tmax && h*b > hmax) *next_h = hmax/2;
931     if (t < tmax && tend < tmax && h*a > hmax) *next_h = hmax;
932   }
933 
934   if (adapt->monitor) {
935     const char *sc_name = (scheme < ncandidates) ? adapt->candidates.name[scheme] : "";
936     ierr = PetscViewerASCIIAddTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
937     if (wlte < 0) {
938       ierr = PetscViewerASCIIPrintf(adapt->monitor,"    TSAdapt %s %s %D:%s step %3D %s t=%-11g+%10.3e dt=%-10.3e\n",((PetscObject)adapt)->type_name,((PetscObject)ts)->type_name,scheme,sc_name,ts->steps,*accept ? "accepted" : "rejected",(double)ts->ptime,(double)h,(double)*next_h);CHKERRQ(ierr);
939     } else {
940       ierr = PetscViewerASCIIPrintf(adapt->monitor,"    TSAdapt %s %s %D:%s step %3D %s t=%-11g+%10.3e dt=%-10.3e wlte=%5.3g  wltea=%5.3g wlter=%5.3g\n",((PetscObject)adapt)->type_name,((PetscObject)ts)->type_name,scheme,sc_name,ts->steps,*accept ? "accepted" : "rejected",(double)ts->ptime,(double)h,(double)*next_h,(double)wlte,(double)wltea,(double)wlter);CHKERRQ(ierr);
941     }
942     ierr = PetscViewerASCIISubtractTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
943   }
944   PetscFunctionReturn(0);
945 }
946 
947 /*@
948    TSAdaptSetTimeStepIncreaseDelay - The number of timesteps to wait after a decrease in the timestep due to failed solver
949                                      before increasing the time step.
950 
951    Logicially Collective on TSAdapt
952 
953    Input Arguments:
954 +  adapt - adaptive controller context
955 -  cnt - the number of timesteps
956 
957    Options Database Key:
958 .  -ts_adapt_time_step_increase_delay cnt - number of steps to delay the increase
959 
960    Notes: This is to prevent an adaptor from bouncing back and forth between two nearby timesteps. The default is 0.
961           The successful use of this option is problem dependent
962 
963    Developer Note: there is no theory to support this option
964 
965    Level: advanced
966 
967 .seealso:
968 @*/
969 PetscErrorCode TSAdaptSetTimeStepIncreaseDelay(TSAdapt adapt,PetscInt cnt)
970 {
971   PetscFunctionBegin;
972   adapt->timestepjustdecreased_delay = cnt;
973   PetscFunctionReturn(0);
974 }
975 
976 /*@
977    TSAdaptCheckStage - checks whether to accept a stage, (e.g. reject and change time step size if nonlinear solve fails or solution vector is infeasible)
978 
979    Collective on TSAdapt
980 
981    Input Arguments:
982 +  adapt - adaptive controller context
983 .  ts - time stepper
984 .  t - Current simulation time
985 -  Y - Current solution vector
986 
987    Output Arguments:
988 .  accept - PETSC_TRUE to accept the stage, PETSC_FALSE to reject
989 
990    Level: developer
991 
992 .seealso:
993 @*/
994 PetscErrorCode TSAdaptCheckStage(TSAdapt adapt,TS ts,PetscReal t,Vec Y,PetscBool *accept)
995 {
996   PetscErrorCode      ierr;
997   SNESConvergedReason snesreason = SNES_CONVERGED_ITERATING;
998 
999   PetscFunctionBegin;
1000   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
1001   PetscValidHeaderSpecific(ts,TS_CLASSID,2);
1002   PetscValidBoolPointer(accept,5);
1003 
1004   if (ts->snes) {ierr = SNESGetConvergedReason(ts->snes,&snesreason);CHKERRQ(ierr);}
1005   if (snesreason < 0) {
1006     *accept = PETSC_FALSE;
1007     if (++ts->num_snes_failures >= ts->max_snes_failures && ts->max_snes_failures > 0) {
1008       ts->reason = TS_DIVERGED_NONLINEAR_SOLVE;
1009       ierr = PetscInfo2(ts,"Step=%D, nonlinear solve failures %D greater than current TS allowed, stopping solve\n",ts->steps,ts->num_snes_failures);CHKERRQ(ierr);
1010       if (adapt->monitor) {
1011         ierr = PetscViewerASCIIAddTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
1012         ierr = PetscViewerASCIIPrintf(adapt->monitor,"    TSAdapt %s step %3D stage rejected t=%-11g+%10.3e, nonlinear solve failures %D greater than current TS allowed\n",((PetscObject)adapt)->type_name,ts->steps,(double)ts->ptime,(double)ts->time_step,ts->num_snes_failures);CHKERRQ(ierr);
1013         ierr = PetscViewerASCIISubtractTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
1014       }
1015     }
1016   } else {
1017     *accept = PETSC_TRUE;
1018     ierr = TSFunctionDomainError(ts,t,Y,accept);CHKERRQ(ierr);
1019     if (*accept && adapt->checkstage) {
1020       ierr = (*adapt->checkstage)(adapt,ts,t,Y,accept);CHKERRQ(ierr);
1021       if (!*accept) {
1022         ierr = PetscInfo1(ts,"Step=%D, solution rejected by user function provided by TSSetFunctionDomainError()\n",ts->steps);CHKERRQ(ierr);
1023         if (adapt->monitor) {
1024           ierr = PetscViewerASCIIAddTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
1025           ierr = PetscViewerASCIIPrintf(adapt->monitor,"    TSAdapt %s step %3D stage rejected by user function provided by TSSetFunctionDomainError()\n",((PetscObject)adapt)->type_name,ts->steps);CHKERRQ(ierr);
1026           ierr = PetscViewerASCIISubtractTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
1027         }
1028       }
1029     }
1030   }
1031 
1032   if (!(*accept) && !ts->reason) {
1033     PetscReal dt,new_dt;
1034     ierr = TSGetTimeStep(ts,&dt);CHKERRQ(ierr);
1035     new_dt = dt * adapt->scale_solve_failed;
1036     ierr = TSSetTimeStep(ts,new_dt);CHKERRQ(ierr);
1037     adapt->timestepjustdecreased += adapt->timestepjustdecreased_delay;
1038     if (adapt->monitor) {
1039       ierr = PetscViewerASCIIAddTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
1040       ierr = PetscViewerASCIIPrintf(adapt->monitor,"    TSAdapt %s step %3D stage rejected (%s) t=%-11g+%10.3e retrying with dt=%-10.3e\n",((PetscObject)adapt)->type_name,ts->steps,SNESConvergedReasons[snesreason],(double)ts->ptime,(double)dt,(double)new_dt);CHKERRQ(ierr);
1041       ierr = PetscViewerASCIISubtractTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
1042     }
1043   }
1044   PetscFunctionReturn(0);
1045 }
1046 
1047 /*@
1048   TSAdaptCreate - create an adaptive controller context for time stepping
1049 
1050   Collective
1051 
1052   Input Parameter:
1053 . comm - The communicator
1054 
1055   Output Parameter:
1056 . adapt - new TSAdapt object
1057 
1058   Level: developer
1059 
1060   Notes:
1061   TSAdapt creation is handled by TS, so users should not need to call this function.
1062 
1063 .seealso: TSGetAdapt(), TSAdaptSetType(), TSAdaptDestroy()
1064 @*/
1065 PetscErrorCode  TSAdaptCreate(MPI_Comm comm,TSAdapt *inadapt)
1066 {
1067   PetscErrorCode ierr;
1068   TSAdapt        adapt;
1069 
1070   PetscFunctionBegin;
1071   PetscValidPointer(inadapt,2);
1072   *inadapt = NULL;
1073   ierr = TSAdaptInitializePackage();CHKERRQ(ierr);
1074 
1075   ierr = PetscHeaderCreate(adapt,TSADAPT_CLASSID,"TSAdapt","Time stepping adaptivity","TS",comm,TSAdaptDestroy,TSAdaptView);CHKERRQ(ierr);
1076 
1077   adapt->always_accept      = PETSC_FALSE;
1078   adapt->safety             = 0.9;
1079   adapt->reject_safety      = 0.5;
1080   adapt->clip[0]            = 0.1;
1081   adapt->clip[1]            = 10.;
1082   adapt->dt_min             = 1e-20;
1083   adapt->dt_max             = 1e+20;
1084   adapt->ignore_max         = -1.0;
1085   adapt->glee_use_local     = PETSC_TRUE;
1086   adapt->scale_solve_failed = 0.25;
1087   /* these two safety factors are not public, and they are used only in the TS_EXACTFINALTIME_MATCHSTEP case
1088      to prevent from situations were unreasonably small time steps are taken in order to match the final time */
1089   adapt->matchstepfac[0]    = 0.01; /* allow 1% step size increase in the last step */
1090   adapt->matchstepfac[1]    = 2.0;  /* halve last step if it is greater than what remains divided this factor */
1091   adapt->wnormtype          = NORM_2;
1092   adapt->timestepjustdecreased_delay = 0;
1093 
1094   *inadapt = adapt;
1095   PetscFunctionReturn(0);
1096 }
1097