xref: /petsc/src/ts/adapt/interface/tsadapt.c (revision e6d0a238963c2a97dd04845ea512b529992c7cdb)
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_GLEE(TSAdapt);
11 PETSC_EXTERN PetscErrorCode TSAdaptCreate_None(TSAdapt);
12 PETSC_EXTERN PetscErrorCode TSAdaptCreate_Basic(TSAdapt);
13 PETSC_EXTERN PetscErrorCode TSAdaptCreate_CFL(TSAdapt);
14 
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 /*@C
53   TSAdaptRegisterAll - Registers all of the adaptivity schemes in TSAdapt
54 
55   Not Collective
56 
57   Level: advanced
58 
59 .keywords: TSAdapt, register, all
60 
61 .seealso: TSAdaptRegisterDestroy()
62 @*/
63 PetscErrorCode  TSAdaptRegisterAll(void)
64 {
65   PetscErrorCode ierr;
66 
67   PetscFunctionBegin;
68   if (TSAdaptRegisterAllCalled) PetscFunctionReturn(0);
69   TSAdaptRegisterAllCalled = PETSC_TRUE;
70   ierr = TSAdaptRegister(TSADAPTGLEE ,TSAdaptCreate_GLEE);CHKERRQ(ierr);
71   ierr = TSAdaptRegister(TSADAPTNONE, TSAdaptCreate_None);CHKERRQ(ierr);
72   ierr = TSAdaptRegister(TSADAPTBASIC,TSAdaptCreate_Basic);CHKERRQ(ierr);
73   ierr = TSAdaptRegister(TSADAPTCFL,  TSAdaptCreate_CFL);CHKERRQ(ierr);
74   PetscFunctionReturn(0);
75 }
76 
77 /*@C
78   TSAdaptFinalizePackage - This function destroys everything in the TS package. It is
79   called from PetscFinalize().
80 
81   Level: developer
82 
83 .keywords: Petsc, destroy, package
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 PetscDLLibraryRegister() when using dynamic libraries, and on the first call to
100   TSCreate_GLLE() when using static libraries.
101 
102   Level: developer
103 
104 .keywords: TSAdapt, initialize, package
105 .seealso: PetscInitialize()
106 @*/
107 PetscErrorCode  TSAdaptInitializePackage(void)
108 {
109   PetscErrorCode ierr;
110 
111   PetscFunctionBegin;
112   if (TSAdaptPackageInitialized) PetscFunctionReturn(0);
113   TSAdaptPackageInitialized = PETSC_TRUE;
114   ierr = PetscClassIdRegister("TSAdapt",&TSADAPT_CLASSID);CHKERRQ(ierr);
115   ierr = TSAdaptRegisterAll();CHKERRQ(ierr);
116   ierr = PetscRegisterFinalize(TSAdaptFinalizePackage);CHKERRQ(ierr);
117   PetscFunctionReturn(0);
118 }
119 
120 /*@C
121   TSAdaptSetType - sets the approach used for the error adapter, currently there is only TSADAPTBASIC and TSADAPTNONE
122 
123   Logicially Collective on TSAdapt
124 
125   Input Parameter:
126 + adapt - the TS error adapter, most likely obtained with TSGetAdapt()
127 - type - either  TSADAPTBASIC or TSADAPTNONE
128 
129   Options Database:
130 .  -ts_adapt_type basic or none - to setting the adapter type
131 
132   Level: intermediate
133 
134 .keywords: TSAdapt, create
135 
136 .seealso: TSGetAdapt(), TSAdaptDestroy(), TSAdaptType, TSAdaptGetType()
137 @*/
138 PetscErrorCode  TSAdaptSetType(TSAdapt adapt,TSAdaptType type)
139 {
140   PetscBool      match;
141   PetscErrorCode ierr,(*r)(TSAdapt);
142 
143   PetscFunctionBegin;
144   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
145   ierr = PetscObjectTypeCompare((PetscObject)adapt,type,&match);CHKERRQ(ierr);
146   if (match) PetscFunctionReturn(0);
147   ierr = PetscFunctionListFind(TSAdaptList,type,&r);CHKERRQ(ierr);
148   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown TSAdapt type \"%s\" given",type);
149   if (adapt->ops->destroy) {ierr = (*adapt->ops->destroy)(adapt);CHKERRQ(ierr);}
150   ierr = PetscMemzero(adapt->ops,sizeof(struct _TSAdaptOps));CHKERRQ(ierr);
151   ierr = PetscObjectChangeTypeName((PetscObject)adapt,type);CHKERRQ(ierr);
152   ierr = (*r)(adapt);CHKERRQ(ierr);
153   PetscFunctionReturn(0);
154 }
155 
156 PetscErrorCode  TSAdaptSetOptionsPrefix(TSAdapt adapt,const char prefix[])
157 {
158   PetscErrorCode ierr;
159 
160   PetscFunctionBegin;
161   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
162   ierr = PetscObjectSetOptionsPrefix((PetscObject)adapt,prefix);CHKERRQ(ierr);
163   PetscFunctionReturn(0);
164 }
165 
166 /*@C
167   TSAdaptLoad - Loads a TSAdapt that has been stored in binary  with TSAdaptView().
168 
169   Collective on PetscViewer
170 
171   Input Parameters:
172 + newdm - the newly loaded TSAdapt, this needs to have been created with TSAdaptCreate() or
173            some related function before a call to TSAdaptLoad().
174 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or
175            HDF5 file viewer, obtained from PetscViewerHDF5Open()
176 
177    Level: intermediate
178 
179   Notes:
180    The type is determined by the data in the file, any type set into the TSAdapt before this call is ignored.
181 
182   Notes for advanced users:
183   Most users should not need to know the details of the binary storage
184   format, since TSAdaptLoad() and TSAdaptView() completely hide these details.
185   But for anyone who's interested, the standard binary matrix storage
186   format is
187 .vb
188      has not yet been determined
189 .ve
190 
191 .seealso: PetscViewerBinaryOpen(), TSAdaptView(), MatLoad(), VecLoad()
192 @*/
193 PetscErrorCode  TSAdaptLoad(TSAdapt adapt,PetscViewer viewer)
194 {
195   PetscErrorCode ierr;
196   PetscBool      isbinary;
197   char           type[256];
198 
199   PetscFunctionBegin;
200   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
201   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
202   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
203   if (!isbinary) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen()");
204 
205   ierr = PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);CHKERRQ(ierr);
206   ierr = TSAdaptSetType(adapt,type);CHKERRQ(ierr);
207   if (adapt->ops->load) {
208     ierr = (*adapt->ops->load)(adapt,viewer);CHKERRQ(ierr);
209   }
210   PetscFunctionReturn(0);
211 }
212 
213 PetscErrorCode  TSAdaptView(TSAdapt adapt,PetscViewer viewer)
214 {
215   PetscErrorCode ierr;
216   PetscBool      iascii,isbinary;
217 
218   PetscFunctionBegin;
219   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
220   if (!viewer) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)adapt),&viewer);CHKERRQ(ierr);}
221   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
222   PetscCheckSameComm(adapt,1,viewer,2);
223   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
224   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
225   if (iascii) {
226     ierr = PetscObjectPrintClassNamePrefixType((PetscObject)adapt,viewer);CHKERRQ(ierr);
227     ierr = PetscViewerASCIIPrintf(viewer,"  number of candidates %D\n",adapt->candidates.n);CHKERRQ(ierr);
228     ierr = PetscViewerASCIIPrintf(viewer,"  maximum allowed timestep %g minimum %g\n",adapt->dt_max,&adapt->dt_min);CHKERRQ(ierr);
229     if (adapt->ops->view) {
230       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
231       ierr = (*adapt->ops->view)(adapt,viewer);CHKERRQ(ierr);
232       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
233     }
234   } else if (isbinary) {
235     char type[256];
236 
237     /* need to save FILE_CLASS_ID for adapt class */
238     ierr = PetscStrncpy(type,((PetscObject)adapt)->type_name,256);CHKERRQ(ierr);
239     ierr = PetscViewerBinaryWrite(viewer,type,256,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr);
240   } else if (adapt->ops->view) {
241     ierr = (*adapt->ops->view)(adapt,viewer);CHKERRQ(ierr);
242   }
243   PetscFunctionReturn(0);
244 }
245 
246 /*@
247    TSAdaptReset - Resets a TSAdapt context.
248 
249    Collective on TS
250 
251    Input Parameter:
252 .  adapt - the TSAdapt context obtained from TSAdaptCreate()
253 
254    Level: developer
255 
256 .seealso: TSAdaptCreate(), TSAdaptDestroy()
257 @*/
258 PetscErrorCode  TSAdaptReset(TSAdapt adapt)
259 {
260   PetscErrorCode ierr;
261 
262   PetscFunctionBegin;
263   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
264   if (adapt->ops->reset) {ierr = (*adapt->ops->reset)(adapt);CHKERRQ(ierr);}
265   PetscFunctionReturn(0);
266 }
267 
268 PetscErrorCode  TSAdaptDestroy(TSAdapt *adapt)
269 {
270   PetscErrorCode ierr;
271 
272   PetscFunctionBegin;
273   if (!*adapt) PetscFunctionReturn(0);
274   PetscValidHeaderSpecific(*adapt,TSADAPT_CLASSID,1);
275   if (--((PetscObject)(*adapt))->refct > 0) {*adapt = NULL; PetscFunctionReturn(0);}
276 
277   ierr = TSAdaptReset(*adapt);CHKERRQ(ierr);
278 
279   if ((*adapt)->ops->destroy) {ierr = (*(*adapt)->ops->destroy)(*adapt);CHKERRQ(ierr);}
280   ierr = PetscViewerDestroy(&(*adapt)->monitor);CHKERRQ(ierr);
281   ierr = PetscHeaderDestroy(adapt);CHKERRQ(ierr);
282   PetscFunctionReturn(0);
283 }
284 
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 /*@C
314    TSAdaptSetCheckStage - set a callback to check convergence for a stage
315 
316    Logically collective on TSAdapt
317 
318    Input Arguments:
319 +  adapt - adaptive controller context
320 -  func - stage check function
321 
322    Arguments of func:
323 $  PetscErrorCode func(TSAdapt adapt,TS ts,PetscBool *accept)
324 
325 +  adapt - adaptive controller context
326 .  ts - time stepping context
327 -  accept - pending choice of whether to accept, can be modified by this routine
328 
329    Level: advanced
330 
331 .seealso: TSAdaptChoose()
332 @*/
333 PetscErrorCode TSAdaptSetCheckStage(TSAdapt adapt,PetscErrorCode (*func)(TSAdapt,TS,PetscReal,Vec,PetscBool*))
334 {
335 
336   PetscFunctionBegin;
337   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
338   adapt->checkstage = func;
339   PetscFunctionReturn(0);
340 }
341 
342 /*@
343    TSAdaptSetStepLimits - Set minimum and maximum step sizes to be considered by the controller
344 
345    Logically Collective
346 
347    Input Arguments:
348 +  adapt - time step adaptivity context, usually gotten with TSGetAdapt()
349 .  hmin - minimum time step
350 -  hmax - maximum time step
351 
352    Options Database Keys:
353 +  -ts_adapt_dt_min - minimum time step
354 -  -ts_adapt_dt_max - maximum time step
355 
356    Level: intermediate
357 
358 .seealso: TSAdapt
359 @*/
360 PetscErrorCode TSAdaptSetStepLimits(TSAdapt adapt,PetscReal hmin,PetscReal hmax)
361 {
362 
363   PetscFunctionBegin;
364   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
365   PetscValidLogicalCollectiveReal(adapt,hmin,2);
366   PetscValidLogicalCollectiveReal(adapt,hmax,3);
367   if (hmin != PETSC_DEFAULT && hmin < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Minimum time step %g must be non negative",(double)hmin);
368   if (hmax != PETSC_DEFAULT && hmax < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Minimum time step %g must be non negative",(double)hmax);
369   if (hmin != PETSC_DEFAULT) adapt->dt_min = hmin;
370   if (hmax != PETSC_DEFAULT) adapt->dt_max = hmax;
371 #if defined(PETSC_USE_DEBUG)
372   hmin = adapt->dt_min;
373   hmax = adapt->dt_max;
374   if (hmax <= hmin) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Maximum time step %g must geather than minimum time step %g",(double)hmax,(double)hmin);
375 #endif
376   PetscFunctionReturn(0);
377 }
378 
379 /*
380    TSAdaptSetFromOptions - Sets various TSAdapt parameters from user options.
381 
382    Collective on TSAdapt
383 
384    Input Parameter:
385 .  adapt - the TSAdapt context
386 
387    Options Database Keys:
388 +  -ts_adapt_type <type> - basic
389 .  -ts_adapt_dt_min <min> - minimum timestep to use
390 .  -ts_adapt_dt_max <max> - maximum timestep to use
391 .  -ts_adapt_scale_solve_failed <scale> - scale timestep by this factor if a solve fails
392 -  -ts_adapt_wnormtype <2 or infinity> - type of norm for computing error estimates
393 
394    Level: advanced
395 
396    Notes:
397    This function is automatically called by TSSetFromOptions()
398 
399 .keywords: TS, TSGetAdapt(), TSAdaptSetType(), TSAdaptSetStepLimits()
400 
401 .seealso: TSGetType()
402 */
403 PetscErrorCode  TSAdaptSetFromOptions(PetscOptionItems *PetscOptionsObject,TSAdapt adapt)
404 {
405   PetscErrorCode ierr;
406   char           type[256] = TSADAPTBASIC;
407   PetscBool      set,flg;
408 
409   PetscFunctionBegin;
410   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
411   /* This should use PetscOptionsBegin() if/when this becomes an object used outside of TS, but currently this
412    * function can only be called from inside TSSetFromOptions()  */
413   ierr = PetscOptionsHead(PetscOptionsObject,"TS Adaptivity options");CHKERRQ(ierr);
414   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);
415   if (flg || !((PetscObject)adapt)->type_name) {
416     ierr = TSAdaptSetType(adapt,type);CHKERRQ(ierr);
417   }
418   ierr = PetscOptionsReal("-ts_adapt_dt_min","Minimum time step considered","TSAdaptSetStepLimits",adapt->dt_min,&adapt->dt_min,NULL);CHKERRQ(ierr);
419   ierr = PetscOptionsReal("-ts_adapt_dt_max","Maximum time step considered","TSAdaptSetStepLimits",adapt->dt_max,&adapt->dt_max,NULL);CHKERRQ(ierr);
420   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);
421   ierr = PetscOptionsBool("-ts_adapt_monitor","Print choices made by adaptive controller","TSAdaptSetMonitor",adapt->monitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr);
422   ierr = PetscOptionsEnum("-ts_adapt_wnormtype","Type of norm computed for error estimation","",NormTypes,(PetscEnum)adapt->wnormtype,(PetscEnum*)&adapt->wnormtype,NULL);CHKERRQ(ierr);
423   if (adapt->wnormtype != NORM_2 && adapt->wnormtype != NORM_INFINITY) SETERRQ(PetscObjectComm((PetscObject)adapt),PETSC_ERR_SUP,"Only 2-norm and infinite norm supported");
424   if (set) {ierr = TSAdaptSetMonitor(adapt,flg);CHKERRQ(ierr);}
425   if (adapt->ops->setfromoptions) {ierr = (*adapt->ops->setfromoptions)(PetscOptionsObject,adapt);CHKERRQ(ierr);}
426   ierr = PetscOptionsTail();CHKERRQ(ierr);
427   PetscFunctionReturn(0);
428 }
429 
430 /*@
431    TSAdaptCandidatesClear - clear any previously set candidate schemes
432 
433    Logically Collective
434 
435    Input Argument:
436 .  adapt - adaptive controller
437 
438    Level: developer
439 
440 .seealso: TSAdapt, TSAdaptCreate(), TSAdaptCandidateAdd(), TSAdaptChoose()
441 @*/
442 PetscErrorCode TSAdaptCandidatesClear(TSAdapt adapt)
443 {
444   PetscErrorCode ierr;
445 
446   PetscFunctionBegin;
447   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
448   ierr = PetscMemzero(&adapt->candidates,sizeof(adapt->candidates));CHKERRQ(ierr);
449   PetscFunctionReturn(0);
450 }
451 
452 /*@C
453    TSAdaptCandidateAdd - add a candidate scheme for the adaptive controller to select from
454 
455    Logically Collective
456 
457    Input Arguments:
458 +  adapt - time step adaptivity context, obtained with TSGetAdapt() or TSAdaptCreate()
459 .  name - name of the candidate scheme to add
460 .  order - order of the candidate scheme
461 .  stageorder - stage order of the candidate scheme
462 .  ccfl - stability coefficient relative to explicit Euler, used for CFL constraints
463 .  cost - relative measure of the amount of work required for the candidate scheme
464 -  inuse - indicates that this scheme is the one currently in use, this flag can only be set for one scheme
465 
466    Note:
467    This routine is not available in Fortran.
468 
469    Level: developer
470 
471 .seealso: TSAdaptCandidatesClear(), TSAdaptChoose()
472 @*/
473 PetscErrorCode TSAdaptCandidateAdd(TSAdapt adapt,const char name[],PetscInt order,PetscInt stageorder,PetscReal ccfl,PetscReal cost,PetscBool inuse)
474 {
475   PetscInt c;
476 
477   PetscFunctionBegin;
478   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
479   if (order < 1) SETERRQ1(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_OUTOFRANGE,"Classical order %D must be a positive integer",order);
480   if (inuse) {
481     if (adapt->candidates.inuse_set) SETERRQ(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_WRONGSTATE,"Cannot set the inuse method twice, maybe forgot to call TSAdaptCandidatesClear()");
482     adapt->candidates.inuse_set = PETSC_TRUE;
483   }
484   /* first slot if this is the current scheme, otherwise the next available slot */
485   c = inuse ? 0 : !adapt->candidates.inuse_set + adapt->candidates.n;
486 
487   adapt->candidates.name[c]       = name;
488   adapt->candidates.order[c]      = order;
489   adapt->candidates.stageorder[c] = stageorder;
490   adapt->candidates.ccfl[c]       = ccfl;
491   adapt->candidates.cost[c]       = cost;
492   adapt->candidates.n++;
493   PetscFunctionReturn(0);
494 }
495 
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 /*@C
531    TSAdaptChoose - choose which method and step size to use for the next step
532 
533    Logically Collective
534 
535    Input Arguments:
536 +  adapt - adaptive contoller
537 -  h - current step size
538 
539    Output Arguments:
540 +  next_sc - optional, scheme to use for the next step
541 .  next_h - step size to use for the next step
542 -  accept - PETSC_TRUE to accept the current step, PETSC_FALSE to repeat the current step with the new step size
543 
544    Note:
545    The input value of parameter accept is retained from the last time step, so it will be PETSC_FALSE if the step is
546    being retried after an initial rejection.
547 
548    Level: developer
549 
550 .seealso: TSAdapt, TSAdaptCandidatesClear(), TSAdaptCandidateAdd()
551 @*/
552 PetscErrorCode TSAdaptChoose(TSAdapt adapt,TS ts,PetscReal h,PetscInt *next_sc,PetscReal *next_h,PetscBool *accept)
553 {
554   PetscErrorCode ierr;
555   PetscInt       ncandidates = adapt->candidates.n;
556   PetscInt       scheme = 0;
557   PetscReal      wlte = -1.0;
558   PetscReal      wltea = -1.0;
559   PetscReal      wlter = -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,&wltea,&wlter);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 %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);
595     } else {
596       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);
597     }
598     ierr = PetscViewerASCIISubtractTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
599   }
600   PetscFunctionReturn(0);
601 }
602 
603 /*@
604    TSAdaptCheckStage - checks whether to accept a stage, (e.g. reject and change time step size if nonlinear solve fails)
605 
606    Collective
607 
608    Input Arguments:
609 +  adapt - adaptive controller context
610 .  ts - time stepper
611 .  t - Current simulation time
612 -  Y - Current solution vector
613 
614    Output Arguments:
615 .  accept - PETSC_TRUE to accept the stage, PETSC_FALSE to reject
616 
617    Level: developer
618 
619 .seealso:
620 @*/
621 PetscErrorCode TSAdaptCheckStage(TSAdapt adapt,TS ts,PetscReal t,Vec Y,PetscBool *accept)
622 {
623   PetscErrorCode      ierr;
624   SNESConvergedReason snesreason = SNES_CONVERGED_ITERATING;
625 
626   PetscFunctionBegin;
627   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
628   PetscValidHeaderSpecific(ts,TS_CLASSID,2);
629   PetscValidIntPointer(accept,3);
630 
631   if (ts->snes) {ierr = SNESGetConvergedReason(ts->snes,&snesreason);CHKERRQ(ierr);}
632   if (snesreason < 0) {
633     *accept = PETSC_FALSE;
634     if (++ts->num_snes_failures >= ts->max_snes_failures && ts->max_snes_failures > 0) {
635       ts->reason = TS_DIVERGED_NONLINEAR_SOLVE;
636       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);
637       if (adapt->monitor) {
638         ierr = PetscViewerASCIIAddTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
639         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);
640         ierr = PetscViewerASCIISubtractTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
641       }
642     }
643   } else {
644     *accept = PETSC_TRUE;
645     ierr = TSFunctionDomainError(ts,t,Y,accept);CHKERRQ(ierr);
646     if(*accept && adapt->checkstage) {
647       ierr = (*adapt->checkstage)(adapt,ts,t,Y,accept);CHKERRQ(ierr);
648     }
649   }
650 
651   if(!(*accept) && !ts->reason) {
652     PetscReal dt,new_dt;
653     ierr = TSGetTimeStep(ts,&dt);CHKERRQ(ierr);
654     new_dt = dt * adapt->scale_solve_failed;
655     ierr = TSSetTimeStep(ts,new_dt);CHKERRQ(ierr);
656     adapt->timestepjustincreased += 4;
657     if (adapt->monitor) {
658       ierr = PetscViewerASCIIAddTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
659       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);
660       ierr = PetscViewerASCIISubtractTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
661     }
662   }
663   PetscFunctionReturn(0);
664 }
665 
666 /*@
667   TSAdaptCreate - create an adaptive controller context for time stepping
668 
669   Collective on MPI_Comm
670 
671   Input Parameter:
672 . comm - The communicator
673 
674   Output Parameter:
675 . adapt - new TSAdapt object
676 
677   Level: developer
678 
679   Notes:
680   TSAdapt creation is handled by TS, so users should not need to call this function.
681 
682 .keywords: TSAdapt, create
683 .seealso: TSGetAdapt(), TSAdaptSetType(), TSAdaptDestroy()
684 @*/
685 PetscErrorCode  TSAdaptCreate(MPI_Comm comm,TSAdapt *inadapt)
686 {
687   PetscErrorCode ierr;
688   TSAdapt        adapt;
689 
690   PetscFunctionBegin;
691   PetscValidPointer(inadapt,1);
692   *inadapt = NULL;
693   ierr = TSAdaptInitializePackage();CHKERRQ(ierr);
694 
695   ierr = PetscHeaderCreate(adapt,TSADAPT_CLASSID,"TSAdapt","Time stepping adaptivity","TS",comm,TSAdaptDestroy,TSAdaptView);CHKERRQ(ierr);
696 
697   adapt->dt_min             = 1e-20;
698   adapt->dt_max             = 1e50;
699   adapt->scale_solve_failed = 0.25;
700   adapt->wnormtype          = NORM_2;
701   ierr = TSAdaptSetType(adapt,TSADAPTBASIC);CHKERRQ(ierr);
702 
703   *inadapt = adapt;
704   PetscFunctionReturn(0);
705 }
706