xref: /petsc/src/ts/adapt/interface/tsadapt.c (revision 2205254efee3a00a594e5e2a3a70f74dcb40bc03)
1 
2 #include <petsc-private/tsimpl.h> /*I  "petscts.h" I*/
3 
4 static PetscFunctionList TSAdaptList;
5 static PetscBool         TSAdaptPackageInitialized;
6 static PetscBool         TSAdaptRegisterAllCalled;
7 static PetscClassId      TSADAPT_CLASSID;
8 
9 EXTERN_C_BEGIN
10 PetscErrorCode  TSAdaptCreate_Basic(TSAdapt);
11 PetscErrorCode  TSAdaptCreate_None(TSAdapt);
12 PetscErrorCode  TSAdaptCreate_CFL(TSAdapt);
13 EXTERN_C_END
14 
15 #undef __FUNCT__
16 #define __FUNCT__ "TSAdaptRegister"
17 /*@C
18    TSAdaptRegister - see TSAdaptRegisterDynamic()
19 
20    Level: advanced
21 @*/
22 PetscErrorCode  TSAdaptRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(TSAdapt))
23 {
24   PetscErrorCode ierr;
25   char           fullname[PETSC_MAX_PATH_LEN];
26 
27   PetscFunctionBegin;
28   ierr = PetscFunctionListConcat(path,name,fullname);CHKERRQ(ierr);
29   ierr = PetscFunctionListAdd(PETSC_COMM_WORLD,&TSAdaptList,sname,fullname,(void(*)(void))function);CHKERRQ(ierr);
30   PetscFunctionReturn(0);
31 }
32 
33 #undef __FUNCT__
34 #define __FUNCT__ "TSAdaptRegisterAll"
35 /*@C
36   TSAdaptRegisterAll - Registers all of the adaptivity schemes in TSAdapt
37 
38   Not Collective
39 
40   Level: advanced
41 
42 .keywords: TSAdapt, register, all
43 
44 .seealso: TSAdaptRegisterDestroy()
45 @*/
46 PetscErrorCode  TSAdaptRegisterAll(const char path[])
47 {
48   PetscErrorCode ierr;
49 
50   PetscFunctionBegin;
51   ierr = TSAdaptRegisterDynamic(TSADAPTBASIC,path,"TSAdaptCreate_Basic",TSAdaptCreate_Basic);CHKERRQ(ierr);
52   ierr = TSAdaptRegisterDynamic(TSADAPTNONE, path,"TSAdaptCreate_None", TSAdaptCreate_None);CHKERRQ(ierr);
53   ierr = TSAdaptRegisterDynamic(TSADAPTCFL,  path,"TSAdaptCreate_CFL",  TSAdaptCreate_CFL);CHKERRQ(ierr);
54   PetscFunctionReturn(0);
55 }
56 
57 #undef __FUNCT__
58 #define __FUNCT__ "TSAdaptFinalizePackage"
59 /*@C
60   TSFinalizePackage - This function destroys everything in the TS package. It is
61   called from PetscFinalize().
62 
63   Level: developer
64 
65 .keywords: Petsc, destroy, package
66 .seealso: PetscFinalize()
67 @*/
68 PetscErrorCode  TSAdaptFinalizePackage(void)
69 {
70   PetscFunctionBegin;
71   TSAdaptPackageInitialized = PETSC_FALSE;
72   TSAdaptRegisterAllCalled  = PETSC_FALSE;
73   TSAdaptList               = PETSC_NULL;
74   PetscFunctionReturn(0);
75 }
76 
77 #undef __FUNCT__
78 #define __FUNCT__ "TSAdaptInitializePackage"
79 /*@C
80   TSAdaptInitializePackage - This function initializes everything in the TSAdapt package. It is
81   called from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to
82   TSCreate_GL() when using static libraries.
83 
84   Input Parameter:
85   path - The dynamic library path, or PETSC_NULL
86 
87   Level: developer
88 
89 .keywords: TSAdapt, initialize, package
90 .seealso: PetscInitialize()
91 @*/
92 PetscErrorCode  TSAdaptInitializePackage(const char path[])
93 {
94   PetscErrorCode ierr;
95 
96   PetscFunctionBegin;
97   if (TSAdaptPackageInitialized) PetscFunctionReturn(0);
98   TSAdaptPackageInitialized = PETSC_TRUE;
99   ierr = PetscClassIdRegister("TSAdapt",&TSADAPT_CLASSID);CHKERRQ(ierr);
100   ierr = TSAdaptRegisterAll(path);CHKERRQ(ierr);
101   ierr = PetscRegisterFinalize(TSAdaptFinalizePackage);CHKERRQ(ierr);
102   PetscFunctionReturn(0);
103 }
104 
105 #undef __FUNCT__
106 #define __FUNCT__ "TSAdaptRegisterDestroy"
107 /*@C
108    TSAdaptRegisterDestroy - Frees the list of adaptivity schemes that were registered by TSAdaptRegister()/TSAdaptRegisterDynamic().
109 
110    Not Collective
111 
112    Level: advanced
113 
114 .keywords: TSAdapt, register, destroy
115 .seealso: TSAdaptRegister(), TSAdaptRegisterAll(), TSAdaptRegisterDynamic()
116 @*/
117 PetscErrorCode  TSAdaptRegisterDestroy(void)
118 {
119   PetscErrorCode ierr;
120 
121   PetscFunctionBegin;
122   ierr = PetscFunctionListDestroy(&TSAdaptList);CHKERRQ(ierr);
123   TSAdaptRegisterAllCalled = PETSC_FALSE;
124   PetscFunctionReturn(0);
125 }
126 
127 
128 #undef __FUNCT__
129 #define __FUNCT__ "TSAdaptSetType"
130 PetscErrorCode  TSAdaptSetType(TSAdapt adapt,TSAdaptType type)
131 {
132   PetscErrorCode ierr,(*r)(TSAdapt);
133 
134   PetscFunctionBegin;
135   ierr = PetscFunctionListFind(((PetscObject)adapt)->comm,TSAdaptList,type,PETSC_TRUE,(void(**)(void))&r);CHKERRQ(ierr);
136   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown TSAdapt type \"%s\" given",type);
137   if (((PetscObject)adapt)->type_name) {ierr = (*adapt->ops->destroy)(adapt);CHKERRQ(ierr);}
138   ierr = (*r)(adapt);CHKERRQ(ierr);
139   ierr = PetscObjectChangeTypeName((PetscObject)adapt,type);CHKERRQ(ierr);
140   PetscFunctionReturn(0);
141 }
142 
143 #undef __FUNCT__
144 #define __FUNCT__ "TSAdaptSetOptionsPrefix"
145 PetscErrorCode  TSAdaptSetOptionsPrefix(TSAdapt adapt,const char prefix[])
146 {
147   PetscErrorCode ierr;
148 
149   PetscFunctionBegin;
150   ierr = PetscObjectSetOptionsPrefix((PetscObject)adapt,prefix);CHKERRQ(ierr);
151   PetscFunctionReturn(0);
152 }
153 
154 #undef __FUNCT__
155 #define __FUNCT__ "TSAdaptLoad"
156 /*@C
157   TSAdaptLoad - Loads a TSAdapt that has been stored in binary  with TSAdaptView().
158 
159   Collective on PetscViewer
160 
161   Input Parameters:
162 + newdm - the newly loaded TSAdapt, this needs to have been created with TSAdaptCreate() or
163            some related function before a call to TSAdaptLoad().
164 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or
165            HDF5 file viewer, obtained from PetscViewerHDF5Open()
166 
167    Level: intermediate
168 
169   Notes:
170    The type is determined by the data in the file, any type set into the TSAdapt before this call is ignored.
171 
172   Notes for advanced users:
173   Most users should not need to know the details of the binary storage
174   format, since TSAdaptLoad() and TSAdaptView() completely hide these details.
175   But for anyone who's interested, the standard binary matrix storage
176   format is
177 .vb
178      has not yet been determined
179 .ve
180 
181 .seealso: PetscViewerBinaryOpen(), TSAdaptView(), MatLoad(), VecLoad()
182 @*/
183 PetscErrorCode  TSAdaptLoad(TSAdapt tsadapt, PetscViewer viewer)
184 {
185   PetscErrorCode ierr;
186   PetscBool      isbinary;
187   char           type[256];
188 
189   PetscFunctionBegin;
190   PetscValidHeaderSpecific(tsadapt,TSADAPT_CLASSID,1);
191   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
192   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
193   if (!isbinary) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen()");
194 
195   ierr = PetscViewerBinaryRead(viewer,type,256,PETSC_CHAR);CHKERRQ(ierr);
196   ierr = TSAdaptSetType(tsadapt, type);CHKERRQ(ierr);
197   if (tsadapt->ops->load) {
198     ierr = (*tsadapt->ops->load)(tsadapt,viewer);CHKERRQ(ierr);
199   }
200   PetscFunctionReturn(0);
201 }
202 
203 #undef __FUNCT__
204 #define __FUNCT__ "TSAdaptView"
205 PetscErrorCode  TSAdaptView(TSAdapt adapt,PetscViewer viewer)
206 {
207   PetscErrorCode ierr;
208   PetscBool      iascii,isbinary;
209 
210   PetscFunctionBegin;
211   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
212   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
213   if (iascii) {
214     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)adapt,viewer,"TSAdapt Object");CHKERRQ(ierr);
215     ierr = PetscViewerASCIIPrintf(viewer,"  number of candidates %D\n",adapt->candidates.n);CHKERRQ(ierr);
216     if (adapt->ops->view) {
217       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
218       ierr = (*adapt->ops->view)(adapt,viewer);CHKERRQ(ierr);
219       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
220     }
221   } else if (isbinary) {
222     char type[256];
223 
224     /* need to save FILE_CLASS_ID for adapt class */
225     ierr = PetscStrncpy(type,((PetscObject)adapt)->type_name,256);CHKERRQ(ierr);
226     ierr = PetscViewerBinaryWrite(viewer,type,256,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr);
227   } else if (adapt->ops->view) {
228     ierr = (*adapt->ops->view)(adapt,viewer);CHKERRQ(ierr);
229   }
230   PetscFunctionReturn(0);
231 }
232 
233 #undef __FUNCT__
234 #define __FUNCT__ "TSAdaptDestroy"
235 PetscErrorCode  TSAdaptDestroy(TSAdapt *adapt)
236 {
237   PetscErrorCode ierr;
238 
239   PetscFunctionBegin;
240   if (!*adapt) PetscFunctionReturn(0);
241   PetscValidHeaderSpecific(*adapt,TSADAPT_CLASSID,1);
242   if (--((PetscObject)(*adapt))->refct > 0) {*adapt = 0; PetscFunctionReturn(0);}
243   if ((*adapt)->ops->destroy) {ierr = (*(*adapt)->ops->destroy)(*adapt);CHKERRQ(ierr);}
244   ierr = PetscViewerDestroy(&(*adapt)->monitor);CHKERRQ(ierr);
245   ierr = PetscHeaderDestroy(adapt);CHKERRQ(ierr);
246   PetscFunctionReturn(0);
247 }
248 
249 #undef __FUNCT__
250 #define __FUNCT__ "TSAdaptSetMonitor"
251 /*@
252    TSAdaptSetMonitor - Monitor the choices made by the adaptive controller
253 
254    Collective on TSAdapt
255 
256    Input Arguments:
257 +  adapt - adaptive controller context
258 -  flg - PETSC_TRUE to active a monitor, PETSC_FALSE to disable
259 
260    Level: intermediate
261 
262 .seealso: TSAdaptChoose()
263 @*/
264 PetscErrorCode TSAdaptSetMonitor(TSAdapt adapt,PetscBool flg)
265 {
266   PetscErrorCode ierr;
267 
268   PetscFunctionBegin;
269   if (flg) {
270     if (!adapt->monitor) {ierr = PetscViewerASCIIOpen(((PetscObject)adapt)->comm,"stdout",&adapt->monitor);CHKERRQ(ierr);}
271   } else {
272     ierr = PetscViewerDestroy(&adapt->monitor);CHKERRQ(ierr);
273   }
274   PetscFunctionReturn(0);
275 }
276 
277 #undef __FUNCT__
278 #define __FUNCT__ "TSAdaptSetCheckStage"
279 /*@C
280    TSAdaptSetCheckStage - set a callback to check convergence for a stage
281 
282    Logically collective on TSAdapt
283 
284    Input Arguments:
285 +  adapt - adaptive controller context
286 -  func - stage check function
287 
288    Arguments of func:
289 $  PetscErrorCode func(TSAdapt adapt,TS ts,PetscBool *accept)
290 
291 +  adapt - adaptive controller context
292 .  ts - time stepping context
293 -  accept - pending choice of whether to accept, can be modified by this routine
294 
295    Level: advanced
296 
297 .seealso: TSAdaptChoose()
298 @*/
299 PetscErrorCode TSAdaptSetCheckStage(TSAdapt adapt,PetscErrorCode (*func)(TSAdapt,TS,PetscBool*))
300 {
301 
302   PetscFunctionBegin;
303   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
304   adapt->ops->checkstage = func;
305   PetscFunctionReturn(0);
306 }
307 
308 #undef __FUNCT__
309 #define __FUNCT__ "TSAdaptSetStepLimits"
310 /*@
311    TSAdaptSetStepLimits - Set minimum and maximum step sizes to be considered by the controller
312 
313    Logically Collective
314 
315    Input Arguments:
316 +  adapt - time step adaptivity context, usually gotten with TSGetTSAdapt()
317 .  hmin - minimum time step
318 -  hmax - maximum time step
319 
320    Options Database Keys:
321 +  -ts_adapt_dt_min - minimum time step
322 -  -ts_adapt_dt_max - maximum time step
323 
324    Level: intermediate
325 
326 .seealso: TSAdapt
327 @*/
328 PetscErrorCode TSAdaptSetStepLimits(TSAdapt adapt,PetscReal hmin,PetscReal hmax)
329 {
330 
331   PetscFunctionBegin;
332   if (hmin != PETSC_DECIDE) adapt->dt_min = hmin;
333   if (hmax != PETSC_DECIDE) adapt->dt_max = hmax;
334   PetscFunctionReturn(0);
335 }
336 
337 #undef __FUNCT__
338 #define __FUNCT__ "TSAdaptSetFromOptions"
339 /*@
340    TSAdaptSetFromOptions - Sets various TSAdapt parameters from user options.
341 
342    Collective on TSAdapt
343 
344    Input Parameter:
345 .  adapt - the TSAdapt context
346 
347    Options Database Keys:
348 .  -ts_adapt_type <type> - basic
349 
350    Level: advanced
351 
352    Notes:
353    This function is automatically called by TSSetFromOptions()
354 
355 .keywords: TS, TSGetTSAdapt(), TSAdaptSetType()
356 
357 .seealso: TSGetType()
358 @*/
359 PetscErrorCode  TSAdaptSetFromOptions(TSAdapt adapt)
360 {
361   PetscErrorCode ierr;
362   char           type[256] = TSADAPTBASIC;
363   PetscBool      set,flg;
364 
365   PetscFunctionBegin;
366   /* This should use PetscOptionsBegin() if/when this becomes an object used outside of TS, but currently this
367   * function can only be called from inside TSSetFromOptions_GL()  */
368   ierr = PetscOptionsHead("TS Adaptivity options");CHKERRQ(ierr);
369   ierr = PetscOptionsList("-ts_adapt_type","Algorithm to use for adaptivity","TSAdaptSetType",TSAdaptList,
370                           ((PetscObject)adapt)->type_name ? ((PetscObject)adapt)->type_name : type,type,sizeof(type),&flg);CHKERRQ(ierr);
371   if (flg || !((PetscObject)adapt)->type_name) {
372     ierr = TSAdaptSetType(adapt,type);CHKERRQ(ierr);
373   }
374   if (adapt->ops->setfromoptions) {ierr = (*adapt->ops->setfromoptions)(adapt);CHKERRQ(ierr);}
375   ierr = PetscOptionsReal("-ts_adapt_dt_min","Minimum time step considered","TSAdaptSetStepLimits",adapt->dt_min,&adapt->dt_min,PETSC_NULL);CHKERRQ(ierr);
376   ierr = PetscOptionsReal("-ts_adapt_dt_max","Maximum time step considered","TSAdaptSetStepLimits",adapt->dt_max,&adapt->dt_max,PETSC_NULL);CHKERRQ(ierr);
377   ierr = PetscOptionsReal("-ts_adapt_scale_solve_failed","Scale step by this factor if solve fails","",adapt->scale_solve_failed,&adapt->scale_solve_failed,PETSC_NULL);CHKERRQ(ierr);
378   ierr = PetscOptionsBool("-ts_adapt_monitor","Print choices made by adaptive controller","TSAdaptSetMonitor",adapt->monitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr);
379   if (set) {ierr = TSAdaptSetMonitor(adapt,flg);CHKERRQ(ierr);}
380   ierr = PetscOptionsTail();CHKERRQ(ierr);
381   PetscFunctionReturn(0);
382 }
383 
384 #undef __FUNCT__
385 #define __FUNCT__ "TSAdaptCandidatesClear"
386 /*@
387    TSAdaptCandidatesClear - clear any previously set candidate schemes
388 
389    Logically Collective
390 
391    Input Argument:
392 .  adapt - adaptive controller
393 
394    Level: developer
395 
396 .seealso: TSAdapt, TSAdaptCreate(), TSAdaptCandidateAdd(), TSAdaptChoose()
397 @*/
398 PetscErrorCode TSAdaptCandidatesClear(TSAdapt adapt)
399 {
400   PetscErrorCode ierr;
401 
402   PetscFunctionBegin;
403   ierr = PetscMemzero(&adapt->candidates,sizeof(adapt->candidates));CHKERRQ(ierr);
404   PetscFunctionReturn(0);
405 }
406 
407 #undef __FUNCT__
408 #define __FUNCT__ "TSAdaptCandidateAdd"
409 /*@C
410    TSAdaptCandidateAdd - add a candidate scheme for the adaptive controller to select from
411 
412    Logically Collective
413 
414    Input Arguments:
415 +  adapt - time step adaptivity context, obtained with TSGetTSAdapt() or TSAdaptCreate()
416 .  name - name of the candidate scheme to add
417 .  order - order of the candidate scheme
418 .  stageorder - stage order of the candidate scheme
419 .  ccfl - stability coefficient relative to explicit Euler, used for CFL constraints
420 .  cost - relative measure of the amount of work required for the candidate scheme
421 -  inuse - indicates that this scheme is the one currently in use, this flag can only be set for one scheme
422 
423    Note:
424    This routine is not available in Fortran.
425 
426    Level: developer
427 
428 .seealso: TSAdaptCandidatesClear(), TSAdaptChoose()
429 @*/
430 PetscErrorCode TSAdaptCandidateAdd(TSAdapt adapt,const char name[],PetscInt order,PetscInt stageorder,PetscReal ccfl,PetscReal cost,PetscBool inuse)
431 {
432   PetscInt c;
433 
434   PetscFunctionBegin;
435   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
436   if (order < 1) SETERRQ1(((PetscObject)adapt)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Classical order %D must be a positive integer",order);
437   if (inuse) {
438     if (adapt->candidates.inuse_set) SETERRQ(((PetscObject)adapt)->comm,PETSC_ERR_ARG_WRONGSTATE,"Cannot set the inuse method twice, maybe forgot to call TSAdaptCandidatesClear()");
439     adapt->candidates.inuse_set = PETSC_TRUE;
440   }
441   /* first slot if this is the current scheme, otherwise the next available slot */
442   c = inuse ? 0 : !adapt->candidates.inuse_set + adapt->candidates.n;
443 
444   adapt->candidates.name[c]       = name;
445   adapt->candidates.order[c]      = order;
446   adapt->candidates.stageorder[c] = stageorder;
447   adapt->candidates.ccfl[c]       = ccfl;
448   adapt->candidates.cost[c]       = cost;
449   adapt->candidates.n++;
450   PetscFunctionReturn(0);
451 }
452 
453 #undef __FUNCT__
454 #define __FUNCT__ "TSAdaptCandidatesGet"
455 /*@C
456    TSAdaptCandidatesGet - Get the list of candidate orders of accuracy and cost
457 
458    Not Collective
459 
460    Input Arguments:
461 .  adapt - time step adaptivity context
462 
463    Output Arguments:
464 +  n - number of candidate schemes, always at least 1
465 .  order - the order of each candidate scheme
466 .  stageorder - the stage order of each candidate scheme
467 .  ccfl - the CFL coefficient of each scheme
468 -  cost - the relative cost of each scheme
469 
470    Level: developer
471 
472    Note:
473    The current scheme is always returned in the first slot
474 
475 .seealso: TSAdaptCandidatesClear(), TSAdaptCandidateAdd(), TSAdaptChoose()
476 @*/
477 PetscErrorCode TSAdaptCandidatesGet(TSAdapt adapt,PetscInt *n,const PetscInt **order,const PetscInt **stageorder,const PetscReal **ccfl,const PetscReal **cost)
478 {
479   PetscFunctionBegin;
480   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
481   if (n) *n = adapt->candidates.n;
482   if (order) *order = adapt->candidates.order;
483   if (stageorder) *stageorder = adapt->candidates.stageorder;
484   if (ccfl) *ccfl = adapt->candidates.ccfl;
485   if (cost) *cost = adapt->candidates.cost;
486   PetscFunctionReturn(0);
487 }
488 
489 #undef __FUNCT__
490 #define __FUNCT__ "TSAdaptChoose"
491 /*@C
492    TSAdaptChoose - choose which method and step size to use for the next step
493 
494    Logically Collective
495 
496    Input Arguments:
497 +  adapt - adaptive contoller
498 -  h - current step size
499 
500    Output Arguments:
501 +  next_sc - scheme to use for the next step
502 .  next_h - step size to use for the next step
503 -  accept - PETSC_TRUE to accept the current step, PETSC_FALSE to repeat the current step with the new step size
504 
505    Note:
506    The input value of parameter accept is retained from the last time step, so it will be PETSC_FALSE if the step is
507    being retried after an initial rejection.
508 
509    Level: developer
510 
511 .seealso: TSAdapt, TSAdaptCandidatesClear(), TSAdaptCandidateAdd()
512 @*/
513 PetscErrorCode TSAdaptChoose(TSAdapt adapt,TS ts,PetscReal h,PetscInt *next_sc,PetscReal *next_h,PetscBool *accept)
514 {
515   PetscErrorCode ierr;
516   PetscReal      wlte = -1.0;
517 
518   PetscFunctionBegin;
519   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
520   PetscValidHeaderSpecific(ts,TS_CLASSID,2);
521   PetscValidIntPointer(next_sc,4);
522   PetscValidPointer(next_h,5);
523   PetscValidIntPointer(accept,6);
524   if (adapt->candidates.n < 1) SETERRQ1(((PetscObject)adapt)->comm,PETSC_ERR_ARG_WRONGSTATE,"%D candidates have been registered",adapt->candidates.n);
525   if (!adapt->candidates.inuse_set) SETERRQ1(((PetscObject)adapt)->comm,PETSC_ERR_ARG_WRONGSTATE,"The current in-use scheme is not among the %D candidates",adapt->candidates.n);
526   ierr = (*adapt->ops->choose)(adapt,ts,h,next_sc,next_h,accept,&wlte);CHKERRQ(ierr);
527   if (*accept && ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP) {
528     /* Reduce time step if it overshoots max time */
529     PetscReal max_time = ts->max_time;
530     PetscReal next_dt  = 0.0;
531     if (ts->ptime + ts->time_step + *next_h >= max_time) {
532       next_dt = max_time - (ts->ptime + ts->time_step);
533       if (next_dt > PETSC_SMALL) *next_h = next_dt;
534       else ts->reason = TS_CONVERGED_TIME;
535     }
536   }
537   if (*next_sc < 0 || adapt->candidates.n <= *next_sc) SETERRQ2(((PetscObject)adapt)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Chosen scheme %D not in valid range 0..%D",*next_sc,adapt->candidates.n-1);
538   if (!(*next_h > 0.)) SETERRQ1(((PetscObject)adapt)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Computed step size %G must be positive",*next_h);
539 
540   if (adapt->monitor) {
541     ierr = PetscViewerASCIIAddTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
542     if (wlte < 0) {
543       ierr = PetscViewerASCIIPrintf(adapt->monitor,"    TSAdapt '%s': step %3D %s t=%-11g+%10.3e family='%s' scheme=%D:'%s' dt=%-10g\n",((PetscObject)adapt)->type_name,ts->steps,*accept ? "accepted" : "rejected",(double)ts->ptime,(double)h,((PetscObject)ts)->type_name,*next_sc,adapt->candidates.name[*next_sc],(double)*next_h);CHKERRQ(ierr);
544     } else {
545       ierr = PetscViewerASCIIPrintf(adapt->monitor,"    TSAdapt '%s': step %3D %s t=%-11g+%10.3e wlte=%5.3g family='%s' scheme=%D:'%s' dt=%-10.3e\n",((PetscObject)adapt)->type_name,ts->steps,*accept ? "accepted" : "rejected",(double)ts->ptime,(double)h,(double)wlte,((PetscObject)ts)->type_name,*next_sc,adapt->candidates.name[*next_sc],(double)*next_h);CHKERRQ(ierr);
546     }
547     ierr = PetscViewerASCIISubtractTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
548   }
549   PetscFunctionReturn(0);
550 }
551 
552 #undef __FUNCT__
553 #define __FUNCT__ "TSAdaptCheckStage"
554 /*@
555    TSAdaptCheckStage - checks whether to accept a stage, (e.g. reject and change time step size if nonlinear solve fails)
556 
557    Collective
558 
559    Input Arguments:
560 +  adapt - adaptive controller context
561 -  ts - time stepper
562 
563    Output Arguments:
564 .  accept - PETSC_TRUE to accept the stage, PETSC_FALSE to reject
565 
566    Level: developer
567 
568 .seealso:
569 @*/
570 PetscErrorCode TSAdaptCheckStage(TSAdapt adapt,TS ts,PetscBool *accept)
571 {
572   PetscErrorCode      ierr;
573   SNES                snes;
574   SNESConvergedReason snesreason;
575 
576   PetscFunctionBegin;
577   *accept = PETSC_TRUE;
578   ierr    = TSGetSNES(ts,&snes);CHKERRQ(ierr);
579   ierr    = SNESGetConvergedReason(snes,&snesreason);CHKERRQ(ierr);
580   if (snesreason < 0) {
581     PetscReal dt,new_dt;
582     *accept = PETSC_FALSE;
583     ierr    = TSGetTimeStep(ts,&dt);CHKERRQ(ierr);
584     if (++ts->num_snes_failures >= ts->max_snes_failures && ts->max_snes_failures > 0) {
585       ts->reason = TS_DIVERGED_NONLINEAR_SOLVE;
586       ierr = PetscInfo2(ts,"Step=%D, nonlinear solve solve failures %D greater than current TS allowed, stopping solve\n",ts->steps,ts->num_snes_failures);CHKERRQ(ierr);
587       if (adapt->monitor) {
588         ierr = PetscViewerASCIIAddTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
589         ierr = PetscViewerASCIIPrintf(adapt->monitor,"    TSAdapt '%s': step %3D stage rejected t=%-11g+%10.3e, %D failures exceeds current TS allowed\n",((PetscObject)adapt)->type_name,ts->steps,(double)ts->ptime,dt,ts->num_snes_failures);CHKERRQ(ierr);
590         ierr = PetscViewerASCIISubtractTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
591       }
592     } else {
593       new_dt = dt*adapt->scale_solve_failed;
594       ierr   = TSSetTimeStep(ts,new_dt);CHKERRQ(ierr);
595       if (adapt->monitor) {
596         ierr = PetscViewerASCIIAddTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
597         ierr = PetscViewerASCIIPrintf(adapt->monitor,"    TSAdapt '%s': step %3D stage rejected t=%-11g+%10.3e retrying with dt=%-10.3e\n",((PetscObject)adapt)->type_name,ts->steps,(double)ts->ptime,(double)dt,(double)new_dt);CHKERRQ(ierr);
598         ierr = PetscViewerASCIISubtractTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
599       }
600     }
601   }
602   if (adapt->ops->checkstage) {ierr = (*adapt->ops->checkstage)(adapt,ts,accept);CHKERRQ(ierr);}
603   PetscFunctionReturn(0);
604 }
605 
606 
607 
608 #undef __FUNCT__
609 #define __FUNCT__ "TSAdaptCreate"
610 /*@
611   TSAdaptCreate - create an adaptive controller context for time stepping
612 
613   Collective on MPI_Comm
614 
615   Input Parameter:
616 . comm - The communicator
617 
618   Output Parameter:
619 . adapt - new TSAdapt object
620 
621   Level: developer
622 
623   Notes:
624   TSAdapt creation is handled by TS, so users should not need to call this function.
625 
626 .keywords: TSAdapt, create
627 .seealso: TSGetTSAdapt(), TSAdaptSetType(), TSAdaptDestroy()
628 @*/
629 PetscErrorCode  TSAdaptCreate(MPI_Comm comm,TSAdapt *inadapt)
630 {
631   PetscErrorCode ierr;
632   TSAdapt        adapt;
633 
634   PetscFunctionBegin;
635   *inadapt = 0;
636   ierr     = PetscHeaderCreate(adapt,_p_TSAdapt,struct _TSAdaptOps,TSADAPT_CLASSID,0,"TSAdapt","General Linear adaptivity","TS",comm,TSAdaptDestroy,TSAdaptView);CHKERRQ(ierr);
637 
638   adapt->dt_min             = 1e-20;
639   adapt->dt_max             = 1e50;
640   adapt->scale_solve_failed = 0.25;
641 
642   *inadapt = adapt;
643   PetscFunctionReturn(0);
644 }
645