Actual source code: tsadapt.c
1: #include <petsc/private/tsimpl.h>
3: PetscClassId TSADAPT_CLASSID;
5: static PetscFunctionList TSAdaptList;
6: static PetscBool TSAdaptPackageInitialized;
7: static PetscBool TSAdaptRegisterAllCalled;
9: PETSC_EXTERN PetscErrorCode TSAdaptCreate_None(TSAdapt);
10: PETSC_EXTERN PetscErrorCode TSAdaptCreate_Basic(TSAdapt);
11: PETSC_EXTERN PetscErrorCode TSAdaptCreate_DSP(TSAdapt);
12: PETSC_EXTERN PetscErrorCode TSAdaptCreate_CFL(TSAdapt);
13: PETSC_EXTERN PetscErrorCode TSAdaptCreate_GLEE(TSAdapt);
14: PETSC_EXTERN PetscErrorCode TSAdaptCreate_History(TSAdapt);
16: /*@C
17: TSAdaptRegister - adds a TSAdapt implementation
19: Not Collective, No Fortran Support
21: Input Parameters:
22: + sname - name of user-defined adaptivity scheme
23: - function - routine to create method context
25: Level: advanced
27: Notes:
28: `TSAdaptRegister()` may be called multiple times to add several user-defined families.
30: Example Usage:
31: .vb
32: TSAdaptRegister("my_scheme", MySchemeCreate);
33: .ve
35: Then, your scheme can be chosen with the procedural interface via
36: .vb
37: TSAdaptSetType(ts, "my_scheme")
38: .ve
39: or at runtime via the option
40: .vb
41: -ts_adapt_type my_scheme
42: .ve
44: .seealso: [](ch_ts), [](sec_ts_error_control), `TSAdaptRegisterAll()`
45: @*/
46: PetscErrorCode TSAdaptRegister(const char sname[], PetscErrorCode (*function)(TSAdapt))
47: {
48: PetscFunctionBegin;
49: PetscCall(TSAdaptInitializePackage());
50: PetscCall(PetscFunctionListAdd(&TSAdaptList, sname, function));
51: PetscFunctionReturn(PETSC_SUCCESS);
52: }
54: /*@C
55: TSAdaptRegisterAll - Registers all of the adaptivity schemes in `TSAdapt`
57: Not Collective
59: Level: advanced
61: .seealso: [](ch_ts), `TSAdaptRegisterDestroy()`
62: @*/
63: PetscErrorCode TSAdaptRegisterAll(void)
64: {
65: PetscFunctionBegin;
66: if (TSAdaptRegisterAllCalled) PetscFunctionReturn(PETSC_SUCCESS);
67: TSAdaptRegisterAllCalled = PETSC_TRUE;
68: PetscCall(TSAdaptRegister(TSADAPTNONE, TSAdaptCreate_None));
69: PetscCall(TSAdaptRegister(TSADAPTBASIC, TSAdaptCreate_Basic));
70: PetscCall(TSAdaptRegister(TSADAPTDSP, TSAdaptCreate_DSP));
71: PetscCall(TSAdaptRegister(TSADAPTCFL, TSAdaptCreate_CFL));
72: PetscCall(TSAdaptRegister(TSADAPTGLEE, TSAdaptCreate_GLEE));
73: PetscCall(TSAdaptRegister(TSADAPTHISTORY, TSAdaptCreate_History));
74: PetscFunctionReturn(PETSC_SUCCESS);
75: }
77: /*@C
78: TSAdaptFinalizePackage - This function destroys everything in the `TS` package. It is
79: called from `PetscFinalize()`.
81: Level: developer
83: .seealso: [](ch_ts), `PetscFinalize()`
84: @*/
85: PetscErrorCode TSAdaptFinalizePackage(void)
86: {
87: PetscFunctionBegin;
88: PetscCall(PetscFunctionListDestroy(&TSAdaptList));
89: TSAdaptPackageInitialized = PETSC_FALSE;
90: TSAdaptRegisterAllCalled = PETSC_FALSE;
91: PetscFunctionReturn(PETSC_SUCCESS);
92: }
94: /*@C
95: TSAdaptInitializePackage - This function initializes everything in the `TSAdapt` package. It is
96: called from `TSInitializePackage()`.
98: Level: developer
100: .seealso: [](ch_ts), `PetscInitialize()`
101: @*/
102: PetscErrorCode TSAdaptInitializePackage(void)
103: {
104: PetscFunctionBegin;
105: if (TSAdaptPackageInitialized) PetscFunctionReturn(PETSC_SUCCESS);
106: TSAdaptPackageInitialized = PETSC_TRUE;
107: PetscCall(PetscClassIdRegister("TSAdapt", &TSADAPT_CLASSID));
108: PetscCall(TSAdaptRegisterAll());
109: PetscCall(PetscRegisterFinalize(TSAdaptFinalizePackage));
110: PetscFunctionReturn(PETSC_SUCCESS);
111: }
113: /*@
114: TSAdaptSetType - sets the approach used for the error adapter
116: Logicially Collective
118: Input Parameters:
119: + adapt - the `TS` adapter, most likely obtained with `TSGetAdapt()`
120: - type - one of the `TSAdaptType`
122: Options Database Key:
123: . -ts_adapt_type (basic|dsp|none|cfl|glee|history) - to set the adapter type
125: Level: intermediate
127: .seealso: [](ch_ts), [](sec_ts_error_control), `TSGetAdapt()`, `TSAdaptDestroy()`, `TSAdaptType`, `TSAdaptGetType()`
128: @*/
129: PetscErrorCode TSAdaptSetType(TSAdapt adapt, TSAdaptType type)
130: {
131: PetscBool match;
132: PetscErrorCode (*r)(TSAdapt);
134: PetscFunctionBegin;
136: PetscAssertPointer(type, 2);
137: PetscCall(PetscObjectTypeCompare((PetscObject)adapt, type, &match));
138: if (match) PetscFunctionReturn(PETSC_SUCCESS);
139: PetscCall(PetscFunctionListFind(TSAdaptList, type, &r));
140: PetscCheck(r, PetscObjectComm((PetscObject)adapt), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown TSAdapt type \"%s\" given", type);
141: PetscTryTypeMethod(adapt, destroy);
142: PetscCall(PetscMemzero(adapt->ops, sizeof(struct _TSAdaptOps)));
143: PetscCall(PetscObjectChangeTypeName((PetscObject)adapt, type));
144: PetscCall((*r)(adapt));
145: PetscFunctionReturn(PETSC_SUCCESS);
146: }
148: /*@
149: TSAdaptGetType - gets the `TS` adapter method type (as a string).
151: Not Collective
153: Input Parameter:
154: . adapt - The `TS` adapter, most likely obtained with `TSGetAdapt()`
156: Output Parameter:
157: . type - The name of `TS` adapter method
159: Level: intermediate
161: .seealso: [](ch_ts), [](sec_ts_error_control), `TSAdapt`, `TSAdaptType`, `TSAdaptSetType()`
162: @*/
163: PetscErrorCode TSAdaptGetType(TSAdapt adapt, TSAdaptType *type)
164: {
165: PetscFunctionBegin;
167: PetscAssertPointer(type, 2);
168: *type = ((PetscObject)adapt)->type_name;
169: PetscFunctionReturn(PETSC_SUCCESS);
170: }
172: /*@C
173: TSAdaptSetOptionsPrefix - Sets the prefix used for searching for `TSAdapt` options in the options database
175: Logically Collective
177: Input Parameters:
178: + adapt - the `TSAdapt` context, most likely obtained with `TSGetAdapt()`
179: - prefix - the prefix to prepend to all option names
181: Level: advanced
183: .seealso: [](ch_ts), [](sec_ts_error_control), `TSAdapt`, `TSGetAdapt()`, `TSSetOptionsPrefix()`
184: @*/
185: PetscErrorCode TSAdaptSetOptionsPrefix(TSAdapt adapt, const char prefix[])
186: {
187: PetscFunctionBegin;
189: PetscCall(PetscObjectSetOptionsPrefix((PetscObject)adapt, prefix));
190: PetscFunctionReturn(PETSC_SUCCESS);
191: }
193: /*@
194: TSAdaptLoad - Loads a TSAdapt that has been stored in binary with `TSAdaptView()`.
196: Collective
198: Input Parameters:
199: + adapt - the newly loaded `TSAdapt`, this needs to have been created with `TSAdaptCreate()` or
200: some related function before a call to `TSAdaptLoad()`.
201: - viewer - binary file viewer, obtained from `PetscViewerBinaryOpen()` or
202: HDF5 file viewer, obtained from `PetscViewerHDF5Open()`
204: Level: intermediate
206: Note:
207: The type is determined by the data in the file, any type set into the `TSAdapt` before this call is ignored.
209: .seealso: [](ch_ts), `PetscViewerBinaryOpen()`, `TSAdaptView()`, `MatLoad()`, `VecLoad()`, `TSAdapt`
210: @*/
211: PetscErrorCode TSAdaptLoad(TSAdapt adapt, PetscViewer viewer)
212: {
213: PetscBool isbinary;
214: char type[256];
216: PetscFunctionBegin;
219: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
220: PetscCheck(isbinary, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Invalid viewer; open viewer with PetscViewerBinaryOpen()");
222: PetscCall(PetscViewerBinaryRead(viewer, type, 256, NULL, PETSC_CHAR));
223: PetscCall(TSAdaptSetType(adapt, type));
224: PetscTryTypeMethod(adapt, load, viewer);
225: PetscFunctionReturn(PETSC_SUCCESS);
226: }
228: /*@
229: TSAdaptView - Prints the `TSAdapt` data structure.
231: Collective
233: Input Parameters:
234: + adapt - the `TSAdapt` context obtained from `TSGetAdapt()`
235: - viewer - visualization context
237: Options Database Key:
238: . -ts_view - calls `TSView()` at end of `TSStep()`
240: Level: advanced
242: Notes:
243: This is called by `TSView()` so rarely called directly.
245: The available visualization contexts include
246: + `PETSC_VIEWER_STDOUT_SELF` - standard output (default)
247: - `PETSC_VIEWER_STDOUT_WORLD` - synchronized standard
248: output where only the first processor opens
249: the file. All other processes send their
250: data to the first process to print.
252: The user can open an alternative visualization context with
253: `PetscViewerASCIIOpen()` - output to a specified file.
255: In the debugger you can do call `TSAdaptView`(adapt,0) to display the `TSAdapt`. (The same holds for any PETSc object viewer).
257: .seealso: [](ch_ts), [](sec_ts_error_control), `TSAdapt`, `TSView()`, `PetscViewer`, `PetscViewerASCIIOpen()`
258: @*/
259: PetscErrorCode TSAdaptView(TSAdapt adapt, PetscViewer viewer)
260: {
261: PetscBool isascii, isbinary, isnone, isglee;
263: PetscFunctionBegin;
265: if (!viewer) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)adapt), &viewer));
267: PetscCheckSameComm(adapt, 1, viewer, 2);
268: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
269: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY, &isbinary));
270: if (isascii) {
271: PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject)adapt, viewer));
272: PetscCall(PetscObjectTypeCompare((PetscObject)adapt, TSADAPTNONE, &isnone));
273: PetscCall(PetscObjectTypeCompare((PetscObject)adapt, TSADAPTGLEE, &isglee));
274: if (!isnone) {
275: if (adapt->always_accept) PetscCall(PetscViewerASCIIPrintf(viewer, " always accepting steps\n"));
276: PetscCall(PetscViewerASCIIPrintf(viewer, " safety factor %g\n", (double)adapt->safety));
277: PetscCall(PetscViewerASCIIPrintf(viewer, " extra safety factor after step rejection %g\n", (double)adapt->reject_safety));
278: PetscCall(PetscViewerASCIIPrintf(viewer, " clip fastest increase %g\n", (double)adapt->clip[1]));
279: PetscCall(PetscViewerASCIIPrintf(viewer, " clip fastest decrease %g\n", (double)adapt->clip[0]));
280: PetscCall(PetscViewerASCIIPrintf(viewer, " maximum allowed timestep %g\n", (double)adapt->dt_max));
281: PetscCall(PetscViewerASCIIPrintf(viewer, " minimum allowed timestep %g\n", (double)adapt->dt_min));
282: PetscCall(PetscViewerASCIIPrintf(viewer, " maximum solution absolute value to be ignored %g\n", (double)adapt->ignore_max));
283: }
284: if (isglee) {
285: if (adapt->glee_use_local) {
286: PetscCall(PetscViewerASCIIPrintf(viewer, " GLEE uses local error control\n"));
287: } else {
288: PetscCall(PetscViewerASCIIPrintf(viewer, " GLEE uses global error control\n"));
289: }
290: }
291: PetscCall(PetscViewerASCIIPushTab(viewer));
292: PetscTryTypeMethod(adapt, view, viewer);
293: PetscCall(PetscViewerASCIIPopTab(viewer));
294: } else if (isbinary) {
295: char type[256];
297: /* need to save FILE_CLASS_ID for adapt class */
298: PetscCall(PetscStrncpy(type, ((PetscObject)adapt)->type_name, 256));
299: PetscCall(PetscViewerBinaryWrite(viewer, type, 256, PETSC_CHAR));
300: } else PetscTryTypeMethod(adapt, view, viewer);
301: PetscFunctionReturn(PETSC_SUCCESS);
302: }
304: /*@
305: TSAdaptReset - Resets a `TSAdapt` context to its defaults
307: Collective
309: Input Parameter:
310: . adapt - the `TSAdapt` context obtained from `TSGetAdapt()` or `TSAdaptCreate()`
312: Level: developer
314: .seealso: [](ch_ts), [](sec_ts_error_control), `TSGetAdapt()`, `TSAdapt`, `TSAdaptCreate()`, `TSAdaptDestroy()`
315: @*/
316: PetscErrorCode TSAdaptReset(TSAdapt adapt)
317: {
318: PetscFunctionBegin;
320: PetscTryTypeMethod(adapt, reset);
321: PetscFunctionReturn(PETSC_SUCCESS);
322: }
324: /*@
325: TSAdaptDestroy - Destroys a `TSAdapt` context
327: Collective
329: Input Parameter:
330: . adapt - the `TSAdapt` context obtained from `TSGetAdapt()` or `TSAdaptCreate()`
332: Level: intermediate
334: .seealso: [](ch_ts), [](sec_ts_error_control), `TSAdapt`, `TSAdaptCreate()`, `TSGetAdapt()`
335: @*/
336: PetscErrorCode TSAdaptDestroy(TSAdapt *adapt)
337: {
338: PetscFunctionBegin;
339: if (!*adapt) PetscFunctionReturn(PETSC_SUCCESS);
341: if (--((PetscObject)*adapt)->refct > 0) {
342: *adapt = NULL;
343: PetscFunctionReturn(PETSC_SUCCESS);
344: }
346: PetscCall(TSAdaptReset(*adapt));
348: PetscTryTypeMethod(*adapt, destroy);
349: PetscCall(PetscViewerDestroy(&(*adapt)->monitor));
350: PetscCall(PetscHeaderDestroy(adapt));
351: PetscFunctionReturn(PETSC_SUCCESS);
352: }
354: /*@
355: TSAdaptSetMonitor - Monitor the choices made by the adaptive controller
357: Collective
359: Input Parameters:
360: + adapt - adaptive controller context
361: - flg - `PETSC_TRUE` to active a monitor, `PETSC_FALSE` to disable
363: Options Database Key:
364: . -ts_adapt_monitor - to turn on monitoring
366: Level: intermediate
368: .seealso: [](ch_ts), [](sec_ts_error_control), `TSAdapt`, `TSGetAdapt()`, `TSAdaptChoose()`
369: @*/
370: PetscErrorCode TSAdaptSetMonitor(TSAdapt adapt, PetscBool flg)
371: {
372: PetscFunctionBegin;
375: if (flg) {
376: if (!adapt->monitor) PetscCall(PetscViewerASCIIOpen(PetscObjectComm((PetscObject)adapt), "stdout", &adapt->monitor));
377: } else {
378: PetscCall(PetscViewerDestroy(&adapt->monitor));
379: }
380: PetscFunctionReturn(PETSC_SUCCESS);
381: }
383: /*@C
384: TSAdaptSetCheckStage - Set a callback to check convergence for a stage
386: Logically Collective
388: Input Parameters:
389: + adapt - adaptive controller context
390: - func - stage check function
392: Calling sequence:
393: + adapt - adaptive controller context
394: . ts - time stepping context
395: . t - current time
396: . Y - current solution vector
397: - accept - pending choice of whether to accept, can be modified by this routine
399: Level: advanced
401: .seealso: [](ch_ts), [](sec_ts_error_control), `TSAdapt`, `TSGetAdapt()`, `TSAdaptChoose()`
402: @*/
403: PetscErrorCode TSAdaptSetCheckStage(TSAdapt adapt, PetscErrorCode (*func)(TSAdapt adapt, TS ts, PetscReal t, Vec Y, PetscBool *accept))
404: {
405: PetscFunctionBegin;
407: adapt->checkstage = func;
408: PetscFunctionReturn(PETSC_SUCCESS);
409: }
411: /*@
412: TSAdaptSetAlwaysAccept - Set whether to always accept steps regardless of
413: any error or stability condition not meeting the prescribed goal.
415: Logically Collective
417: Input Parameters:
418: + adapt - time step adaptivity context, usually gotten with `TSGetAdapt()`
419: - flag - whether to always accept steps
421: Options Database Key:
422: . -ts_adapt_always_accept - to always accept steps
424: Level: intermediate
426: .seealso: [](ch_ts), [](sec_ts_error_control), `TSAdapt`, `TSGetAdapt()`, `TSAdaptChoose()`
427: @*/
428: PetscErrorCode TSAdaptSetAlwaysAccept(TSAdapt adapt, PetscBool flag)
429: {
430: PetscFunctionBegin;
433: adapt->always_accept = flag;
434: PetscFunctionReturn(PETSC_SUCCESS);
435: }
437: /*@
438: TSAdaptSetSafety - Set safety factors for time step adaptor
440: Logically Collective
442: Input Parameters:
443: + adapt - adaptive controller context
444: . safety - safety factor relative to target error/stability goal
445: - reject_safety - extra safety factor to apply if the last step was rejected
447: Options Database Keys:
448: + -ts_adapt_safety safety - to set safety factor
449: - -ts_adapt_reject_safety reject_safety - to set reject safety factor
451: Level: intermediate
453: Note:
454: Use `PETSC_CURRENT` to keep the current value for either parameter
456: Fortran Note:
457: Use `PETSC_CURRENT_REAL`
459: .seealso: [](ch_ts), [](sec_ts_error_control), `TSAdapt`, `TSAdaptGetSafety()`, `TSAdaptChoose()`
460: @*/
461: PetscErrorCode TSAdaptSetSafety(TSAdapt adapt, PetscReal safety, PetscReal reject_safety)
462: {
463: PetscFunctionBegin;
467: PetscCheck(safety == (PetscReal)PETSC_CURRENT || safety >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Safety factor %g must be non negative", (double)safety);
468: PetscCheck(safety == (PetscReal)PETSC_CURRENT || safety <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Safety factor %g must be less than one", (double)safety);
469: PetscCheck(reject_safety == (PetscReal)PETSC_CURRENT || reject_safety >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Reject safety factor %g must be non negative", (double)reject_safety);
470: PetscCheck(reject_safety == (PetscReal)PETSC_CURRENT || reject_safety <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Reject safety factor %g must be less than one", (double)reject_safety);
471: if (safety != (PetscReal)PETSC_CURRENT) adapt->safety = safety;
472: if (reject_safety != (PetscReal)PETSC_CURRENT) adapt->reject_safety = reject_safety;
473: PetscFunctionReturn(PETSC_SUCCESS);
474: }
476: /*@
477: TSAdaptGetSafety - Get safety factors for time step adapter
479: Not Collective
481: Input Parameter:
482: . adapt - adaptive controller context
484: Output Parameters:
485: + safety - safety factor relative to target error/stability goal
486: - reject_safety - extra safety factor to apply if the last step was rejected
488: Level: intermediate
490: .seealso: [](ch_ts), [](sec_ts_error_control), `TSAdapt`, `TSAdaptSetSafety()`, `TSAdaptChoose()`
491: @*/
492: PetscErrorCode TSAdaptGetSafety(TSAdapt adapt, PetscReal *safety, PetscReal *reject_safety)
493: {
494: PetscFunctionBegin;
496: if (safety) PetscAssertPointer(safety, 2);
497: if (reject_safety) PetscAssertPointer(reject_safety, 3);
498: if (safety) *safety = adapt->safety;
499: if (reject_safety) *reject_safety = adapt->reject_safety;
500: PetscFunctionReturn(PETSC_SUCCESS);
501: }
503: /*@
504: TSAdaptSetMaxIgnore - Set error estimation threshold. Solution components below this threshold value will not be considered when computing error norms
505: for time step adaptivity (in absolute value). A negative value (default) of the threshold leads to considering all solution components.
507: Logically Collective
509: Input Parameters:
510: + adapt - adaptive controller context
511: - max_ignore - threshold for solution components that are ignored during error estimation
513: Options Database Key:
514: . -ts_adapt_max_ignore max_ignore - to set the threshold
516: Level: intermediate
518: .seealso: [](ch_ts), [](sec_ts_error_control), `TSAdapt`, `TSAdaptGetMaxIgnore()`, `TSAdaptChoose()`
519: @*/
520: PetscErrorCode TSAdaptSetMaxIgnore(TSAdapt adapt, PetscReal max_ignore)
521: {
522: PetscFunctionBegin;
525: adapt->ignore_max = max_ignore;
526: PetscFunctionReturn(PETSC_SUCCESS);
527: }
529: /*@
530: TSAdaptGetMaxIgnore - Get error estimation threshold. Solution components below this threshold value will not be considered when computing error norms
531: for time step adaptivity (in absolute value).
533: Not Collective
535: Input Parameter:
536: . adapt - adaptive controller context
538: Output Parameter:
539: . max_ignore - threshold for solution components that are ignored during error estimation
541: Level: intermediate
543: .seealso: [](ch_ts), [](sec_ts_error_control), `TSAdapt`, `TSAdaptSetMaxIgnore()`, `TSAdaptChoose()`
544: @*/
545: PetscErrorCode TSAdaptGetMaxIgnore(TSAdapt adapt, PetscReal *max_ignore)
546: {
547: PetscFunctionBegin;
549: PetscAssertPointer(max_ignore, 2);
550: *max_ignore = adapt->ignore_max;
551: PetscFunctionReturn(PETSC_SUCCESS);
552: }
554: /*@
555: TSAdaptSetClip - Sets the admissible decrease/increase factor in step size in the time step adapter
557: Logically collective
559: Input Parameters:
560: + adapt - adaptive controller context
561: . low - admissible decrease factor
562: - high - admissible increase factor
564: Options Database Key:
565: . -ts_adapt_clip low,high - to set admissible time step decrease and increase factors
567: Level: intermediate
569: Note:
570: Use `PETSC_CURRENT` to keep the current value for either parameter
572: Fortran Note:
573: Use `PETSC_CURRENT_REAL`
575: .seealso: [](ch_ts), [](sec_ts_error_control), `TSAdapt`, `TSAdaptChoose()`, `TSAdaptGetClip()`, `TSAdaptSetScaleSolveFailed()`
576: @*/
577: PetscErrorCode TSAdaptSetClip(TSAdapt adapt, PetscReal low, PetscReal high)
578: {
579: PetscFunctionBegin;
583: PetscCheck(low == (PetscReal)PETSC_CURRENT || low >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Decrease factor %g must be non negative", (double)low);
584: PetscCheck(low == (PetscReal)PETSC_CURRENT || low <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Decrease factor %g must be less than one", (double)low);
585: PetscCheck(high == (PetscReal)PETSC_CURRENT || high >= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Increase factor %g must be greater than one", (double)high);
586: if (low != (PetscReal)PETSC_CURRENT) adapt->clip[0] = low;
587: if (high != (PetscReal)PETSC_CURRENT) adapt->clip[1] = high;
588: PetscFunctionReturn(PETSC_SUCCESS);
589: }
591: /*@
592: TSAdaptGetClip - Gets the admissible decrease/increase factor in step size in the time step adapter
594: Not Collective
596: Input Parameter:
597: . adapt - adaptive controller context
599: Output Parameters:
600: + low - optional, admissible decrease factor
601: - high - optional, admissible increase factor
603: Level: intermediate
605: .seealso: [](ch_ts), [](sec_ts_error_control), `TSAdapt`, `TSAdaptChoose()`, `TSAdaptSetClip()`, `TSAdaptSetScaleSolveFailed()`
606: @*/
607: PetscErrorCode TSAdaptGetClip(TSAdapt adapt, PetscReal *low, PetscReal *high)
608: {
609: PetscFunctionBegin;
611: if (low) PetscAssertPointer(low, 2);
612: if (high) PetscAssertPointer(high, 3);
613: if (low) *low = adapt->clip[0];
614: if (high) *high = adapt->clip[1];
615: PetscFunctionReturn(PETSC_SUCCESS);
616: }
618: /*@
619: TSAdaptSetScaleSolveFailed - Scale step size by this factor if solve fails
621: Logically Collective
623: Input Parameters:
624: + adapt - adaptive controller context
625: - scale - scale
627: Options Database Key:
628: . -ts_adapt_scale_solve_failed scale - to set scale step by this factor if solve fails
630: Level: intermediate
632: .seealso: [](ch_ts), [](sec_ts_error_control), `TSAdapt`, `TSAdaptChoose()`, `TSAdaptGetScaleSolveFailed()`, `TSAdaptGetClip()`
633: @*/
634: PetscErrorCode TSAdaptSetScaleSolveFailed(TSAdapt adapt, PetscReal scale)
635: {
636: PetscFunctionBegin;
639: PetscCheck(scale > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Scale factor %g must be positive", (double)scale);
640: PetscCheck(scale <= 1, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Scale factor %g must be less than one", (double)scale);
641: adapt->scale_solve_failed = scale;
642: PetscFunctionReturn(PETSC_SUCCESS);
643: }
645: /*@
646: TSAdaptGetScaleSolveFailed - Gets the admissible decrease/increase factor in step size
648: Not Collective
650: Input Parameter:
651: . adapt - adaptive controller context
653: Output Parameter:
654: . scale - scale factor
656: Level: intermediate
658: .seealso: [](ch_ts), [](sec_ts_error_control), `TSAdapt`, `TSAdaptChoose()`, `TSAdaptSetScaleSolveFailed()`, `TSAdaptSetClip()`
659: @*/
660: PetscErrorCode TSAdaptGetScaleSolveFailed(TSAdapt adapt, PetscReal *scale)
661: {
662: PetscFunctionBegin;
664: if (scale) PetscAssertPointer(scale, 2);
665: if (scale) *scale = adapt->scale_solve_failed;
666: PetscFunctionReturn(PETSC_SUCCESS);
667: }
669: /*@
670: TSAdaptSetStepLimits - Set the minimum and maximum step sizes to be considered by the time step controller
672: Logically Collective
674: Input Parameters:
675: + adapt - time step adaptivity context, usually gotten with `TSGetAdapt()`
676: . hmin - minimum time step
677: - hmax - maximum time step
679: Options Database Keys:
680: + -ts_adapt_dt_min min - to set minimum time step
681: - -ts_adapt_dt_max max - to set maximum time step
683: Level: intermediate
685: Note:
686: Use `PETSC_CURRENT` to keep the current value for either parameter
688: Fortran Note:
689: Use `PETSC_CURRENT_REAL`
691: .seealso: [](ch_ts), [](sec_ts_error_control), `TSAdapt`, `TSAdaptGetStepLimits()`, `TSAdaptChoose()`
692: @*/
693: PetscErrorCode TSAdaptSetStepLimits(TSAdapt adapt, PetscReal hmin, PetscReal hmax)
694: {
695: PetscFunctionBegin;
699: PetscCheck(hmin == (PetscReal)PETSC_CURRENT || hmin >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Minimum time step %g must be non negative", (double)hmin);
700: PetscCheck(hmax == (PetscReal)PETSC_CURRENT || hmax >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Minimum time step %g must be non negative", (double)hmax);
701: if (hmin != (PetscReal)PETSC_CURRENT) adapt->dt_min = hmin;
702: if (hmax != (PetscReal)PETSC_CURRENT) adapt->dt_max = hmax;
703: hmin = adapt->dt_min;
704: hmax = adapt->dt_max;
705: 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);
706: PetscFunctionReturn(PETSC_SUCCESS);
707: }
709: /*@
710: TSAdaptGetStepLimits - Get the minimum and maximum step sizes to be considered by the time step controller
712: Not Collective
714: Input Parameter:
715: . adapt - time step adaptivity context, usually gotten with `TSGetAdapt()`
717: Output Parameters:
718: + hmin - minimum time step
719: - hmax - maximum time step
721: Level: intermediate
723: .seealso: [](ch_ts), [](sec_ts_error_control), `TSAdapt`, `TSAdaptSetStepLimits()`, `TSAdaptChoose()`
724: @*/
725: PetscErrorCode TSAdaptGetStepLimits(TSAdapt adapt, PetscReal *hmin, PetscReal *hmax)
726: {
727: PetscFunctionBegin;
729: if (hmin) PetscAssertPointer(hmin, 2);
730: if (hmax) PetscAssertPointer(hmax, 3);
731: if (hmin) *hmin = adapt->dt_min;
732: if (hmax) *hmax = adapt->dt_max;
733: PetscFunctionReturn(PETSC_SUCCESS);
734: }
736: /*@C
737: TSAdaptSetFromOptions - Sets various `TSAdapt` parameters from user options.
739: Collective
741: Input Parameters:
742: + adapt - the `TSAdapt` context
743: - PetscOptionsObject - object created by `PetscOptionsBegin()`
745: Options Database Keys:
746: + -ts_adapt_type (basic|dsp|none|cfl|glee|history) - algorithm to use for adaptivity
747: . -ts_adapt_always_accept (true|false) - always accept steps regardless of error/stability goals
748: . -ts_adapt_safety safety - safety factor relative to target error/stability goal
749: . -ts_adapt_reject_safety safety - extra safety factor to apply if the last step was rejected
750: . -ts_adapt_clip low,high - admissible time step decrease and increase factors
751: . -ts_adapt_dt_min min - minimum timestep to use
752: . -ts_adapt_dt_max max - maximum timestep to use
753: . -ts_adapt_scale_solve_failed scale - scale timestep by this factor if a solve fails
754: . -ts_adapt_wnormtype (2|infinity) - type of norm for computing error estimates
755: - -ts_adapt_time_step_increase_delay steps - number of timesteps to delay increasing the time step after it has been decreased due to failed solver
757: Level: advanced
759: Note:
760: This function is automatically called by `TSSetFromOptions()`
762: .seealso: [](ch_ts), [](sec_ts_error_control), `TSAdapt`, `TSGetAdapt()`, `TSAdaptSetType()`, `TSAdaptSetAlwaysAccept()`, `TSAdaptSetSafety()`,
763: `TSAdaptSetClip()`, `TSAdaptSetScaleSolveFailed()`, `TSAdaptSetStepLimits()`, `TSAdaptSetMonitor()`
764: @*/
765: PetscErrorCode TSAdaptSetFromOptions(TSAdapt adapt, PetscOptionItems PetscOptionsObject)
766: {
767: char type[256] = TSADAPTBASIC;
768: PetscReal safety, reject_safety, clip[2], scale, hmin, hmax;
769: PetscBool set, flg;
770: PetscInt two;
772: PetscFunctionBegin;
774: /* This should use PetscOptionsBegin() if/when this becomes an object used outside of TS, but currently this
775: * function can only be called from inside TSSetFromOptions() */
776: PetscOptionsHeadBegin(PetscOptionsObject, "TS Adaptivity options");
777: 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));
778: if (flg || !((PetscObject)adapt)->type_name) PetscCall(TSAdaptSetType(adapt, type));
780: PetscCall(PetscOptionsBool("-ts_adapt_always_accept", "Always accept the step", "TSAdaptSetAlwaysAccept", adapt->always_accept, &flg, &set));
781: if (set) PetscCall(TSAdaptSetAlwaysAccept(adapt, flg));
783: safety = adapt->safety;
784: reject_safety = adapt->reject_safety;
785: PetscCall(PetscOptionsReal("-ts_adapt_safety", "Safety factor relative to target error/stability goal", "TSAdaptSetSafety", safety, &safety, &set));
786: PetscCall(PetscOptionsReal("-ts_adapt_reject_safety", "Extra safety factor to apply if the last step was rejected", "TSAdaptSetSafety", reject_safety, &reject_safety, &flg));
787: if (set || flg) PetscCall(TSAdaptSetSafety(adapt, safety, reject_safety));
789: two = 2;
790: clip[0] = adapt->clip[0];
791: clip[1] = adapt->clip[1];
792: PetscCall(PetscOptionsRealArray("-ts_adapt_clip", "Admissible decrease/increase factor in step size", "TSAdaptSetClip", clip, &two, &set));
793: PetscCheck(!set || (two == 2), PetscObjectComm((PetscObject)adapt), PETSC_ERR_ARG_OUTOFRANGE, "Must give exactly two values to -ts_adapt_clip");
794: if (set) PetscCall(TSAdaptSetClip(adapt, clip[0], clip[1]));
796: hmin = adapt->dt_min;
797: hmax = adapt->dt_max;
798: PetscCall(PetscOptionsReal("-ts_adapt_dt_min", "Minimum time step considered", "TSAdaptSetStepLimits", hmin, &hmin, &set));
799: PetscCall(PetscOptionsReal("-ts_adapt_dt_max", "Maximum time step considered", "TSAdaptSetStepLimits", hmax, &hmax, &flg));
800: if (set || flg) PetscCall(TSAdaptSetStepLimits(adapt, hmin, hmax));
802: PetscCall(PetscOptionsReal("-ts_adapt_max_ignore", "Adaptor ignores (absolute) solution values smaller than this value", "", adapt->ignore_max, &adapt->ignore_max, &set));
803: 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));
805: PetscCall(PetscOptionsReal("-ts_adapt_scale_solve_failed", "Scale step by this factor if solve fails", "TSAdaptSetScaleSolveFailed", adapt->scale_solve_failed, &scale, &set));
806: if (set) PetscCall(TSAdaptSetScaleSolveFailed(adapt, scale));
808: PetscCall(PetscOptionsEnum("-ts_adapt_wnormtype", "Type of norm computed for error estimation", "", NormTypes, (PetscEnum)adapt->wnormtype, (PetscEnum *)&adapt->wnormtype, NULL));
809: PetscCheck(adapt->wnormtype == NORM_2 || adapt->wnormtype == NORM_INFINITY, PetscObjectComm((PetscObject)adapt), PETSC_ERR_SUP, "Only 2-norm and infinite norm supported");
811: 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));
813: PetscCall(PetscOptionsBool("-ts_adapt_monitor", "Print choices made by adaptive controller", "TSAdaptSetMonitor", adapt->monitor ? PETSC_TRUE : PETSC_FALSE, &flg, &set));
814: if (set) PetscCall(TSAdaptSetMonitor(adapt, flg));
816: PetscTryTypeMethod(adapt, setfromoptions, PetscOptionsObject);
817: PetscOptionsHeadEnd();
818: PetscFunctionReturn(PETSC_SUCCESS);
819: }
821: /*@
822: TSAdaptCandidatesClear - clear any previously set candidate schemes
824: Logically Collective
826: Input Parameter:
827: . adapt - adaptive controller
829: Level: developer
831: .seealso: [](ch_ts), [](sec_ts_error_control), `TSAdapt`, `TSAdaptCreate()`, `TSAdaptCandidateAdd()`, `TSAdaptChoose()`
832: @*/
833: PetscErrorCode TSAdaptCandidatesClear(TSAdapt adapt)
834: {
835: PetscFunctionBegin;
837: PetscCall(PetscMemzero(&adapt->candidates, sizeof(adapt->candidates)));
838: PetscFunctionReturn(PETSC_SUCCESS);
839: }
841: /*@C
842: TSAdaptCandidateAdd - add a candidate scheme for the adaptive controller to select from
844: Logically Collective; No Fortran Support
846: Input Parameters:
847: + adapt - time step adaptivity context, obtained with `TSGetAdapt()` or `TSAdaptCreate()`
848: . name - name of the candidate scheme to add
849: . order - order of the candidate scheme
850: . stageorder - stage order of the candidate scheme
851: . ccfl - stability coefficient relative to explicit Euler, used for CFL constraints
852: . cost - relative measure of the amount of work required for the candidate scheme
853: - inuse - indicates that this scheme is the one currently in use, this flag can only be set for one scheme
855: Level: developer
857: .seealso: [](ch_ts), [](sec_ts_error_control), `TSAdapt`, `TSAdaptCandidatesClear()`, `TSAdaptChoose()`
858: @*/
859: PetscErrorCode TSAdaptCandidateAdd(TSAdapt adapt, const char name[], PetscInt order, PetscInt stageorder, PetscReal ccfl, PetscReal cost, PetscBool inuse)
860: {
861: PetscInt c;
863: PetscFunctionBegin;
865: PetscCheck(order >= 1, PetscObjectComm((PetscObject)adapt), PETSC_ERR_ARG_OUTOFRANGE, "Classical order %" PetscInt_FMT " must be a positive integer", order);
866: if (inuse) {
867: PetscCheck(!adapt->candidates.inuse_set, PetscObjectComm((PetscObject)adapt), PETSC_ERR_ARG_WRONGSTATE, "Cannot set the inuse method twice, maybe forgot to call TSAdaptCandidatesClear()");
868: adapt->candidates.inuse_set = PETSC_TRUE;
869: }
870: /* first slot if this is the current scheme, otherwise the next available slot */
871: c = inuse ? 0 : !adapt->candidates.inuse_set + adapt->candidates.n;
873: adapt->candidates.name[c] = name;
874: adapt->candidates.order[c] = order;
875: adapt->candidates.stageorder[c] = stageorder;
876: adapt->candidates.ccfl[c] = ccfl;
877: adapt->candidates.cost[c] = cost;
878: adapt->candidates.n++;
879: PetscFunctionReturn(PETSC_SUCCESS);
880: }
882: /*@C
883: TSAdaptCandidatesGet - Get the list of candidate orders of accuracy and cost
885: Not Collective
887: Input Parameter:
888: . adapt - time step adaptivity context
890: Output Parameters:
891: + n - number of candidate schemes, always at least 1
892: . order - the order of each candidate scheme
893: . stageorder - the stage order of each candidate scheme
894: . ccfl - the CFL coefficient of each scheme
895: - cost - the relative cost of each scheme
897: Level: developer
899: Note:
900: The current scheme is always returned in the first slot
902: .seealso: [](ch_ts), [](sec_ts_error_control), `TSAdapt`, `TSAdaptCandidatesClear()`, `TSAdaptCandidateAdd()`, `TSAdaptChoose()`
903: @*/
904: PetscErrorCode TSAdaptCandidatesGet(TSAdapt adapt, PetscInt *n, const PetscInt **order, const PetscInt **stageorder, const PetscReal **ccfl, const PetscReal **cost)
905: {
906: PetscFunctionBegin;
908: if (n) *n = adapt->candidates.n;
909: if (order) *order = adapt->candidates.order;
910: if (stageorder) *stageorder = adapt->candidates.stageorder;
911: if (ccfl) *ccfl = adapt->candidates.ccfl;
912: if (cost) *cost = adapt->candidates.cost;
913: PetscFunctionReturn(PETSC_SUCCESS);
914: }
916: /*@C
917: TSAdaptChoose - choose which method and step size to use for the next step
919: Collective
921: Input Parameters:
922: + adapt - adaptive controller
923: . ts - time stepper
924: - h - current step size
926: Output Parameters:
927: + next_sc - optional, scheme to use for the next step
928: . next_h - step size to use for the next step
929: - accept - `PETSC_TRUE` to accept the current step, `PETSC_FALSE` to repeat the current step with the new step size
931: Level: developer
933: Note:
934: The input value of parameter accept is retained from the last time step, so it will be `PETSC_FALSE` if the step is
935: being retried after an initial rejection.
937: .seealso: [](ch_ts), [](sec_ts_error_control), `TSAdapt`, `TSAdaptCandidatesClear()`, `TSAdaptCandidateAdd()`
938: @*/
939: PetscErrorCode TSAdaptChoose(TSAdapt adapt, TS ts, PetscReal h, PetscInt *next_sc, PetscReal *next_h, PetscBool *accept)
940: {
941: PetscInt ncandidates = adapt->candidates.n;
942: PetscInt scheme = 0;
943: PetscReal wlte = -1.0;
944: PetscReal wltea = -1.0;
945: PetscReal wlter = -1.0;
947: PetscFunctionBegin;
950: if (next_sc) PetscAssertPointer(next_sc, 4);
951: PetscAssertPointer(next_h, 5);
952: PetscAssertPointer(accept, 6);
953: if (next_sc) *next_sc = 0;
955: /* Do not mess with adaptivity while handling events */
956: if (ts->event && ts->event->processing) {
957: *next_h = h;
958: *accept = PETSC_TRUE;
959: if (adapt->monitor) {
960: PetscCall(PetscViewerASCIIAddTab(adapt->monitor, ((PetscObject)adapt)->tablevel));
962: if (ts->event->iterctr == 0) {
963: /*
964: An event has been found, now finalising the event processing: performing the 1st and 2nd post-event steps.
965: Entering this if-branch means both these steps (set to either PETSC_DECIDE or numerical value) are managed
966: by the event handler. In this case the 1st post-event step is always accepted, without interference of TSAdapt.
967: Note: if the 2nd post-event step is not managed by the event handler (e.g. given 1st = numerical, 2nd = PETSC_DECIDE),
968: this if-branch is not entered, and TSAdapt may reject/adjust the proposed 1st post-event step.
969: */
970: PetscCall(PetscViewerASCIIPrintf(adapt->monitor, "TSAdapt does not interfere, step %3" PetscInt_FMT " accepted. Processing post-event steps: 1-st accepted just now, 2-nd yet to come\n", ts->steps));
971: } else PetscCall(PetscViewerASCIIPrintf(adapt->monitor, "TSAdapt does not interfere, step %3" PetscInt_FMT " accepted. Event handling in progress\n", ts->steps));
973: PetscCall(PetscViewerASCIISubtractTab(adapt->monitor, ((PetscObject)adapt)->tablevel));
974: }
975: PetscFunctionReturn(PETSC_SUCCESS);
976: }
978: PetscUseTypeMethod(adapt, choose, ts, h, &scheme, next_h, accept, &wlte, &wltea, &wlter);
979: 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);
980: PetscCheck(*next_h >= 0, PetscObjectComm((PetscObject)adapt), PETSC_ERR_ARG_OUTOFRANGE, "Computed step size %g must be positive", (double)*next_h);
981: if (next_sc) *next_sc = scheme;
983: if (*accept && ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP) {
984: /* Increase/reduce step size if end time of next step is close to or overshoots max time */
985: PetscReal t = ts->ptime + ts->time_step, tend, tmax, h1, hmax;
986: PetscReal a = (PetscReal)(1.0 + adapt->matchstepfac[0]);
987: PetscReal b = adapt->matchstepfac[1];
989: /*
990: Logic in using 'dt_span_cached':
991: 1. It always overrides *next_h, except (any of):
992: a) the current step was rejected,
993: b) the adaptor proposed to decrease the next step,
994: c) the adaptor proposed *next_h > dt_span_cached.
995: 2. If *next_h was adjusted by eval_times points (or the final point):
996: -- when dt_span_cached is filled (>0), it keeps its value,
997: -- when dt_span_cached is clear (==0), it gets the unadjusted version of *next_h.
998: 3. If *next_h was not adjusted as in (2), dt_span_cached is cleared.
999: Note, if a combination (1.b || 1.c) && (3) takes place, this means that
1000: dt_span_cached remains unused at the moment of clearing.
1001: If (1.a) takes place, dt_span_cached keeps its value.
1002: Also, dt_span_cached can be updated by the event handler, see tsevent.c.
1003: */
1004: if (h <= *next_h && *next_h <= adapt->dt_eval_times_cached) *next_h = adapt->dt_eval_times_cached; /* try employing the cache */
1005: h1 = *next_h;
1006: tend = t + h1;
1008: if (ts->eval_times && ts->eval_times->time_point_idx < ts->eval_times->num_time_points) {
1009: PetscCheck(ts->eval_times->worktol == 0, PetscObjectComm((PetscObject)adapt), PETSC_ERR_PLIB, "Unexpected state (tspan->worktol != 0) in TSAdaptChoose()");
1010: ts->eval_times->worktol = ts->eval_times->reltol * h1 + ts->eval_times->abstol;
1011: if (PetscIsCloseAtTol(t, ts->eval_times->time_points[ts->eval_times->time_point_idx], ts->eval_times->worktol, 0)) /* hit a span time point */
1012: if (ts->eval_times->time_point_idx + 1 < ts->eval_times->num_time_points) tmax = ts->eval_times->time_points[ts->eval_times->time_point_idx + 1];
1013: else tmax = ts->max_time; /* hit the last span time point */
1014: else tmax = ts->eval_times->time_points[ts->eval_times->time_point_idx];
1015: } else tmax = ts->max_time;
1016: tmax = PetscMin(tmax, ts->max_time);
1017: hmax = tmax - t;
1019: if (t < tmax && tend > tmax) *next_h = hmax;
1020: if (t < tmax && tend < tmax && h1 * b > hmax) *next_h = hmax / 2;
1021: if (t < tmax && tend < tmax && h1 * a > hmax) *next_h = hmax;
1022: if (ts->eval_times && h1 != *next_h && !adapt->dt_eval_times_cached) adapt->dt_eval_times_cached = h1; /* cache the step size if it is to be changed */
1023: if (ts->eval_times && h1 == *next_h && adapt->dt_eval_times_cached) adapt->dt_eval_times_cached = 0; /* clear the cache if the step size is unchanged */
1024: }
1025: if (adapt->monitor) {
1026: const char *sc_name = (scheme < ncandidates) ? adapt->candidates.name[scheme] : "";
1027: PetscCall(PetscViewerASCIIAddTab(adapt->monitor, ((PetscObject)adapt)->tablevel));
1028: if (wlte < 0) {
1029: 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",
1030: (double)ts->ptime, (double)h, (double)*next_h));
1031: } else {
1032: 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",
1033: (double)ts->ptime, (double)h, (double)*next_h, (double)wlte, (double)wltea, (double)wlter));
1034: }
1035: PetscCall(PetscViewerASCIISubtractTab(adapt->monitor, ((PetscObject)adapt)->tablevel));
1036: }
1037: PetscFunctionReturn(PETSC_SUCCESS);
1038: }
1040: /*@
1041: TSAdaptSetTimeStepIncreaseDelay - The number of timesteps to wait after a decrease in the timestep due to failed solver
1042: before increasing the time step.
1044: Logicially Collective
1046: Input Parameters:
1047: + adapt - adaptive controller context
1048: - cnt - the number of timesteps
1050: Options Database Key:
1051: . -ts_adapt_time_step_increase_delay cnt - number of steps to delay the increase
1053: Level: advanced
1055: Notes:
1056: This is to prevent an adaptor from bouncing back and forth between two nearby timesteps. The default is 0.
1058: The successful use of this option is problem dependent
1060: Developer Notes:
1061: There is no theory to support this option
1063: .seealso: [](ch_ts), [](sec_ts_error_control), `TSAdapt`
1064: @*/
1065: PetscErrorCode TSAdaptSetTimeStepIncreaseDelay(TSAdapt adapt, PetscInt cnt)
1066: {
1067: PetscFunctionBegin;
1068: adapt->timestepjustdecreased_delay = cnt;
1069: PetscFunctionReturn(PETSC_SUCCESS);
1070: }
1072: /*@
1073: TSAdaptCheckStage - checks whether to accept a stage, (e.g. reject and change time step size if nonlinear solve fails or solution vector is infeasible)
1075: Collective
1077: Input Parameters:
1078: + adapt - adaptive controller context
1079: . ts - time stepper
1080: . t - Current simulation time
1081: - Y - Current solution vector
1083: Output Parameter:
1084: . accept - `PETSC_TRUE` to accept the stage, `PETSC_FALSE` to reject
1086: Level: developer
1088: .seealso: [](ch_ts), [](sec_ts_error_control), `TSAdapt`
1089: @*/
1090: PetscErrorCode TSAdaptCheckStage(TSAdapt adapt, TS ts, PetscReal t, Vec Y, PetscBool *accept)
1091: {
1092: SNESConvergedReason snesreason = SNES_CONVERGED_ITERATING;
1093: PetscBool func_accept;
1094: char reject_stage_message[128];
1096: PetscFunctionBegin;
1099: PetscAssertPointer(accept, 5);
1100: *accept = PETSC_TRUE;
1102: if (adapt->checkstage) {
1103: PetscCallBack("TSAdapt callback check stage", (*adapt->checkstage)(adapt, ts, t, Y, accept));
1104: if (!*accept) {
1105: PetscCall(PetscStrncpy(reject_stage_message, "rejected by TSAdaptSetCheckStage", sizeof reject_stage_message));
1106: goto reject_stage;
1107: }
1108: }
1110: PetscCall(TSFunctionDomainError(ts, t, Y, &func_accept));
1111: if (!func_accept) {
1112: PetscCall(PetscStrncpy(reject_stage_message, "rejected by TSSetFunctionDomainError()", sizeof reject_stage_message));
1113: goto reject_stage;
1114: }
1116: if (ts->snes) PetscCall(SNESGetConvergedReason(ts->snes, &snesreason));
1117: if (snesreason < 0) {
1118: // SNES_DIVERGED_FUNCTION_DOMAIN should not count against ts->max_snes_failures, see !6581 and commit 6c6709e3a
1119: if (snesreason != SNES_DIVERGED_FUNCTION_DOMAIN && ++ts->num_snes_failures >= ts->max_snes_failures && ts->max_snes_failures != PETSC_UNLIMITED) {
1120: ts->reason = TS_DIVERGED_NONLINEAR_SOLVE;
1121: PetscCall(PetscSNPrintf(reject_stage_message, sizeof reject_stage_message, "nonlinear solve failures %" PetscInt_FMT " greater than current TS allowed, stopping solve", ts->num_snes_failures));
1122: } else PetscCall(PetscSNPrintf(reject_stage_message, sizeof reject_stage_message, "SNES solve failure %s", SNESConvergedReasons[snesreason]));
1123: goto reject_stage;
1124: }
1125: PetscFunctionReturn(PETSC_SUCCESS);
1127: reject_stage:
1128: *accept = PETSC_FALSE;
1129: PetscCall(PetscInfo(ts, "Step=%" PetscInt_FMT ", %s\n", ts->steps, reject_stage_message));
1130: if (adapt->monitor) {
1131: PetscCall(PetscViewerASCIIAddTab(adapt->monitor, ((PetscObject)adapt)->tablevel));
1132: PetscCall(PetscViewerASCIIPrintf(adapt->monitor, "TSAdapt %s step %3" PetscInt_FMT " stage rejected t=%-11g+%10.3e, %s", ((PetscObject)adapt)->type_name, ts->steps, (double)ts->ptime, (double)ts->time_step, reject_stage_message));
1133: PetscCall(PetscViewerASCIISubtractTab(adapt->monitor, ((PetscObject)adapt)->tablevel));
1134: }
1135: if (!ts->reason) {
1136: PetscReal dt, new_dt;
1137: PetscCall(TSGetTimeStep(ts, &dt));
1138: new_dt = dt * adapt->scale_solve_failed;
1139: PetscCall(TSSetTimeStep(ts, new_dt));
1140: adapt->timestepjustdecreased += adapt->timestepjustdecreased_delay;
1141: if (adapt->monitor) PetscCall(PetscViewerASCIIPrintf(adapt->monitor, ", retrying with dt=%-10.3e\n", (double)new_dt));
1142: } else if (adapt->monitor) {
1143: PetscCall(PetscViewerASCIIPrintf(adapt->monitor, "\n"));
1144: }
1145: PetscFunctionReturn(PETSC_SUCCESS);
1146: }
1148: /*@
1149: TSAdaptCreate - create an adaptive controller context for time stepping
1151: Collective
1153: Input Parameter:
1154: . comm - The communicator
1156: Output Parameter:
1157: . inadapt - new `TSAdapt` object
1159: Level: developer
1161: Note:
1162: `TSAdapt` creation is handled by `TS`, so users should not need to call this function.
1164: .seealso: [](ch_ts), [](sec_ts_error_control), `TSAdapt`, `TSGetAdapt()`, `TSAdaptSetType()`, `TSAdaptDestroy()`
1165: @*/
1166: PetscErrorCode TSAdaptCreate(MPI_Comm comm, TSAdapt *inadapt)
1167: {
1168: TSAdapt adapt;
1170: PetscFunctionBegin;
1171: PetscAssertPointer(inadapt, 2);
1172: PetscCall(TSAdaptInitializePackage());
1174: PetscCall(PetscHeaderCreate(adapt, TSADAPT_CLASSID, "TSAdapt", "Time stepping adaptivity", "TS", comm, TSAdaptDestroy, TSAdaptView));
1175: adapt->always_accept = PETSC_FALSE;
1176: adapt->safety = 0.9;
1177: adapt->reject_safety = 0.5;
1178: adapt->clip[0] = 0.1;
1179: adapt->clip[1] = 10.;
1180: adapt->dt_min = 1e-20;
1181: adapt->dt_max = 1e+20;
1182: adapt->ignore_max = -1.0;
1183: adapt->glee_use_local = PETSC_TRUE;
1184: adapt->scale_solve_failed = 0.25;
1185: /* these two safety factors are not public, and they are used only in the TS_EXACTFINALTIME_MATCHSTEP case
1186: to prevent from situations were unreasonably small time steps are taken in order to match the final time */
1187: adapt->matchstepfac[0] = 0.01; /* allow 1% step size increase in the last step */
1188: adapt->matchstepfac[1] = 2.0; /* halve last step if it is greater than what remains divided this factor */
1189: adapt->wnormtype = NORM_2;
1190: adapt->timestepjustdecreased_delay = 0;
1191: *inadapt = adapt;
1192: PetscFunctionReturn(PETSC_SUCCESS);
1193: }