xref: /petsc/src/ts/adapt/interface/tsadapt.c (revision 1566a47f5f7ddc4d41547989035e2da0a3965616)
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_None(TSAdapt);
10 PETSC_EXTERN PetscErrorCode TSAdaptCreate_Basic(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(TSADAPTNONE, TSAdaptCreate_None);CHKERRQ(ierr);
73   ierr = TSAdaptRegister(TSADAPTBASIC,TSAdaptCreate_Basic);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()  */
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 - optional, 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   PetscInt       ncandidates = adapt->candidates.n;
558   PetscInt       scheme = 0;
559   PetscReal      wlte = -1.0;
560 
561   PetscFunctionBegin;
562   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
563   PetscValidHeaderSpecific(ts,TS_CLASSID,2);
564   if (next_sc) PetscValidIntPointer(next_sc,4);
565   PetscValidPointer(next_h,5);
566   PetscValidIntPointer(accept,6);
567   if (next_sc) *next_sc = 0;
568 
569   /* Do not mess with adaptivity while handling events*/
570   if (ts->event && ts->event->status != TSEVENT_NONE) {
571     *next_h = h;
572     *accept = PETSC_TRUE;
573     PetscFunctionReturn(0);
574   }
575 
576   ierr = (*adapt->ops->choose)(adapt,ts,h,&scheme,next_h,accept,&wlte);CHKERRQ(ierr);
577   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);
578   if (*next_h < 0) SETERRQ1(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_OUTOFRANGE,"Computed step size %g must be positive",(double)*next_h);
579   if (next_sc) *next_sc = scheme;
580 
581   if (*accept && ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP) {
582     /* Reduce time step if it overshoots max time */
583     if (ts->ptime + ts->time_step + *next_h >= ts->max_time) {
584       PetscReal next_dt = ts->max_time - (ts->ptime + ts->time_step);
585       if (next_dt > PETSC_SMALL) *next_h = next_dt;
586       else ts->reason = TS_CONVERGED_TIME;
587     }
588   }
589 
590   if (adapt->monitor) {
591     const char *sc_name = (scheme < ncandidates) ? adapt->candidates.name[scheme] : "";
592     ierr = PetscViewerASCIIAddTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
593     if (wlte < 0) {
594       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,scheme,sc_name,(double)*next_h);CHKERRQ(ierr);
595     } else {
596       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,scheme,sc_name,(double)*next_h);CHKERRQ(ierr);
597     }
598     ierr = PetscViewerASCIISubtractTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
599   }
600   PetscFunctionReturn(0);
601 }
602 
603 #undef __FUNCT__
604 #define __FUNCT__ "TSAdaptCheckStage"
605 /*@
606    TSAdaptCheckStage - checks whether to accept a stage, (e.g. reject and change time step size if nonlinear solve fails)
607 
608    Collective
609 
610    Input Arguments:
611 +  adapt - adaptive controller context
612 .  ts - time stepper
613 .  t - Current simulation time
614 -  Y - Current solution vector
615 
616    Output Arguments:
617 .  accept - PETSC_TRUE to accept the stage, PETSC_FALSE to reject
618 
619    Level: developer
620 
621 .seealso:
622 @*/
623 PetscErrorCode TSAdaptCheckStage(TSAdapt adapt,TS ts,PetscReal t,Vec Y,PetscBool *accept)
624 {
625   PetscErrorCode      ierr;
626   SNESConvergedReason snesreason = SNES_CONVERGED_ITERATING;
627 
628   PetscFunctionBegin;
629   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
630   PetscValidHeaderSpecific(ts,TS_CLASSID,2);
631   PetscValidIntPointer(accept,3);
632 
633   if (ts->snes) {ierr = SNESGetConvergedReason(ts->snes,&snesreason);CHKERRQ(ierr);}
634   if (snesreason < 0) {
635     *accept = PETSC_FALSE;
636     if (++ts->num_snes_failures >= ts->max_snes_failures && ts->max_snes_failures > 0) {
637       ts->reason = TS_DIVERGED_NONLINEAR_SOLVE;
638       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);
639       if (adapt->monitor) {
640         ierr = PetscViewerASCIIAddTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
641         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);
642         ierr = PetscViewerASCIISubtractTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
643       }
644     }
645   } else {
646     *accept = PETSC_TRUE;
647     ierr = TSFunctionDomainError(ts,t,Y,accept);CHKERRQ(ierr);
648     if(*accept && adapt->checkstage) {
649       ierr = (*adapt->checkstage)(adapt,ts,t,Y,accept);CHKERRQ(ierr);
650     }
651   }
652 
653   if(!(*accept) && !ts->reason) {
654     PetscReal dt,new_dt;
655     ierr = TSGetTimeStep(ts,&dt);CHKERRQ(ierr);
656     new_dt = dt * adapt->scale_solve_failed;
657     ierr = TSSetTimeStep(ts,new_dt);CHKERRQ(ierr);
658     if (adapt->monitor) {
659       ierr = PetscViewerASCIIAddTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
660       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);
661       ierr = PetscViewerASCIISubtractTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
662     }
663   }
664   PetscFunctionReturn(0);
665 }
666 
667 #undef __FUNCT__
668 #define __FUNCT__ "TSAdaptCreate"
669 /*@
670   TSAdaptCreate - create an adaptive controller context for time stepping
671 
672   Collective on MPI_Comm
673 
674   Input Parameter:
675 . comm - The communicator
676 
677   Output Parameter:
678 . adapt - new TSAdapt object
679 
680   Level: developer
681 
682   Notes:
683   TSAdapt creation is handled by TS, so users should not need to call this function.
684 
685 .keywords: TSAdapt, create
686 .seealso: TSGetAdapt(), TSAdaptSetType(), TSAdaptDestroy()
687 @*/
688 PetscErrorCode  TSAdaptCreate(MPI_Comm comm,TSAdapt *inadapt)
689 {
690   PetscErrorCode ierr;
691   TSAdapt        adapt;
692 
693   PetscFunctionBegin;
694   PetscValidPointer(inadapt,1);
695   *inadapt = NULL;
696   ierr = TSAdaptInitializePackage();CHKERRQ(ierr);
697 
698   ierr = PetscHeaderCreate(adapt,TSADAPT_CLASSID,"TSAdapt","Time stepping adaptivity","TS",comm,TSAdaptDestroy,TSAdaptView);CHKERRQ(ierr);
699 
700   adapt->dt_min             = 1e-20;
701   adapt->dt_max             = 1e50;
702   adapt->scale_solve_failed = 0.25;
703   adapt->wnormtype          = NORM_2;
704 
705   *inadapt = adapt;
706   PetscFunctionReturn(0);
707 }
708