Actual source code: tsadapt.c


  2: #include <petsc/private/tsimpl.h>

  4: PetscClassId TSADAPT_CLASSID;

  6: static PetscFunctionList TSAdaptList;
  7: static PetscBool         TSAdaptPackageInitialized;
  8: static PetscBool         TSAdaptRegisterAllCalled;

 10: PETSC_EXTERN PetscErrorCode TSAdaptCreate_None(TSAdapt);
 11: PETSC_EXTERN PetscErrorCode TSAdaptCreate_Basic(TSAdapt);
 12: PETSC_EXTERN PetscErrorCode TSAdaptCreate_DSP(TSAdapt);
 13: PETSC_EXTERN PetscErrorCode TSAdaptCreate_CFL(TSAdapt);
 14: PETSC_EXTERN PetscErrorCode TSAdaptCreate_GLEE(TSAdapt);
 15: PETSC_EXTERN PetscErrorCode TSAdaptCreate_History(TSAdapt);

 17: /*@C
 18:    TSAdaptRegister -  adds a TSAdapt implementation

 20:    Not Collective

 22:    Input Parameters:
 23: +  name_scheme - name of user-defined adaptivity scheme
 24: -  routine_create - routine to create method context

 26:    Level: advanced

 28:    Notes:
 29:    `TSAdaptRegister()` may be called multiple times to add several user-defined families.

 31:    Sample usage:
 32: .vb
 33:    TSAdaptRegister("my_scheme",MySchemeCreate);
 34: .ve

 36:    Then, your scheme can be chosen with the procedural interface via
 37: $     TSAdaptSetType(ts,"my_scheme")
 38:    or at runtime via the option
 39: $     -ts_adapt_type my_scheme

 41: .seealso: [](chapter_ts), `TSAdaptRegisterAll()`
 42: @*/
 43: PetscErrorCode TSAdaptRegister(const char sname[], PetscErrorCode (*function)(TSAdapt))
 44: {
 45:   PetscFunctionBegin;
 46:   PetscCall(TSAdaptInitializePackage());
 47:   PetscCall(PetscFunctionListAdd(&TSAdaptList, sname, function));
 48:   PetscFunctionReturn(PETSC_SUCCESS);
 49: }

 51: /*@C
 52:   TSAdaptRegisterAll - Registers all of the adaptivity schemes in TSAdapt

 54:   Not Collective

 56:   Level: advanced

 58: .seealso: [](chapter_ts), `TSAdaptRegisterDestroy()`
 59: @*/
 60: PetscErrorCode TSAdaptRegisterAll(void)
 61: {
 62:   PetscFunctionBegin;
 63:   if (TSAdaptRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS);
 64:   TSAdaptRegisterAllCalled = PETSC_TRUE;
 65:   PetscCall(TSAdaptRegister(TSADAPTNONE, TSAdaptCreate_None));
 66:   PetscCall(TSAdaptRegister(TSADAPTBASIC, TSAdaptCreate_Basic));
 67:   PetscCall(TSAdaptRegister(TSADAPTDSP, TSAdaptCreate_DSP));
 68:   PetscCall(TSAdaptRegister(TSADAPTCFL, TSAdaptCreate_CFL));
 69:   PetscCall(TSAdaptRegister(TSADAPTGLEE, TSAdaptCreate_GLEE));
 70:   PetscCall(TSAdaptRegister(TSADAPTHISTORY, TSAdaptCreate_History));
 71:   PetscFunctionReturn(PETSC_SUCCESS);
 72: }

 74: /*@C
 75:   TSAdaptFinalizePackage - This function destroys everything in the TS package. It is
 76:   called from PetscFinalize().

 78:   Level: developer

 80: .seealso: [](chapter_ts), `PetscFinalize()`
 81: @*/
 82: PetscErrorCode TSAdaptFinalizePackage(void)
 83: {
 84:   PetscFunctionBegin;
 85:   PetscCall(PetscFunctionListDestroy(&TSAdaptList));
 86:   TSAdaptPackageInitialized = PETSC_FALSE;
 87:   TSAdaptRegisterAllCalled  = PETSC_FALSE;
 88:   PetscFunctionReturn(PETSC_SUCCESS);
 89: }

 91: /*@C
 92:   TSAdaptInitializePackage - This function initializes everything in the TSAdapt package. It is
 93:   called from TSInitializePackage().

 95:   Level: developer

 97: .seealso: [](chapter_ts), `PetscInitialize()`
 98: @*/
 99: PetscErrorCode TSAdaptInitializePackage(void)
100: {
101:   PetscFunctionBegin;
102:   if (TSAdaptPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS);
103:   TSAdaptPackageInitialized = PETSC_TRUE;
104:   PetscCall(PetscClassIdRegister("TSAdapt", &TSADAPT_CLASSID));
105:   PetscCall(TSAdaptRegisterAll());
106:   PetscCall(PetscRegisterFinalize(TSAdaptFinalizePackage));
107:   PetscFunctionReturn(PETSC_SUCCESS);
108: }

110: /*@C
111:   TSAdaptSetType - sets the approach used for the error adapter

113:   Logicially Collective onadapt

115:   Input Parameters:
116: + adapt - the `TS` adapter, most likely obtained with `TSGetAdapt()`
117: - type - one of the `TSAdaptType`

119:   Options Database Key:
120: . -ts_adapt_type <basic or dsp or none> - to set the adapter type

122:   Level: intermediate

124: .seealso: [](chapter_ts), `TSGetAdapt()`, `TSAdaptDestroy()`, `TSAdaptType`, `TSAdaptGetType()`, `TSAdaptType`
125: @*/
126: PetscErrorCode TSAdaptSetType(TSAdapt adapt, TSAdaptType type)
127: {
128:   PetscBool match;
129:   PetscErrorCode (*r)(TSAdapt);

131:   PetscFunctionBegin;
134:   PetscCall(PetscObjectTypeCompare((PetscObject)adapt, type, &match));
135:   if (match) PetscFunctionReturn(PETSC_SUCCESS);
136:   PetscCall(PetscFunctionListFind(TSAdaptList, type, &r));
137:   PetscCheck(r, PETSC_COMM_SELF, PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown TSAdapt type \"%s\" given", type);
138:   PetscTryTypeMethod(adapt, destroy);
139:   PetscCall(PetscMemzero(adapt->ops, sizeof(struct _TSAdaptOps)));
140:   PetscCall(PetscObjectChangeTypeName((PetscObject)adapt, type));
141:   PetscCall((*r)(adapt));
142:   PetscFunctionReturn(PETSC_SUCCESS);
143: }

145: /*@C
146:   TSAdaptGetType - gets the `TS` adapter method type (as a string).

148:   Not Collective

150:   Input Parameter:
151: . adapt - The `TS` adapter, most likely obtained with `TSGetAdapt()`

153:   Output Parameter:
154: . type - The name of `TS` adapter method

156:   Level: intermediate

158: .seealso: `TSAdapt`, `TSAdaptType`, `TSAdaptSetType()`
159: @*/
160: PetscErrorCode TSAdaptGetType(TSAdapt adapt, TSAdaptType *type)
161: {
162:   PetscFunctionBegin;
165:   *type = ((PetscObject)adapt)->type_name;
166:   PetscFunctionReturn(PETSC_SUCCESS);
167: }

169: PetscErrorCode TSAdaptSetOptionsPrefix(TSAdapt adapt, const char prefix[])
170: {
171:   PetscFunctionBegin;
173:   PetscCall(PetscObjectSetOptionsPrefix((PetscObject)adapt, prefix));
174:   PetscFunctionReturn(PETSC_SUCCESS);
175: }

177: /*@C
178:   TSAdaptLoad - Loads a TSAdapt that has been stored in binary  with TSAdaptView().

180:   Collective

182:   Input Parameters:
183: + newdm - the newly loaded `TSAdapt`, this needs to have been created with `TSAdaptCreate()` or
184:            some related function before a call to `TSAdaptLoad()`.
185: - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()` or
186:            HDF5 file viewer, obtained from `PetscViewerHDF5Open()`

188:    Level: intermediate

190:   Note:
191:    The type is determined by the data in the file, any type set into the `TSAdapt` before this call is ignored.

193: .seealso: [](chapter_ts), `PetscViewerBinaryOpen()`, `TSAdaptView()`, `MatLoad()`, `VecLoad()`, `TSAdapt`
194: @*/
195: PetscErrorCode TSAdaptLoad(TSAdapt adapt, PetscViewer viewer)
196: {
197:   PetscBool isbinary;
198:   char      type[256];

200:   PetscFunctionBegin;
203:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
204:   PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()");

206:   PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR));
207:   PetscCall(TSAdaptSetType(adapt, type));
208:   PetscTryTypeMethod(adapt, load, viewer);
209:   PetscFunctionReturn(PETSC_SUCCESS);
210: }

212: PetscErrorCode TSAdaptView(TSAdapt adapt, PetscViewer viewer)
213: {
214:   PetscBool iascii, isbinary, isnone, isglee;

216:   PetscFunctionBegin;
218:   if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)adapt), &viewer));
220:   PetscCheckSameComm(adapt, 1, viewer, 2);
221:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii));
222:   PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
223:   if (iascii) {
224:     PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)adapt, viewer));
225:     PetscCall(PetscObjectTypeCompare((PetscObject)adapt, TSADAPTNONE, &isnone));
226:     PetscCall(PetscObjectTypeCompare((PetscObject)adapt, TSADAPTGLEE, &isglee));
227:     if (!isnone) {
228:       if (adapt->always_accept) PetscCall(PetscViewerASCIIPrintf(viewer, "  always accepting steps\n"));
229:       PetscCall(PetscViewerASCIIPrintf(viewer, "  safety factor %g\n", (double)adapt->safety));
230:       PetscCall(PetscViewerASCIIPrintf(viewer, "  extra safety factor after step rejection %g\n", (double)adapt->reject_safety));
231:       PetscCall(PetscViewerASCIIPrintf(viewer, "  clip fastest increase %g\n", (double)adapt->clip[1]));
232:       PetscCall(PetscViewerASCIIPrintf(viewer, "  clip fastest decrease %g\n", (double)adapt->clip[0]));
233:       PetscCall(PetscViewerASCIIPrintf(viewer, "  maximum allowed timestep %g\n", (double)adapt->dt_max));
234:       PetscCall(PetscViewerASCIIPrintf(viewer, "  minimum allowed timestep %g\n", (double)adapt->dt_min));
235:       PetscCall(PetscViewerASCIIPrintf(viewer, "  maximum solution absolute value to be ignored %g\n", (double)adapt->ignore_max));
236:     }
237:     if (isglee) {
238:       if (adapt->glee_use_local) {
239:         PetscCall(PetscViewerASCIIPrintf(viewer, "  GLEE uses local error control\n"));
240:       } else {
241:         PetscCall(PetscViewerASCIIPrintf(viewer, "  GLEE uses global error control\n"));
242:       }
243:     }
244:     PetscCall(PetscViewerASCIIPushTab(viewer));
245:     PetscTryTypeMethod(adapt, view, viewer);
246:     PetscCall(PetscViewerASCIIPopTab(viewer));
247:   } else if (isbinary) {
248:     char type[256];

250:     /* need to save FILE_CLASS_ID for adapt class */
251:     PetscCall(PetscStrncpy(type, ((PetscObject)adapt)->type_name, 256));
252:     PetscCall(PetscViewerBinaryWrite(viewer, type, 256, PETSC_CHAR));
253:   } else PetscTryTypeMethod(adapt, view, viewer);
254:   PetscFunctionReturn(PETSC_SUCCESS);
255: }

257: /*@
258:    TSAdaptReset - Resets a `TSAdapt` context to its defaults

260:    Collective

262:    Input Parameter:
263: .  adapt - the `TSAdapt` context obtained from `TSGetAdapt()` or `TSAdaptCreate()`

265:    Level: developer

267: .seealso: [](chapter_ts), `TSGetAdapt()`, `TSAdapt`, `TSAdaptCreate()`, `TSAdaptDestroy()`
268: @*/
269: PetscErrorCode TSAdaptReset(TSAdapt adapt)
270: {
271:   PetscFunctionBegin;
273:   PetscTryTypeMethod(adapt, reset);
274:   PetscFunctionReturn(PETSC_SUCCESS);
275: }

277: PetscErrorCode TSAdaptDestroy(TSAdapt *adapt)
278: {
279:   PetscFunctionBegin;
280:   if (!*adapt) PetscFunctionReturn(PETSC_SUCCESS);
282:   if (--((PetscObject)(*adapt))->refct > 0) {
283:     *adapt = NULL;
284:     PetscFunctionReturn(PETSC_SUCCESS);
285:   }

287:   PetscCall(TSAdaptReset(*adapt));

289:   PetscTryTypeMethod((*adapt), destroy);
290:   PetscCall(PetscViewerDestroy(&(*adapt)->monitor));
291:   PetscCall(PetscHeaderDestroy(adapt));
292:   PetscFunctionReturn(PETSC_SUCCESS);
293: }

295: /*@
296:    TSAdaptSetMonitor - Monitor the choices made by the adaptive controller

298:    Collective

300:    Input Parameters:
301: +  adapt - adaptive controller context
302: -  flg - `PETSC_TRUE` to active a monitor, `PETSC_FALSE` to disable

304:    Options Database Key:
305: .  -ts_adapt_monitor - to turn on monitoring

307:    Level: intermediate

309: .seealso: [](chapter_ts), `TSAdapt`, `TSGetAdapt()`, `TSAdaptChoose()`
310: @*/
311: PetscErrorCode TSAdaptSetMonitor(TSAdapt adapt, PetscBool flg)
312: {
313:   PetscFunctionBegin;
316:   if (flg) {
317:     if (!adapt->monitor) PetscCall(PetscViewerASCIIOpen(PetscObjectComm((PetscObject)adapt), "stdout", &adapt->monitor));
318:   } else {
319:     PetscCall(PetscViewerDestroy(&adapt->monitor));
320:   }
321:   PetscFunctionReturn(PETSC_SUCCESS);
322: }

324: /*@C
325:    TSAdaptSetCheckStage - Set a callback to check convergence for a stage

327:    Logically collective

329:    Input Parameters:
330: +  adapt - adaptive controller context
331: -  func - stage check function

333:    Arguments of func:
334: $  PetscErrorCode func(TSAdapt adapt,TS ts,PetscBool *accept)

336: +  adapt - adaptive controller context
337: .  ts - time stepping context
338: -  accept - pending choice of whether to accept, can be modified by this routine

340:    Level: advanced

342: .seealso: [](chapter_ts), `TSAdapt`, `TSGetAdapt()`, `TSAdaptChoose()`
343: @*/
344: PetscErrorCode TSAdaptSetCheckStage(TSAdapt adapt, PetscErrorCode (*func)(TSAdapt, TS, PetscReal, Vec, PetscBool *))
345: {
346:   PetscFunctionBegin;
348:   adapt->checkstage = func;
349:   PetscFunctionReturn(PETSC_SUCCESS);
350: }

352: /*@
353:    TSAdaptSetAlwaysAccept - Set whether to always accept steps regardless of
354:    any error or stability condition not meeting the prescribed goal.

356:    Logically collective

358:    Input Parameters:
359: +  adapt - time step adaptivity context, usually gotten with `TSGetAdapt()`
360: -  flag - whether to always accept steps

362:    Options Database Key:
363: .  -ts_adapt_always_accept - to always accept steps

365:    Level: intermediate

367: .seealso: [](chapter_ts), `TSAdapt`, `TSGetAdapt()`, `TSAdaptChoose()`
368: @*/
369: PetscErrorCode TSAdaptSetAlwaysAccept(TSAdapt adapt, PetscBool flag)
370: {
371:   PetscFunctionBegin;
374:   adapt->always_accept = flag;
375:   PetscFunctionReturn(PETSC_SUCCESS);
376: }

378: /*@
379:    TSAdaptSetSafety - Set safety factors for time step adaptor

381:    Logically collective

383:    Input Parameters:
384: +  adapt - adaptive controller context
385: .  safety - safety factor relative to target error/stability goal
386: -  reject_safety - extra safety factor to apply if the last step was rejected

388:    Options Database Keys:
389: +  -ts_adapt_safety <safety> - to set safety factor
390: -  -ts_adapt_reject_safety <reject_safety> - to set reject safety factor

392:    Level: intermediate

394: .seealso: [](chapter_ts), `TSAdapt`, `TSAdaptGetSafety()`, `TSAdaptChoose()`
395: @*/
396: PetscErrorCode TSAdaptSetSafety(TSAdapt adapt, PetscReal safety, PetscReal reject_safety)
397: {
398:   PetscFunctionBegin;
402:   PetscCheck(safety == PETSC_DEFAULT || safety >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Safety factor %g must be non negative", (double)safety);
403:   PetscCheck(safety == PETSC_DEFAULT || safety <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Safety factor %g must be less than one", (double)safety);
404:   PetscCheck(reject_safety == PETSC_DEFAULT || reject_safety >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Reject safety factor %g must be non negative", (double)reject_safety);
405:   PetscCheck(reject_safety == PETSC_DEFAULT || reject_safety <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Reject safety factor %g must be less than one", (double)reject_safety);
406:   if (safety != PETSC_DEFAULT) adapt->safety = safety;
407:   if (reject_safety != PETSC_DEFAULT) adapt->reject_safety = reject_safety;
408:   PetscFunctionReturn(PETSC_SUCCESS);
409: }

411: /*@
412:    TSAdaptGetSafety - Get safety factors for time step adapter

414:    Not Collective

416:    Input Parameter:
417: .  adapt - adaptive controller context

419:    Output Parameters:
420: .  safety - safety factor relative to target error/stability goal
421: +  reject_safety - extra safety factor to apply if the last step was rejected

423:    Level: intermediate

425: .seealso: [](chapter_ts), `TSAdapt`, `TSAdaptSetSafety()`, `TSAdaptChoose()`
426: @*/
427: PetscErrorCode TSAdaptGetSafety(TSAdapt adapt, PetscReal *safety, PetscReal *reject_safety)
428: {
429:   PetscFunctionBegin;
433:   if (safety) *safety = adapt->safety;
434:   if (reject_safety) *reject_safety = adapt->reject_safety;
435:   PetscFunctionReturn(PETSC_SUCCESS);
436: }

438: /*@
439:    TSAdaptSetMaxIgnore - Set error estimation threshold. Solution components below this threshold value will not be considered when computing error norms
440:    for time step adaptivity (in absolute value). A negative value (default) of the threshold leads to considering all solution components.

442:    Logically collective

444:    Input Parameters:
445: +  adapt - adaptive controller context
446: -  max_ignore - threshold for solution components that are ignored during error estimation

448:    Options Database Key:
449: .  -ts_adapt_max_ignore <max_ignore> - to set the threshold

451:    Level: intermediate

453: .seealso: [](chapter_ts), `TSAdapt`, `TSAdaptGetMaxIgnore()`, `TSAdaptChoose()`
454: @*/
455: PetscErrorCode TSAdaptSetMaxIgnore(TSAdapt adapt, PetscReal max_ignore)
456: {
457:   PetscFunctionBegin;
460:   adapt->ignore_max = max_ignore;
461:   PetscFunctionReturn(PETSC_SUCCESS);
462: }

464: /*@
465:    TSAdaptGetMaxIgnore - Get error estimation threshold. Solution components below this threshold value will not be considered when computing error norms
466:    for time step adaptivity (in absolute value).

468:    Not Collective

470:    Input Parameter:
471: .  adapt - adaptive controller context

473:    Output Parameter:
474: .  max_ignore - threshold for solution components that are ignored during error estimation

476:    Level: intermediate

478: .seealso: [](chapter_ts), `TSAdapt`, `TSAdaptSetMaxIgnore()`, `TSAdaptChoose()`
479: @*/
480: PetscErrorCode TSAdaptGetMaxIgnore(TSAdapt adapt, PetscReal *max_ignore)
481: {
482:   PetscFunctionBegin;
485:   *max_ignore = adapt->ignore_max;
486:   PetscFunctionReturn(PETSC_SUCCESS);
487: }

489: /*@
490:    TSAdaptSetClip - Sets the admissible decrease/increase factor in step size in the time step adapter

492:    Logically collective

494:    Input Parameters:
495: +  adapt - adaptive controller context
496: .  low - admissible decrease factor
497: -  high - admissible increase factor

499:    Options Database Key:
500: .  -ts_adapt_clip <low>,<high> - to set admissible time step decrease and increase factors

502:    Level: intermediate

504: .seealso: [](chapter_ts), `TSAdapt`, `TSAdaptChoose()`, `TSAdaptGetClip()`, `TSAdaptSetScaleSolveFailed()`
505: @*/
506: PetscErrorCode TSAdaptSetClip(TSAdapt adapt, PetscReal low, PetscReal high)
507: {
508:   PetscFunctionBegin;
512:   PetscCheck(low == PETSC_DEFAULT || low >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Decrease factor %g must be non negative", (double)low);
513:   PetscCheck(low == PETSC_DEFAULT || low <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Decrease factor %g must be less than one", (double)low);
514:   PetscCheck(high == PETSC_DEFAULT || high >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Increase factor %g must be greater than one", (double)high);
515:   if (low != PETSC_DEFAULT) adapt->clip[0] = low;
516:   if (high != PETSC_DEFAULT) adapt->clip[1] = high;
517:   PetscFunctionReturn(PETSC_SUCCESS);
518: }

520: /*@
521:    TSAdaptGetClip - Gets the admissible decrease/increase factor in step size in the time step adapter

523:    Not Collective

525:    Input Parameter:
526: .  adapt - adaptive controller context

528:    Output Parameters:
529: +  low - optional, admissible decrease factor
530: -  high - optional, admissible increase factor

532:    Level: intermediate

534: .seealso: [](chapter_ts), `TSAdapt`, `TSAdaptChoose()`, `TSAdaptSetClip()`, `TSAdaptSetScaleSolveFailed()`
535: @*/
536: PetscErrorCode TSAdaptGetClip(TSAdapt adapt, PetscReal *low, PetscReal *high)
537: {
538:   PetscFunctionBegin;
542:   if (low) *low = adapt->clip[0];
543:   if (high) *high = adapt->clip[1];
544:   PetscFunctionReturn(PETSC_SUCCESS);
545: }

547: /*@
548:    TSAdaptSetScaleSolveFailed - Scale step size by this factor if solve fails

550:    Logically collective

552:    Input Parameters:
553: +  adapt - adaptive controller context
554: -  scale - scale

556:    Options Database Key:
557: .  -ts_adapt_scale_solve_failed <scale> - to set scale step by this factor if solve fails

559:    Level: intermediate

561: .seealso: [](chapter_ts), `TSAdapt`, `TSAdaptChoose()`, `TSAdaptGetScaleSolveFailed()`, `TSAdaptGetClip()`
562: @*/
563: PetscErrorCode TSAdaptSetScaleSolveFailed(TSAdapt adapt, PetscReal scale)
564: {
565:   PetscFunctionBegin;
568:   PetscCheck(scale == PETSC_DEFAULT || scale > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Scale factor %g must be positive", (double)scale);
569:   PetscCheck(scale == PETSC_DEFAULT || scale <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Scale factor %g must be less than one", (double)scale);
570:   if (scale != PETSC_DEFAULT) adapt->scale_solve_failed = scale;
571:   PetscFunctionReturn(PETSC_SUCCESS);
572: }

574: /*@
575:    TSAdaptGetScaleSolveFailed - Gets the admissible decrease/increase factor in step size

577:    Not Collective

579:    Input Parameter:
580: .  adapt - adaptive controller context

582:    Output Parameter:
583: .  scale - scale factor

585:    Level: intermediate

587: .seealso: [](chapter_ts), `TSAdapt`, `TSAdaptChoose()`, `TSAdaptSetScaleSolveFailed()`, `TSAdaptSetClip()`
588: @*/
589: PetscErrorCode TSAdaptGetScaleSolveFailed(TSAdapt adapt, PetscReal *scale)
590: {
591:   PetscFunctionBegin;
594:   if (scale) *scale = adapt->scale_solve_failed;
595:   PetscFunctionReturn(PETSC_SUCCESS);
596: }

598: /*@
599:    TSAdaptSetStepLimits - Set the minimum and maximum step sizes to be considered by the time step controller

601:    Logically collective

603:    Input Parameters:
604: +  adapt - time step adaptivity context, usually gotten with `TSGetAdapt()`
605: .  hmin - minimum time step
606: -  hmax - maximum time step

608:    Options Database Keys:
609: +  -ts_adapt_dt_min <min> - to set minimum time step
610: -  -ts_adapt_dt_max <max> - to set maximum time step

612:    Level: intermediate

614: .seealso: [](chapter_ts), `TSAdapt`, `TSAdaptGetStepLimits()`, `TSAdaptChoose()`
615: @*/
616: PetscErrorCode TSAdaptSetStepLimits(TSAdapt adapt, PetscReal hmin, PetscReal hmax)
617: {
618:   PetscFunctionBegin;
622:   PetscCheck(hmin == PETSC_DEFAULT || hmin >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Minimum time step %g must be non negative", (double)hmin);
623:   PetscCheck(hmax == PETSC_DEFAULT || hmax >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Minimum time step %g must be non negative", (double)hmax);
624:   if (hmin != PETSC_DEFAULT) adapt->dt_min = hmin;
625:   if (hmax != PETSC_DEFAULT) adapt->dt_max = hmax;
626:   hmin = adapt->dt_min;
627:   hmax = adapt->dt_max;
628:   PetscCheck(hmax > hmin, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Maximum time step %g must greater than minimum time step %g", (double)hmax, (double)hmin);
629:   PetscFunctionReturn(PETSC_SUCCESS);
630: }

632: /*@
633:    TSAdaptGetStepLimits - Get the minimum and maximum step sizes to be considered by the time step controller

635:    Not Collective

637:    Input Parameter:
638: .  adapt - time step adaptivity context, usually gotten with `TSGetAdapt()`

640:    Output Parameters:
641: +  hmin - minimum time step
642: -  hmax - maximum time step

644:    Level: intermediate

646: .seealso: [](chapter_ts), `TSAdapt`, `TSAdaptSetStepLimits()`, `TSAdaptChoose()`
647: @*/
648: PetscErrorCode TSAdaptGetStepLimits(TSAdapt adapt, PetscReal *hmin, PetscReal *hmax)
649: {
650:   PetscFunctionBegin;
654:   if (hmin) *hmin = adapt->dt_min;
655:   if (hmax) *hmax = adapt->dt_max;
656:   PetscFunctionReturn(PETSC_SUCCESS);
657: }

659: /*
660:    TSAdaptSetFromOptions - Sets various `TSAdapt` parameters from user options.

662:    Collective

664:    Input Parameter:
665: .  adapt - the `TSAdapt` context

667:    Options Database Keys:
668: +  -ts_adapt_type <type> - algorithm to use for adaptivity
669: .  -ts_adapt_always_accept - always accept steps regardless of error/stability goals
670: .  -ts_adapt_safety <safety> - safety factor relative to target error/stability goal
671: .  -ts_adapt_reject_safety <safety> - extra safety factor to apply if the last step was rejected
672: .  -ts_adapt_clip <low,high> - admissible time step decrease and increase factors
673: .  -ts_adapt_dt_min <min> - minimum timestep to use
674: .  -ts_adapt_dt_max <max> - maximum timestep to use
675: .  -ts_adapt_scale_solve_failed <scale> - scale timestep by this factor if a solve fails
676: .  -ts_adapt_wnormtype <2 or infinity> - type of norm for computing error estimates
677: -  -ts_adapt_time_step_increase_delay - number of timesteps to delay increasing the time step after it has been decreased due to failed solver

679:    Level: advanced

681:    Note:
682:    This function is automatically called by `TSSetFromOptions()`

684: .seealso: [](chapter_ts), `TSAdapt`, `TSGetAdapt()`, `TSAdaptSetType()`, `TSAdaptSetAlwaysAccept()`, `TSAdaptSetSafety()`,
685:           `TSAdaptSetClip()`, `TSAdaptSetScaleSolveFailed()`, `TSAdaptSetStepLimits()`, `TSAdaptSetMonitor()`
686: */
687: PetscErrorCode TSAdaptSetFromOptions(TSAdapt adapt, PetscOptionItems *PetscOptionsObject)
688: {
689:   char      type[256] = TSADAPTBASIC;
690:   PetscReal safety, reject_safety, clip[2], scale, hmin, hmax;
691:   PetscBool set, flg;
692:   PetscInt  two;

694:   PetscFunctionBegin;
696:   /* This should use PetscOptionsBegin() if/when this becomes an object used outside of TS, but currently this
697:    * function can only be called from inside TSSetFromOptions()  */
698:   PetscOptionsHeadBegin(PetscOptionsObject, "TS Adaptivity options");
699:   PetscCall(PetscOptionsFList("-ts_adapt_type", "Algorithm to use for adaptivity", "TSAdaptSetType", TSAdaptList, ((PetscObject)adapt)->type_name ? ((PetscObject)adapt)->type_name : type, type, sizeof(type), &flg));
700:   if (flg || !((PetscObject)adapt)->type_name) PetscCall(TSAdaptSetType(adapt, type));

702:   PetscCall(PetscOptionsBool("-ts_adapt_always_accept", "Always accept the step", "TSAdaptSetAlwaysAccept", adapt->always_accept, &flg, &set));
703:   if (set) PetscCall(TSAdaptSetAlwaysAccept(adapt, flg));

705:   safety        = adapt->safety;
706:   reject_safety = adapt->reject_safety;
707:   PetscCall(PetscOptionsReal("-ts_adapt_safety", "Safety factor relative to target error/stability goal", "TSAdaptSetSafety", safety, &safety, &set));
708:   PetscCall(PetscOptionsReal("-ts_adapt_reject_safety", "Extra safety factor to apply if the last step was rejected", "TSAdaptSetSafety", reject_safety, &reject_safety, &flg));
709:   if (set || flg) PetscCall(TSAdaptSetSafety(adapt, safety, reject_safety));

711:   two     = 2;
712:   clip[0] = adapt->clip[0];
713:   clip[1] = adapt->clip[1];
714:   PetscCall(PetscOptionsRealArray("-ts_adapt_clip", "Admissible decrease/increase factor in step size", "TSAdaptSetClip", clip, &two, &set));
715:   PetscCheck(!set || (two == 2), PetscObjectComm((PetscObject)adapt), PETSC_ERR_ARG_OUTOFRANGE, "Must give exactly two values to -ts_adapt_clip");
716:   if (set) PetscCall(TSAdaptSetClip(adapt, clip[0], clip[1]));

718:   hmin = adapt->dt_min;
719:   hmax = adapt->dt_max;
720:   PetscCall(PetscOptionsReal("-ts_adapt_dt_min", "Minimum time step considered", "TSAdaptSetStepLimits", hmin, &hmin, &set));
721:   PetscCall(PetscOptionsReal("-ts_adapt_dt_max", "Maximum time step considered", "TSAdaptSetStepLimits", hmax, &hmax, &flg));
722:   if (set || flg) PetscCall(TSAdaptSetStepLimits(adapt, hmin, hmax));

724:   PetscCall(PetscOptionsReal("-ts_adapt_max_ignore", "Adaptor ignores (absolute) solution values smaller than this value", "", adapt->ignore_max, &adapt->ignore_max, &set));
725:   PetscCall(PetscOptionsBool("-ts_adapt_glee_use_local", "GLEE adaptor uses local error estimation for step control", "", adapt->glee_use_local, &adapt->glee_use_local, &set));

727:   PetscCall(PetscOptionsReal("-ts_adapt_scale_solve_failed", "Scale step by this factor if solve fails", "TSAdaptSetScaleSolveFailed", adapt->scale_solve_failed, &scale, &set));
728:   if (set) PetscCall(TSAdaptSetScaleSolveFailed(adapt, scale));

730:   PetscCall(PetscOptionsEnum("-ts_adapt_wnormtype", "Type of norm computed for error estimation", "", NormTypes, (PetscEnum)adapt->wnormtype, (PetscEnum *)&adapt->wnormtype, NULL));
731:   PetscCheck(adapt->wnormtype == NORM_2 || adapt->wnormtype == NORM_INFINITY, PetscObjectComm((PetscObject)adapt), PETSC_ERR_SUP, "Only 2-norm and infinite norm supported");

733:   PetscCall(PetscOptionsInt("-ts_adapt_time_step_increase_delay", "Number of timesteps to delay increasing the time step after it has been decreased due to failed solver", "TSAdaptSetTimeStepIncreaseDelay", adapt->timestepjustdecreased_delay, &adapt->timestepjustdecreased_delay, NULL));

735:   PetscCall(PetscOptionsBool("-ts_adapt_monitor", "Print choices made by adaptive controller", "TSAdaptSetMonitor", adapt->monitor ? PETSC_TRUE : PETSC_FALSE, &flg, &set));
736:   if (set) PetscCall(TSAdaptSetMonitor(adapt, flg));

738:   PetscTryTypeMethod(adapt, setfromoptions, PetscOptionsObject);
739:   PetscOptionsHeadEnd();
740:   PetscFunctionReturn(PETSC_SUCCESS);
741: }

743: /*@
744:    TSAdaptCandidatesClear - clear any previously set candidate schemes

746:    Logically collective

748:    Input Parameter:
749: .  adapt - adaptive controller

751:    Level: developer

753: .seealso: [](chapter_ts), `TSAdapt`, `TSAdaptCreate()`, `TSAdaptCandidateAdd()`, `TSAdaptChoose()`
754: @*/
755: PetscErrorCode TSAdaptCandidatesClear(TSAdapt adapt)
756: {
757:   PetscFunctionBegin;
759:   PetscCall(PetscMemzero(&adapt->candidates, sizeof(adapt->candidates)));
760:   PetscFunctionReturn(PETSC_SUCCESS);
761: }

763: /*@C
764:    TSAdaptCandidateAdd - add a candidate scheme for the adaptive controller to select from

766:    Logically collective

768:    Input Parameters:
769: +  adapt - time step adaptivity context, obtained with `TSGetAdapt()` or `TSAdaptCreate()`
770: .  name - name of the candidate scheme to add
771: .  order - order of the candidate scheme
772: .  stageorder - stage order of the candidate scheme
773: .  ccfl - stability coefficient relative to explicit Euler, used for CFL constraints
774: .  cost - relative measure of the amount of work required for the candidate scheme
775: -  inuse - indicates that this scheme is the one currently in use, this flag can only be set for one scheme

777:    Level: developer

779:    Fortran Note:
780:    This routine is not available in Fortran.

782: .seealso: [](chapter_ts), `TSAdapt`, `TSAdaptCandidatesClear()`, `TSAdaptChoose()`
783: @*/
784: PetscErrorCode TSAdaptCandidateAdd(TSAdapt adapt, const char name[], PetscInt order, PetscInt stageorder, PetscReal ccfl, PetscReal cost, PetscBool inuse)
785: {
786:   PetscInt c;

788:   PetscFunctionBegin;
790:   PetscCheck(order >= 1, PetscObjectComm((PetscObject)adapt), PETSC_ERR_ARG_OUTOFRANGE, "Classical order %" PetscInt_FMT " must be a positive integer", order);
791:   if (inuse) {
792:     PetscCheck(!adapt->candidates.inuse_set, PetscObjectComm((PetscObject)adapt), PETSC_ERR_ARG_WRONGSTATE, "Cannot set the inuse method twice, maybe forgot to call TSAdaptCandidatesClear()");
793:     adapt->candidates.inuse_set = PETSC_TRUE;
794:   }
795:   /* first slot if this is the current scheme, otherwise the next available slot */
796:   c = inuse ? 0 : !adapt->candidates.inuse_set + adapt->candidates.n;

798:   adapt->candidates.name[c]       = name;
799:   adapt->candidates.order[c]      = order;
800:   adapt->candidates.stageorder[c] = stageorder;
801:   adapt->candidates.ccfl[c]       = ccfl;
802:   adapt->candidates.cost[c]       = cost;
803:   adapt->candidates.n++;
804:   PetscFunctionReturn(PETSC_SUCCESS);
805: }

807: /*@C
808:    TSAdaptCandidatesGet - Get the list of candidate orders of accuracy and cost

810:    Not Collective

812:    Input Parameter:
813: .  adapt - time step adaptivity context

815:    Output Parameters:
816: +  n - number of candidate schemes, always at least 1
817: .  order - the order of each candidate scheme
818: .  stageorder - the stage order of each candidate scheme
819: .  ccfl - the CFL coefficient of each scheme
820: -  cost - the relative cost of each scheme

822:    Level: developer

824:    Note:
825:    The current scheme is always returned in the first slot

827: .seealso: [](chapter_ts), `TSAdapt`, `TSAdaptCandidatesClear()`, `TSAdaptCandidateAdd()`, `TSAdaptChoose()`
828: @*/
829: PetscErrorCode TSAdaptCandidatesGet(TSAdapt adapt, PetscInt *n, const PetscInt **order, const PetscInt **stageorder, const PetscReal **ccfl, const PetscReal **cost)
830: {
831:   PetscFunctionBegin;
833:   if (n) *n = adapt->candidates.n;
834:   if (order) *order = adapt->candidates.order;
835:   if (stageorder) *stageorder = adapt->candidates.stageorder;
836:   if (ccfl) *ccfl = adapt->candidates.ccfl;
837:   if (cost) *cost = adapt->candidates.cost;
838:   PetscFunctionReturn(PETSC_SUCCESS);
839: }

841: /*@C
842:    TSAdaptChoose - choose which method and step size to use for the next step

844:    Collective

846:    Input Parameters:
847: +  adapt - adaptive controller
848: .  ts - time stepper
849: -  h - current step size

851:    Output Parameters:
852: +  next_sc - optional, scheme to use for the next step
853: .  next_h - step size to use for the next step
854: -  accept - `PETSC_TRUE` to accept the current step, `PETSC_FALSE` to repeat the current step with the new step size

856:    Level: developer

858:    Note:
859:    The input value of parameter accept is retained from the last time step, so it will be `PETSC_FALSE` if the step is
860:    being retried after an initial rejection.

862: .seealso: [](chapter_ts), `TSAdapt`, `TSAdaptCandidatesClear()`, `TSAdaptCandidateAdd()`
863: @*/
864: PetscErrorCode TSAdaptChoose(TSAdapt adapt, TS ts, PetscReal h, PetscInt *next_sc, PetscReal *next_h, PetscBool *accept)
865: {
866:   PetscInt  ncandidates = adapt->candidates.n;
867:   PetscInt  scheme      = 0;
868:   PetscReal wlte        = -1.0;
869:   PetscReal wltea       = -1.0;
870:   PetscReal wlter       = -1.0;

872:   PetscFunctionBegin;
878:   if (next_sc) *next_sc = 0;

880:   /* Do not mess with adaptivity while handling events*/
881:   if (ts->event && ts->event->status != TSEVENT_NONE) {
882:     *next_h = h;
883:     *accept = PETSC_TRUE;
884:     PetscFunctionReturn(PETSC_SUCCESS);
885:   }

887:   PetscUseTypeMethod(adapt, choose, ts, h, &scheme, next_h, accept, &wlte, &wltea, &wlter);
888:   PetscCheck(scheme >= 0 && (ncandidates <= 0 || scheme < ncandidates), PetscObjectComm((PetscObject)adapt), PETSC_ERR_ARG_OUTOFRANGE, "Chosen scheme %" PetscInt_FMT " not in valid range 0..%" PetscInt_FMT, scheme, ncandidates - 1);
889:   PetscCheck(*next_h >= 0, PetscObjectComm((PetscObject)adapt), PETSC_ERR_ARG_OUTOFRANGE, "Computed step size %g must be positive", (double)*next_h);
890:   if (next_sc) *next_sc = scheme;

892:   if (*accept && ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP) {
893:     /* Increase/reduce step size if end time of next step is close to or overshoots max time */
894:     PetscReal t = ts->ptime + ts->time_step, h = *next_h;
895:     PetscReal tend = t + h, tmax, hmax;
896:     PetscReal a    = (PetscReal)(1.0 + adapt->matchstepfac[0]);
897:     PetscReal b    = adapt->matchstepfac[1];

899:     if (ts->tspan) {
900:       if (PetscIsCloseAtTol(t, ts->tspan->span_times[ts->tspan->spanctr], ts->tspan->reltol * h + ts->tspan->abstol, 0)) /* hit a span time point */
901:         if (ts->tspan->spanctr + 1 < ts->tspan->num_span_times) tmax = ts->tspan->span_times[ts->tspan->spanctr + 1];
902:         else tmax = ts->max_time; /* hit the last span time point */
903:       else tmax = ts->tspan->span_times[ts->tspan->spanctr];
904:     } else tmax = ts->max_time;
905:     hmax = tmax - t;
906:     if (t < tmax && tend > tmax) *next_h = hmax;
907:     if (t < tmax && tend < tmax && h * b > hmax) *next_h = hmax / 2;
908:     if (t < tmax && tend < tmax && h * a > hmax) *next_h = hmax;
909:     /* if step size is changed to match a span time point */
910:     if (ts->tspan && h != *next_h && !adapt->dt_span_cached) adapt->dt_span_cached = h;
911:     /* reset time step after a span time point */
912:     if (ts->tspan && h == *next_h && adapt->dt_span_cached && PetscIsCloseAtTol(t, ts->tspan->span_times[ts->tspan->spanctr], ts->tspan->reltol * h + ts->tspan->abstol, 0)) {
913:       *next_h               = adapt->dt_span_cached;
914:       adapt->dt_span_cached = 0;
915:     }
916:   }
917:   if (adapt->monitor) {
918:     const char *sc_name = (scheme < ncandidates) ? adapt->candidates.name[scheme] : "";
919:     PetscCall(PetscViewerASCIIAddTab(adapt->monitor, ((PetscObject)adapt)->tablevel));
920:     if (wlte < 0) {
921:       PetscCall(PetscViewerASCIIPrintf(adapt->monitor, "    TSAdapt %s %s %" PetscInt_FMT ":%s step %3" PetscInt_FMT " %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",
922:                                        (double)ts->ptime, (double)h, (double)*next_h));
923:     } else {
924:       PetscCall(PetscViewerASCIIPrintf(adapt->monitor, "    TSAdapt %s %s %" PetscInt_FMT ":%s step %3" PetscInt_FMT " %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",
925:                                        (double)ts->ptime, (double)h, (double)*next_h, (double)wlte, (double)wltea, (double)wlter));
926:     }
927:     PetscCall(PetscViewerASCIISubtractTab(adapt->monitor, ((PetscObject)adapt)->tablevel));
928:   }
929:   PetscFunctionReturn(PETSC_SUCCESS);
930: }

932: /*@
933:    TSAdaptSetTimeStepIncreaseDelay - The number of timesteps to wait after a decrease in the timestep due to failed solver
934:                                      before increasing the time step.

936:    Logicially Collective

938:    Input Parameters:
939: +  adapt - adaptive controller context
940: -  cnt - the number of timesteps

942:    Options Database Key:
943: .  -ts_adapt_time_step_increase_delay cnt - number of steps to delay the increase

945:    Level: advanced

947:    Notes:
948:    This is to prevent an adaptor from bouncing back and forth between two nearby timesteps. The default is 0.

950:    The successful use of this option is problem dependent

952:    Developer Note:
953:    There is no theory to support this option

955: .seealso: [](chapter_ts), `TSAdapt`
956: @*/
957: PetscErrorCode TSAdaptSetTimeStepIncreaseDelay(TSAdapt adapt, PetscInt cnt)
958: {
959:   PetscFunctionBegin;
960:   adapt->timestepjustdecreased_delay = cnt;
961:   PetscFunctionReturn(PETSC_SUCCESS);
962: }

964: /*@
965:    TSAdaptCheckStage - checks whether to accept a stage, (e.g. reject and change time step size if nonlinear solve fails or solution vector is infeasible)

967:    Collective

969:    Input Parameters:
970: +  adapt - adaptive controller context
971: .  ts - time stepper
972: .  t - Current simulation time
973: -  Y - Current solution vector

975:    Output Parameter:
976: .  accept - `PETSC_TRUE` to accept the stage, `PETSC_FALSE` to reject

978:    Level: developer

980: .seealso: [](chapter_ts), `TSAdapt`
981: @*/
982: PetscErrorCode TSAdaptCheckStage(TSAdapt adapt, TS ts, PetscReal t, Vec Y, PetscBool *accept)
983: {
984:   SNESConvergedReason snesreason = SNES_CONVERGED_ITERATING;

986:   PetscFunctionBegin;

991:   if (ts->snes) PetscCall(SNESGetConvergedReason(ts->snes, &snesreason));
992:   if (snesreason < 0) {
993:     *accept = PETSC_FALSE;
994:     if (++ts->num_snes_failures >= ts->max_snes_failures && ts->max_snes_failures > 0) {
995:       ts->reason = TS_DIVERGED_NONLINEAR_SOLVE;
996:       PetscCall(PetscInfo(ts, "Step=%" PetscInt_FMT ", nonlinear solve failures %" PetscInt_FMT " greater than current TS allowed, stopping solve\n", ts->steps, ts->num_snes_failures));
997:       if (adapt->monitor) {
998:         PetscCall(PetscViewerASCIIAddTab(adapt->monitor, ((PetscObject)adapt)->tablevel));
999:         PetscCall(PetscViewerASCIIPrintf(adapt->monitor, "    TSAdapt %s step %3" PetscInt_FMT " stage rejected t=%-11g+%10.3e, nonlinear solve failures %" PetscInt_FMT " greater than current TS allowed\n", ((PetscObject)adapt)->type_name, ts->steps,
1000:                                          (double)ts->ptime, (double)ts->time_step, ts->num_snes_failures));
1001:         PetscCall(PetscViewerASCIISubtractTab(adapt->monitor, ((PetscObject)adapt)->tablevel));
1002:       }
1003:     }
1004:   } else {
1005:     *accept = PETSC_TRUE;
1006:     PetscCall(TSFunctionDomainError(ts, t, Y, accept));
1007:     if (*accept && adapt->checkstage) {
1008:       PetscCall((*adapt->checkstage)(adapt, ts, t, Y, accept));
1009:       if (!*accept) {
1010:         PetscCall(PetscInfo(ts, "Step=%" PetscInt_FMT ", solution rejected by user function provided by TSSetFunctionDomainError()\n", ts->steps));
1011:         if (adapt->monitor) {
1012:           PetscCall(PetscViewerASCIIAddTab(adapt->monitor, ((PetscObject)adapt)->tablevel));
1013:           PetscCall(PetscViewerASCIIPrintf(adapt->monitor, "    TSAdapt %s step %3" PetscInt_FMT " stage rejected by user function provided by TSSetFunctionDomainError()\n", ((PetscObject)adapt)->type_name, ts->steps));
1014:           PetscCall(PetscViewerASCIISubtractTab(adapt->monitor, ((PetscObject)adapt)->tablevel));
1015:         }
1016:       }
1017:     }
1018:   }

1020:   if (!(*accept) && !ts->reason) {
1021:     PetscReal dt, new_dt;
1022:     PetscCall(TSGetTimeStep(ts, &dt));
1023:     new_dt = dt * adapt->scale_solve_failed;
1024:     PetscCall(TSSetTimeStep(ts, new_dt));
1025:     adapt->timestepjustdecreased += adapt->timestepjustdecreased_delay;
1026:     if (adapt->monitor) {
1027:       PetscCall(PetscViewerASCIIAddTab(adapt->monitor, ((PetscObject)adapt)->tablevel));
1028:       PetscCall(PetscViewerASCIIPrintf(adapt->monitor, "    TSAdapt %s step %3" PetscInt_FMT " 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));
1029:       PetscCall(PetscViewerASCIISubtractTab(adapt->monitor, ((PetscObject)adapt)->tablevel));
1030:     }
1031:   }
1032:   PetscFunctionReturn(PETSC_SUCCESS);
1033: }

1035: /*@
1036:   TSAdaptCreate - create an adaptive controller context for time stepping

1038:   Collective

1040:   Input Parameter:
1041: . comm - The communicator

1043:   Output Parameter:
1044: . adapt - new `TSAdapt` object

1046:   Level: developer

1048:   Note:
1049:   `TSAdapt` creation is handled by `TS`, so users should not need to call this function.

1051: .seealso: [](chapter_ts), `TSAdapt`, `TSGetAdapt()`, `TSAdaptSetType()`, `TSAdaptDestroy()`
1052: @*/
1053: PetscErrorCode TSAdaptCreate(MPI_Comm comm, TSAdapt *inadapt)
1054: {
1055:   TSAdapt adapt;

1057:   PetscFunctionBegin;
1059:   *inadapt = NULL;
1060:   PetscCall(TSAdaptInitializePackage());

1062:   PetscCall(PetscHeaderCreate(adapt, TSADAPT_CLASSID, "TSAdapt", "Time stepping adaptivity", "TS", comm, TSAdaptDestroy, TSAdaptView));

1064:   adapt->always_accept      = PETSC_FALSE;
1065:   adapt->safety             = 0.9;
1066:   adapt->reject_safety      = 0.5;
1067:   adapt->clip[0]            = 0.1;
1068:   adapt->clip[1]            = 10.;
1069:   adapt->dt_min             = 1e-20;
1070:   adapt->dt_max             = 1e+20;
1071:   adapt->ignore_max         = -1.0;
1072:   adapt->glee_use_local     = PETSC_TRUE;
1073:   adapt->scale_solve_failed = 0.25;
1074:   /* these two safety factors are not public, and they are used only in the TS_EXACTFINALTIME_MATCHSTEP case
1075:      to prevent from situations were unreasonably small time steps are taken in order to match the final time */
1076:   adapt->matchstepfac[0]             = 0.01; /* allow 1% step size increase in the last step */
1077:   adapt->matchstepfac[1]             = 2.0;  /* halve last step if it is greater than what remains divided this factor */
1078:   adapt->wnormtype                   = NORM_2;
1079:   adapt->timestepjustdecreased_delay = 0;

1081:   *inadapt = adapt;
1082:   PetscFunctionReturn(PETSC_SUCCESS);
1083: }