xref: /petsc/src/ts/adapt/interface/tsadapt.c (revision f8e4bde84cdee892096ab78baf4256ae384d8e42) !
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 (*checkstage)(TSAdapt,TS,PetscBool*);
131   PetscErrorCode ierr,(*r)(TSAdapt);
132 
133   PetscFunctionBegin;
134   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
135   ierr = PetscObjectTypeCompare((PetscObject)adapt,type,&match);CHKERRQ(ierr);
136   if (match) PetscFunctionReturn(0);
137   ierr = PetscFunctionListFind(TSAdaptList,type,&r);CHKERRQ(ierr);
138   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown TSAdapt type \"%s\" given",type);
139   if (adapt->ops->destroy) {ierr = (*adapt->ops->destroy)(adapt);CHKERRQ(ierr);}
140   /* Reinitialize function pointers in TSAdaptOps structure */
141   checkstage = adapt->ops->checkstage;
142   ierr = PetscMemzero(adapt->ops,sizeof(struct _TSAdaptOps));CHKERRQ(ierr);
143   adapt->ops->checkstage = checkstage;
144   ierr = (*r)(adapt);CHKERRQ(ierr);
145   ierr = PetscObjectChangeTypeName((PetscObject)adapt,type);CHKERRQ(ierr);
146   PetscFunctionReturn(0);
147 }
148 
149 #undef __FUNCT__
150 #define __FUNCT__ "TSAdaptSetOptionsPrefix"
151 PetscErrorCode  TSAdaptSetOptionsPrefix(TSAdapt adapt,const char prefix[])
152 {
153   PetscErrorCode ierr;
154 
155   PetscFunctionBegin;
156   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
157   ierr = PetscObjectSetOptionsPrefix((PetscObject)adapt,prefix);CHKERRQ(ierr);
158   PetscFunctionReturn(0);
159 }
160 
161 #undef __FUNCT__
162 #define __FUNCT__ "TSAdaptLoad"
163 /*@C
164   TSAdaptLoad - Loads a TSAdapt that has been stored in binary  with TSAdaptView().
165 
166   Collective on PetscViewer
167 
168   Input Parameters:
169 + newdm - the newly loaded TSAdapt, this needs to have been created with TSAdaptCreate() or
170            some related function before a call to TSAdaptLoad().
171 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or
172            HDF5 file viewer, obtained from PetscViewerHDF5Open()
173 
174    Level: intermediate
175 
176   Notes:
177    The type is determined by the data in the file, any type set into the TSAdapt before this call is ignored.
178 
179   Notes for advanced users:
180   Most users should not need to know the details of the binary storage
181   format, since TSAdaptLoad() and TSAdaptView() completely hide these details.
182   But for anyone who's interested, the standard binary matrix storage
183   format is
184 .vb
185      has not yet been determined
186 .ve
187 
188 .seealso: PetscViewerBinaryOpen(), TSAdaptView(), MatLoad(), VecLoad()
189 @*/
190 PetscErrorCode  TSAdaptLoad(TSAdapt adapt,PetscViewer viewer)
191 {
192   PetscErrorCode ierr;
193   PetscBool      isbinary;
194   PetscInt       len = 256;
195   char           type[256];
196 
197   PetscFunctionBegin;
198   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
199   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
200   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
201   if (!isbinary) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen()");
202 
203   ierr = PetscViewerBinaryRead(viewer,type,&len,PETSC_CHAR);CHKERRQ(ierr);
204   ierr = TSAdaptSetType(adapt, type);CHKERRQ(ierr);
205   if (adapt->ops->load) {
206     ierr = (*adapt->ops->load)(adapt,viewer);CHKERRQ(ierr);
207   }
208   PetscFunctionReturn(0);
209 }
210 
211 #undef __FUNCT__
212 #define __FUNCT__ "TSAdaptView"
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     if (adapt->ops->view) {
229       ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
230       ierr = (*adapt->ops->view)(adapt,viewer);CHKERRQ(ierr);
231       ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
232     }
233   } else if (isbinary) {
234     char type[256];
235 
236     /* need to save FILE_CLASS_ID for adapt class */
237     ierr = PetscStrncpy(type,((PetscObject)adapt)->type_name,256);CHKERRQ(ierr);
238     ierr = PetscViewerBinaryWrite(viewer,type,256,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr);
239   } else if (adapt->ops->view) {
240     ierr = (*adapt->ops->view)(adapt,viewer);CHKERRQ(ierr);
241   }
242   PetscFunctionReturn(0);
243 }
244 
245 #undef __FUNCT__
246 #define __FUNCT__ "TSAdaptDestroy"
247 PetscErrorCode  TSAdaptDestroy(TSAdapt *adapt)
248 {
249   PetscErrorCode ierr;
250 
251   PetscFunctionBegin;
252   if (!*adapt) PetscFunctionReturn(0);
253   PetscValidHeaderSpecific(*adapt,TSADAPT_CLASSID,1);
254   if (--((PetscObject)(*adapt))->refct > 0) {*adapt = NULL; PetscFunctionReturn(0);}
255   if ((*adapt)->ops->destroy) {ierr = (*(*adapt)->ops->destroy)(*adapt);CHKERRQ(ierr);}
256   ierr = PetscViewerDestroy(&(*adapt)->monitor);CHKERRQ(ierr);
257   ierr = PetscHeaderDestroy(adapt);CHKERRQ(ierr);
258   PetscFunctionReturn(0);
259 }
260 
261 #undef __FUNCT__
262 #define __FUNCT__ "TSAdaptSetMonitor"
263 /*@
264    TSAdaptSetMonitor - Monitor the choices made by the adaptive controller
265 
266    Collective on TSAdapt
267 
268    Input Arguments:
269 +  adapt - adaptive controller context
270 -  flg - PETSC_TRUE to active a monitor, PETSC_FALSE to disable
271 
272    Level: intermediate
273 
274 .seealso: TSAdaptChoose()
275 @*/
276 PetscErrorCode TSAdaptSetMonitor(TSAdapt adapt,PetscBool flg)
277 {
278   PetscErrorCode ierr;
279 
280   PetscFunctionBegin;
281   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
282   PetscValidLogicalCollectiveBool(adapt,flg,2);
283   if (flg) {
284     if (!adapt->monitor) {ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)adapt),"stdout",&adapt->monitor);CHKERRQ(ierr);}
285   } else {
286     ierr = PetscViewerDestroy(&adapt->monitor);CHKERRQ(ierr);
287   }
288   PetscFunctionReturn(0);
289 }
290 
291 #undef __FUNCT__
292 #define __FUNCT__ "TSAdaptSetCheckStage"
293 /*@C
294    TSAdaptSetCheckStage - set a callback to check convergence for a stage
295 
296    Logically collective on TSAdapt
297 
298    Input Arguments:
299 +  adapt - adaptive controller context
300 -  func - stage check function
301 
302    Arguments of func:
303 $  PetscErrorCode func(TSAdapt adapt,TS ts,PetscBool *accept)
304 
305 +  adapt - adaptive controller context
306 .  ts - time stepping context
307 -  accept - pending choice of whether to accept, can be modified by this routine
308 
309    Level: advanced
310 
311 .seealso: TSAdaptChoose()
312 @*/
313 PetscErrorCode TSAdaptSetCheckStage(TSAdapt adapt,PetscErrorCode (*func)(TSAdapt,TS,PetscBool*))
314 {
315 
316   PetscFunctionBegin;
317   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
318   adapt->ops->checkstage = func;
319   PetscFunctionReturn(0);
320 }
321 
322 #undef __FUNCT__
323 #define __FUNCT__ "TSAdaptSetStepLimits"
324 /*@
325    TSAdaptSetStepLimits - Set minimum and maximum step sizes to be considered by the controller
326 
327    Logically Collective
328 
329    Input Arguments:
330 +  adapt - time step adaptivity context, usually gotten with TSGetAdapt()
331 .  hmin - minimum time step
332 -  hmax - maximum time step
333 
334    Options Database Keys:
335 +  -ts_adapt_dt_min - minimum time step
336 -  -ts_adapt_dt_max - maximum time step
337 
338    Level: intermediate
339 
340 .seealso: TSAdapt
341 @*/
342 PetscErrorCode TSAdaptSetStepLimits(TSAdapt adapt,PetscReal hmin,PetscReal hmax)
343 {
344 
345   PetscFunctionBegin;
346   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
347   if (hmin != PETSC_DECIDE) adapt->dt_min = hmin;
348   if (hmax != PETSC_DECIDE) adapt->dt_max = hmax;
349   PetscFunctionReturn(0);
350 }
351 
352 #undef __FUNCT__
353 #define __FUNCT__ "TSAdaptSetFromOptions"
354 /*
355    TSAdaptSetFromOptions - Sets various TSAdapt parameters from user options.
356 
357    Collective on TSAdapt
358 
359    Input Parameter:
360 .  adapt - the TSAdapt context
361 
362    Options Database Keys:
363 .  -ts_adapt_type <type> - basic
364 
365    Level: advanced
366 
367    Notes:
368    This function is automatically called by TSSetFromOptions()
369 
370 .keywords: TS, TSGetAdapt(), TSAdaptSetType()
371 
372 .seealso: TSGetType()
373 */
374 PetscErrorCode  TSAdaptSetFromOptions(PetscOptions *PetscOptionsObject,TSAdapt adapt)
375 {
376   PetscErrorCode ierr;
377   char           type[256] = TSADAPTBASIC;
378   PetscBool      set,flg;
379 
380   PetscFunctionBegin;
381   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
382   /* This should use PetscOptionsBegin() if/when this becomes an object used outside of TS, but currently this
383   * function can only be called from inside TSSetFromOptions_GL()  */
384   ierr = PetscOptionsHead(PetscOptionsObject,"TS Adaptivity options");CHKERRQ(ierr);
385   ierr = PetscOptionsFList("-ts_adapt_type","Algorithm to use for adaptivity","TSAdaptSetType",TSAdaptList,
386                           ((PetscObject)adapt)->type_name ? ((PetscObject)adapt)->type_name : type,type,sizeof(type),&flg);CHKERRQ(ierr);
387   if (flg || !((PetscObject)adapt)->type_name) {
388     ierr = TSAdaptSetType(adapt,type);CHKERRQ(ierr);
389   }
390   ierr = PetscOptionsReal("-ts_adapt_dt_min","Minimum time step considered","TSAdaptSetStepLimits",adapt->dt_min,&adapt->dt_min,NULL);CHKERRQ(ierr);
391   ierr = PetscOptionsReal("-ts_adapt_dt_max","Maximum time step considered","TSAdaptSetStepLimits",adapt->dt_max,&adapt->dt_max,NULL);CHKERRQ(ierr);
392   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);
393   ierr = PetscOptionsBool("-ts_adapt_monitor","Print choices made by adaptive controller","TSAdaptSetMonitor",adapt->monitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr);
394   ierr = PetscOptionsEnum("-ts_adapt_wnormtype","Type of norm computed for error estimation","",NormTypes,(PetscEnum)adapt->wnormtype,(PetscEnum*)&adapt->wnormtype,NULL);CHKERRQ(ierr);
395   if (adapt->wnormtype != NORM_2 && adapt->wnormtype != NORM_INFINITY) SETERRQ(PetscObjectComm((PetscObject)adapt),PETSC_ERR_SUP,"Only 2-norm and infinite norm supported");
396   if (set) {ierr = TSAdaptSetMonitor(adapt,flg);CHKERRQ(ierr);}
397   if (adapt->ops->setfromoptions) {ierr = (*adapt->ops->setfromoptions)(PetscOptionsObject,adapt);CHKERRQ(ierr);}
398   ierr = PetscOptionsTail();CHKERRQ(ierr);
399   PetscFunctionReturn(0);
400 }
401 
402 #undef __FUNCT__
403 #define __FUNCT__ "TSAdaptCandidatesClear"
404 /*@
405    TSAdaptCandidatesClear - clear any previously set candidate schemes
406 
407    Logically Collective
408 
409    Input Argument:
410 .  adapt - adaptive controller
411 
412    Level: developer
413 
414 .seealso: TSAdapt, TSAdaptCreate(), TSAdaptCandidateAdd(), TSAdaptChoose()
415 @*/
416 PetscErrorCode TSAdaptCandidatesClear(TSAdapt adapt)
417 {
418   PetscErrorCode ierr;
419 
420   PetscFunctionBegin;
421   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
422   ierr = PetscMemzero(&adapt->candidates,sizeof(adapt->candidates));CHKERRQ(ierr);
423   PetscFunctionReturn(0);
424 }
425 
426 #undef __FUNCT__
427 #define __FUNCT__ "TSAdaptCandidateAdd"
428 /*@C
429    TSAdaptCandidateAdd - add a candidate scheme for the adaptive controller to select from
430 
431    Logically Collective
432 
433    Input Arguments:
434 +  adapt - time step adaptivity context, obtained with TSGetAdapt() or TSAdaptCreate()
435 .  name - name of the candidate scheme to add
436 .  order - order of the candidate scheme
437 .  stageorder - stage order of the candidate scheme
438 .  ccfl - stability coefficient relative to explicit Euler, used for CFL constraints
439 .  cost - relative measure of the amount of work required for the candidate scheme
440 -  inuse - indicates that this scheme is the one currently in use, this flag can only be set for one scheme
441 
442    Note:
443    This routine is not available in Fortran.
444 
445    Level: developer
446 
447 .seealso: TSAdaptCandidatesClear(), TSAdaptChoose()
448 @*/
449 PetscErrorCode TSAdaptCandidateAdd(TSAdapt adapt,const char name[],PetscInt order,PetscInt stageorder,PetscReal ccfl,PetscReal cost,PetscBool inuse)
450 {
451   PetscInt c;
452 
453   PetscFunctionBegin;
454   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
455   if (order < 1) SETERRQ1(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_OUTOFRANGE,"Classical order %D must be a positive integer",order);
456   if (inuse) {
457     if (adapt->candidates.inuse_set) SETERRQ(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_WRONGSTATE,"Cannot set the inuse method twice, maybe forgot to call TSAdaptCandidatesClear()");
458     adapt->candidates.inuse_set = PETSC_TRUE;
459   }
460   /* first slot if this is the current scheme, otherwise the next available slot */
461   c = inuse ? 0 : !adapt->candidates.inuse_set + adapt->candidates.n;
462 
463   adapt->candidates.name[c]       = name;
464   adapt->candidates.order[c]      = order;
465   adapt->candidates.stageorder[c] = stageorder;
466   adapt->candidates.ccfl[c]       = ccfl;
467   adapt->candidates.cost[c]       = cost;
468   adapt->candidates.n++;
469   PetscFunctionReturn(0);
470 }
471 
472 #undef __FUNCT__
473 #define __FUNCT__ "TSAdaptCandidatesGet"
474 /*@C
475    TSAdaptCandidatesGet - Get the list of candidate orders of accuracy and cost
476 
477    Not Collective
478 
479    Input Arguments:
480 .  adapt - time step adaptivity context
481 
482    Output Arguments:
483 +  n - number of candidate schemes, always at least 1
484 .  order - the order of each candidate scheme
485 .  stageorder - the stage order of each candidate scheme
486 .  ccfl - the CFL coefficient of each scheme
487 -  cost - the relative cost of each scheme
488 
489    Level: developer
490 
491    Note:
492    The current scheme is always returned in the first slot
493 
494 .seealso: TSAdaptCandidatesClear(), TSAdaptCandidateAdd(), TSAdaptChoose()
495 @*/
496 PetscErrorCode TSAdaptCandidatesGet(TSAdapt adapt,PetscInt *n,const PetscInt **order,const PetscInt **stageorder,const PetscReal **ccfl,const PetscReal **cost)
497 {
498   PetscFunctionBegin;
499   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
500   if (n) *n = adapt->candidates.n;
501   if (order) *order = adapt->candidates.order;
502   if (stageorder) *stageorder = adapt->candidates.stageorder;
503   if (ccfl) *ccfl = adapt->candidates.ccfl;
504   if (cost) *cost = adapt->candidates.cost;
505   PetscFunctionReturn(0);
506 }
507 
508 #undef __FUNCT__
509 #define __FUNCT__ "TSAdaptChoose"
510 /*@C
511    TSAdaptChoose - choose which method and step size to use for the next step
512 
513    Logically Collective
514 
515    Input Arguments:
516 +  adapt - adaptive contoller
517 -  h - current step size
518 
519    Output Arguments:
520 +  next_sc - scheme to use for the next step
521 .  next_h - step size to use for the next step
522 -  accept - PETSC_TRUE to accept the current step, PETSC_FALSE to repeat the current step with the new step size
523 
524    Note:
525    The input value of parameter accept is retained from the last time step, so it will be PETSC_FALSE if the step is
526    being retried after an initial rejection.
527 
528    Level: developer
529 
530 .seealso: TSAdapt, TSAdaptCandidatesClear(), TSAdaptCandidateAdd()
531 @*/
532 PetscErrorCode TSAdaptChoose(TSAdapt adapt,TS ts,PetscReal h,PetscInt *next_sc,PetscReal *next_h,PetscBool *accept)
533 {
534   PetscErrorCode ierr;
535   PetscReal      wlte = -1.0;
536 
537   PetscFunctionBegin;
538   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
539   PetscValidHeaderSpecific(ts,TS_CLASSID,2);
540   PetscValidIntPointer(next_sc,4);
541   PetscValidPointer(next_h,5);
542   PetscValidIntPointer(accept,6);
543   if (adapt->candidates.n < 1) SETERRQ1(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_WRONGSTATE,"%D candidates have been registered",adapt->candidates.n);
544   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);
545   ierr = (*adapt->ops->choose)(adapt,ts,h,next_sc,next_h,accept,&wlte);CHKERRQ(ierr);
546   if (*accept && ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP) {
547     /* Reduce time step if it overshoots max time */
548     PetscReal max_time = ts->max_time;
549     PetscReal next_dt  = 0.0;
550     if (ts->ptime + ts->time_step + *next_h >= max_time) {
551       next_dt = max_time - (ts->ptime + ts->time_step);
552       if (next_dt > PETSC_SMALL) *next_h = next_dt;
553       else ts->reason = TS_CONVERGED_TIME;
554     }
555   }
556   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);
557   if (!(*next_h > 0.)) SETERRQ1(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_OUTOFRANGE,"Computed step size %g must be positive",(double)*next_h);
558 
559   if (adapt->monitor) {
560     ierr = PetscViewerASCIIAddTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
561     if (wlte < 0) {
562       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);
563     } else {
564       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);
565     }
566     ierr = PetscViewerASCIISubtractTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
567   }
568   PetscFunctionReturn(0);
569 }
570 
571 #undef __FUNCT__
572 #define __FUNCT__ "TSAdaptCheckStage"
573 /*@
574    TSAdaptCheckStage - checks whether to accept a stage, (e.g. reject and change time step size if nonlinear solve fails)
575 
576    Collective
577 
578    Input Arguments:
579 +  adapt - adaptive controller context
580 -  ts - time stepper
581 
582    Output Arguments:
583 .  accept - PETSC_TRUE to accept the stage, PETSC_FALSE to reject
584 
585    Level: developer
586 
587 .seealso:
588 @*/
589 PetscErrorCode TSAdaptCheckStage(TSAdapt adapt,TS ts,PetscBool *accept)
590 {
591   PetscErrorCode      ierr;
592   SNES                snes;
593   SNESConvergedReason snesreason;
594 
595   PetscFunctionBegin;
596   PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1);
597   PetscValidHeaderSpecific(ts,TS_CLASSID,2);
598   PetscValidIntPointer(accept,3);
599   *accept = PETSC_TRUE;
600   ierr    = TSGetSNES(ts,&snes);CHKERRQ(ierr);
601   ierr    = SNESGetConvergedReason(snes,&snesreason);CHKERRQ(ierr);
602   if (snesreason < 0) {
603     PetscReal dt,new_dt;
604     *accept = PETSC_FALSE;
605     ierr    = TSGetTimeStep(ts,&dt);CHKERRQ(ierr);
606     if (++ts->num_snes_failures >= ts->max_snes_failures && ts->max_snes_failures > 0) {
607       ts->reason = TS_DIVERGED_NONLINEAR_SOLVE;
608       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);
609       if (adapt->monitor) {
610         ierr = PetscViewerASCIIAddTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
611         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);
612         ierr = PetscViewerASCIISubtractTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
613       }
614     } else {
615       new_dt = dt*adapt->scale_solve_failed;
616       ierr   = TSSetTimeStep(ts,new_dt);CHKERRQ(ierr);
617       if (adapt->monitor) {
618         ierr = PetscViewerASCIIAddTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
619         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);
620         ierr = PetscViewerASCIISubtractTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr);
621       }
622     }
623   }
624   if (adapt->ops->checkstage) {ierr = (*adapt->ops->checkstage)(adapt,ts,accept);CHKERRQ(ierr);}
625   PetscFunctionReturn(0);
626 }
627 
628 
629 
630 #undef __FUNCT__
631 #define __FUNCT__ "TSAdaptCreate"
632 /*@
633   TSAdaptCreate - create an adaptive controller context for time stepping
634 
635   Collective on MPI_Comm
636 
637   Input Parameter:
638 . comm - The communicator
639 
640   Output Parameter:
641 . adapt - new TSAdapt object
642 
643   Level: developer
644 
645   Notes:
646   TSAdapt creation is handled by TS, so users should not need to call this function.
647 
648 .keywords: TSAdapt, create
649 .seealso: TSGetAdapt(), TSAdaptSetType(), TSAdaptDestroy()
650 @*/
651 PetscErrorCode  TSAdaptCreate(MPI_Comm comm,TSAdapt *inadapt)
652 {
653   PetscErrorCode ierr;
654   TSAdapt        adapt;
655 
656   PetscFunctionBegin;
657   PetscValidPointer(inadapt,1);
658   *inadapt = NULL;
659   ierr = TSAdaptInitializePackage();CHKERRQ(ierr);
660 
661   ierr = PetscHeaderCreate(adapt,_p_TSAdapt,struct _TSAdaptOps,TSADAPT_CLASSID,"TSAdapt","General Linear adaptivity","TS",comm,TSAdaptDestroy,TSAdaptView);CHKERRQ(ierr);
662 
663   adapt->dt_min             = 1e-20;
664   adapt->dt_max             = 1e50;
665   adapt->scale_solve_failed = 0.25;
666   adapt->wnormtype          = NORM_2;
667 
668   *inadapt = adapt;
669   PetscFunctionReturn(0);
670 }
671