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