1 2 #include <petsc/private/tsimpl.h> /*I "petscts.h" I*/ 3 4 PetscClassId TSADAPT_CLASSID; 5 6 static PetscFunctionList TSAdaptList; 7 static PetscBool TSAdaptPackageInitialized; 8 static PetscBool TSAdaptRegisterAllCalled; 9 10 PETSC_EXTERN PetscErrorCode TSAdaptCreate_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); 16 17 /*@C 18 TSAdaptRegister - adds a TSAdapt implementation 19 20 Not Collective 21 22 Input Parameters: 23 + name_scheme - name of user-defined adaptivity scheme 24 - routine_create - routine to create method context 25 26 Notes: 27 TSAdaptRegister() may be called multiple times to add several user-defined families. 28 29 Sample usage: 30 .vb 31 TSAdaptRegister("my_scheme",MySchemeCreate); 32 .ve 33 34 Then, your scheme can be chosen with the procedural interface via 35 $ TSAdaptSetType(ts,"my_scheme") 36 or at runtime via the option 37 $ -ts_adapt_type my_scheme 38 39 Level: advanced 40 41 .keywords: TSAdapt, register 42 43 .seealso: TSAdaptRegisterAll() 44 @*/ 45 PetscErrorCode TSAdaptRegister(const char sname[],PetscErrorCode (*function)(TSAdapt)) 46 { 47 PetscErrorCode ierr; 48 49 PetscFunctionBegin; 50 ierr = TSAdaptInitializePackage();CHKERRQ(ierr); 51 ierr = PetscFunctionListAdd(&TSAdaptList,sname,function);CHKERRQ(ierr); 52 PetscFunctionReturn(0); 53 } 54 55 /*@C 56 TSAdaptRegisterAll - Registers all of the adaptivity schemes in TSAdapt 57 58 Not Collective 59 60 Level: advanced 61 62 .keywords: TSAdapt, register, all 63 64 .seealso: TSAdaptRegisterDestroy() 65 @*/ 66 PetscErrorCode TSAdaptRegisterAll(void) 67 { 68 PetscErrorCode ierr; 69 70 PetscFunctionBegin; 71 if (TSAdaptRegisterAllCalled) PetscFunctionReturn(0); 72 TSAdaptRegisterAllCalled = PETSC_TRUE; 73 ierr = TSAdaptRegister(TSADAPTNONE, TSAdaptCreate_None);CHKERRQ(ierr); 74 ierr = TSAdaptRegister(TSADAPTBASIC, TSAdaptCreate_Basic);CHKERRQ(ierr); 75 ierr = TSAdaptRegister(TSADAPTDSP, TSAdaptCreate_DSP);CHKERRQ(ierr); 76 ierr = TSAdaptRegister(TSADAPTCFL, TSAdaptCreate_CFL);CHKERRQ(ierr); 77 ierr = TSAdaptRegister(TSADAPTGLEE, TSAdaptCreate_GLEE);CHKERRQ(ierr); 78 ierr = TSAdaptRegister(TSADAPTHISTORY,TSAdaptCreate_History);CHKERRQ(ierr); 79 PetscFunctionReturn(0); 80 } 81 82 /*@C 83 TSAdaptFinalizePackage - This function destroys everything in the TS package. It is 84 called from PetscFinalize(). 85 86 Level: developer 87 88 .keywords: Petsc, destroy, package 89 .seealso: PetscFinalize() 90 @*/ 91 PetscErrorCode TSAdaptFinalizePackage(void) 92 { 93 PetscErrorCode ierr; 94 95 PetscFunctionBegin; 96 ierr = PetscFunctionListDestroy(&TSAdaptList);CHKERRQ(ierr); 97 TSAdaptPackageInitialized = PETSC_FALSE; 98 TSAdaptRegisterAllCalled = PETSC_FALSE; 99 PetscFunctionReturn(0); 100 } 101 102 /*@C 103 TSAdaptInitializePackage - This function initializes everything in the TSAdapt package. It is 104 called from TSInitializePackage(). 105 106 Level: developer 107 108 .keywords: TSAdapt, initialize, package 109 .seealso: PetscInitialize() 110 @*/ 111 PetscErrorCode TSAdaptInitializePackage(void) 112 { 113 PetscErrorCode ierr; 114 115 PetscFunctionBegin; 116 if (TSAdaptPackageInitialized) PetscFunctionReturn(0); 117 TSAdaptPackageInitialized = PETSC_TRUE; 118 ierr = PetscClassIdRegister("TSAdapt",&TSADAPT_CLASSID);CHKERRQ(ierr); 119 ierr = TSAdaptRegisterAll();CHKERRQ(ierr); 120 ierr = PetscRegisterFinalize(TSAdaptFinalizePackage);CHKERRQ(ierr); 121 PetscFunctionReturn(0); 122 } 123 124 /*@C 125 TSAdaptSetType - sets the approach used for the error adapter, currently there is only TSADAPTBASIC and TSADAPTNONE 126 127 Logicially Collective on TSAdapt 128 129 Input Parameter: 130 + adapt - the TS adapter, most likely obtained with TSGetAdapt() 131 - type - either TSADAPTBASIC or TSADAPTNONE 132 133 Options Database: 134 . -ts_adapt_type <basic or dsp or none> - to set the adapter type 135 136 Level: intermediate 137 138 .keywords: TSAdapt, create 139 140 .seealso: TSGetAdapt(), TSAdaptDestroy(), TSAdaptType, TSAdaptGetType() 141 @*/ 142 PetscErrorCode TSAdaptSetType(TSAdapt adapt,TSAdaptType type) 143 { 144 PetscBool match; 145 PetscErrorCode ierr,(*r)(TSAdapt); 146 147 PetscFunctionBegin; 148 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 149 PetscValidCharPointer(type,2); 150 ierr = PetscObjectTypeCompare((PetscObject)adapt,type,&match);CHKERRQ(ierr); 151 if (match) PetscFunctionReturn(0); 152 ierr = PetscFunctionListFind(TSAdaptList,type,&r);CHKERRQ(ierr); 153 if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown TSAdapt type \"%s\" given",type); 154 if (adapt->ops->destroy) {ierr = (*adapt->ops->destroy)(adapt);CHKERRQ(ierr);} 155 ierr = PetscMemzero(adapt->ops,sizeof(struct _TSAdaptOps));CHKERRQ(ierr); 156 ierr = PetscObjectChangeTypeName((PetscObject)adapt,type);CHKERRQ(ierr); 157 ierr = (*r)(adapt);CHKERRQ(ierr); 158 PetscFunctionReturn(0); 159 } 160 161 /*@C 162 TSAdaptGetType - gets the TS adapter method type (as a string). 163 164 Not Collective 165 166 Input Parameter: 167 . adapt - The TS adapter, most likely obtained with TSGetAdapt() 168 169 Output Parameter: 170 . type - The name of TS adapter method 171 172 Level: intermediate 173 174 .keywords: TSAdapt, get, type 175 .seealso TSAdaptSetType() 176 @*/ 177 PetscErrorCode TSAdaptGetType(TSAdapt adapt,TSAdaptType *type) 178 { 179 PetscFunctionBegin; 180 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 181 PetscValidPointer(type,2); 182 *type = ((PetscObject)adapt)->type_name; 183 PetscFunctionReturn(0); 184 } 185 186 PetscErrorCode TSAdaptSetOptionsPrefix(TSAdapt adapt,const char prefix[]) 187 { 188 PetscErrorCode ierr; 189 190 PetscFunctionBegin; 191 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 192 ierr = PetscObjectSetOptionsPrefix((PetscObject)adapt,prefix);CHKERRQ(ierr); 193 PetscFunctionReturn(0); 194 } 195 196 /*@C 197 TSAdaptLoad - Loads a TSAdapt that has been stored in binary with TSAdaptView(). 198 199 Collective on PetscViewer 200 201 Input Parameters: 202 + newdm - the newly loaded TSAdapt, this needs to have been created with TSAdaptCreate() or 203 some related function before a call to TSAdaptLoad(). 204 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or 205 HDF5 file viewer, obtained from PetscViewerHDF5Open() 206 207 Level: intermediate 208 209 Notes: 210 The type is determined by the data in the file, any type set into the TSAdapt before this call is ignored. 211 212 Notes for advanced users: 213 Most users should not need to know the details of the binary storage 214 format, since TSAdaptLoad() and TSAdaptView() completely hide these details. 215 But for anyone who's interested, the standard binary matrix storage 216 format is 217 .vb 218 has not yet been determined 219 .ve 220 221 .seealso: PetscViewerBinaryOpen(), TSAdaptView(), MatLoad(), VecLoad() 222 @*/ 223 PetscErrorCode TSAdaptLoad(TSAdapt adapt,PetscViewer viewer) 224 { 225 PetscErrorCode ierr; 226 PetscBool isbinary; 227 char type[256]; 228 229 PetscFunctionBegin; 230 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 231 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 232 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 233 if (!isbinary) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen()"); 234 235 ierr = PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);CHKERRQ(ierr); 236 ierr = TSAdaptSetType(adapt,type);CHKERRQ(ierr); 237 if (adapt->ops->load) { 238 ierr = (*adapt->ops->load)(adapt,viewer);CHKERRQ(ierr); 239 } 240 PetscFunctionReturn(0); 241 } 242 243 PetscErrorCode TSAdaptView(TSAdapt adapt,PetscViewer viewer) 244 { 245 PetscErrorCode ierr; 246 PetscBool iascii,isbinary,isnone; 247 248 PetscFunctionBegin; 249 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 250 if (!viewer) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)adapt),&viewer);CHKERRQ(ierr);} 251 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 252 PetscCheckSameComm(adapt,1,viewer,2); 253 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 254 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 255 if (iascii) { 256 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)adapt,viewer);CHKERRQ(ierr); 257 ierr = PetscObjectTypeCompare((PetscObject)adapt,TSADAPTNONE,&isnone);CHKERRQ(ierr); 258 if (!isnone) { 259 if (adapt->always_accept) {ierr = PetscViewerASCIIPrintf(viewer," always accepting steps\n");CHKERRQ(ierr);} 260 ierr = PetscViewerASCIIPrintf(viewer," safety factor %g\n",(double)adapt->safety);CHKERRQ(ierr); 261 ierr = PetscViewerASCIIPrintf(viewer," extra safety factor after step rejection %g\n",(double)adapt->reject_safety);CHKERRQ(ierr); 262 ierr = PetscViewerASCIIPrintf(viewer," clip fastest increase %g\n",(double)adapt->clip[1]);CHKERRQ(ierr); 263 ierr = PetscViewerASCIIPrintf(viewer," clip fastest decrease %g\n",(double)adapt->clip[0]);CHKERRQ(ierr); 264 ierr = PetscViewerASCIIPrintf(viewer," maximum allowed timestep %g\n",(double)adapt->dt_max);CHKERRQ(ierr); 265 ierr = PetscViewerASCIIPrintf(viewer," minimum allowed timestep %g\n",(double)adapt->dt_min);CHKERRQ(ierr); 266 } 267 if (adapt->ops->view) { 268 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 269 ierr = (*adapt->ops->view)(adapt,viewer);CHKERRQ(ierr); 270 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 271 } 272 } else if (isbinary) { 273 char type[256]; 274 275 /* need to save FILE_CLASS_ID for adapt class */ 276 ierr = PetscStrncpy(type,((PetscObject)adapt)->type_name,256);CHKERRQ(ierr); 277 ierr = PetscViewerBinaryWrite(viewer,type,256,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr); 278 } else if (adapt->ops->view) { 279 ierr = (*adapt->ops->view)(adapt,viewer);CHKERRQ(ierr); 280 } 281 PetscFunctionReturn(0); 282 } 283 284 /*@ 285 TSAdaptReset - Resets a TSAdapt context. 286 287 Collective on TS 288 289 Input Parameter: 290 . adapt - the TSAdapt context obtained from TSAdaptCreate() 291 292 Level: developer 293 294 .seealso: TSAdaptCreate(), TSAdaptDestroy() 295 @*/ 296 PetscErrorCode TSAdaptReset(TSAdapt adapt) 297 { 298 PetscErrorCode ierr; 299 300 PetscFunctionBegin; 301 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 302 if (adapt->ops->reset) {ierr = (*adapt->ops->reset)(adapt);CHKERRQ(ierr);} 303 PetscFunctionReturn(0); 304 } 305 306 PetscErrorCode TSAdaptDestroy(TSAdapt *adapt) 307 { 308 PetscErrorCode ierr; 309 310 PetscFunctionBegin; 311 if (!*adapt) PetscFunctionReturn(0); 312 PetscValidHeaderSpecific(*adapt,TSADAPT_CLASSID,1); 313 if (--((PetscObject)(*adapt))->refct > 0) {*adapt = NULL; PetscFunctionReturn(0);} 314 315 ierr = TSAdaptReset(*adapt);CHKERRQ(ierr); 316 317 if ((*adapt)->ops->destroy) {ierr = (*(*adapt)->ops->destroy)(*adapt);CHKERRQ(ierr);} 318 ierr = PetscViewerDestroy(&(*adapt)->monitor);CHKERRQ(ierr); 319 ierr = PetscHeaderDestroy(adapt);CHKERRQ(ierr); 320 PetscFunctionReturn(0); 321 } 322 323 /*@ 324 TSAdaptSetMonitor - Monitor the choices made by the adaptive controller 325 326 Collective on TSAdapt 327 328 Input Arguments: 329 + adapt - adaptive controller context 330 - flg - PETSC_TRUE to active a monitor, PETSC_FALSE to disable 331 332 Options Database Keys: 333 . -ts_adapt_monitor - to turn on monitoring 334 335 Level: intermediate 336 337 .seealso: TSAdaptChoose() 338 @*/ 339 PetscErrorCode TSAdaptSetMonitor(TSAdapt adapt,PetscBool flg) 340 { 341 PetscErrorCode ierr; 342 343 PetscFunctionBegin; 344 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 345 PetscValidLogicalCollectiveBool(adapt,flg,2); 346 if (flg) { 347 if (!adapt->monitor) {ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)adapt),"stdout",&adapt->monitor);CHKERRQ(ierr);} 348 } else { 349 ierr = PetscViewerDestroy(&adapt->monitor);CHKERRQ(ierr); 350 } 351 PetscFunctionReturn(0); 352 } 353 354 /*@C 355 TSAdaptSetCheckStage - Set a callback to check convergence for a stage 356 357 Logically collective on TSAdapt 358 359 Input Arguments: 360 + adapt - adaptive controller context 361 - func - stage check function 362 363 Arguments of func: 364 $ PetscErrorCode func(TSAdapt adapt,TS ts,PetscBool *accept) 365 366 + adapt - adaptive controller context 367 . ts - time stepping context 368 - accept - pending choice of whether to accept, can be modified by this routine 369 370 Level: advanced 371 372 .seealso: TSAdaptChoose() 373 @*/ 374 PetscErrorCode TSAdaptSetCheckStage(TSAdapt adapt,PetscErrorCode (*func)(TSAdapt,TS,PetscReal,Vec,PetscBool*)) 375 { 376 377 PetscFunctionBegin; 378 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 379 adapt->checkstage = func; 380 PetscFunctionReturn(0); 381 } 382 383 /*@ 384 TSAdaptSetAlwaysAccept - Set whether to always accept steps regardless of 385 any error or stability condition not meeting the prescribed goal. 386 387 Logically collective on TSAdapt 388 389 Input Arguments: 390 + adapt - time step adaptivity context, usually gotten with TSGetAdapt() 391 - flag - whether to always accept steps 392 393 Options Database Keys: 394 . -ts_adapt_always_accept - to always accept steps 395 396 Level: intermediate 397 398 .seealso: TSAdapt, TSAdaptChoose() 399 @*/ 400 PetscErrorCode TSAdaptSetAlwaysAccept(TSAdapt adapt,PetscBool flag) 401 { 402 PetscFunctionBegin; 403 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 404 PetscValidLogicalCollectiveBool(adapt,flag,2); 405 adapt->always_accept = flag; 406 PetscFunctionReturn(0); 407 } 408 409 /*@ 410 TSAdaptSetSafety - Set safety factors 411 412 Logically collective on TSAdapt 413 414 Input Arguments: 415 + adapt - adaptive controller context 416 . safety - safety factor relative to target error/stability goal 417 - reject_safety - extra safety factor to apply if the last step was rejected 418 419 Options Database Keys: 420 + -ts_adapt_safety <safety> - to set safety factor 421 - -ts_adapt_reject_safety <reject_safety> - to set reject safety factor 422 423 Level: intermediate 424 425 .seealso: TSAdapt, TSAdaptGetSafety(), TSAdaptChoose() 426 @*/ 427 PetscErrorCode TSAdaptSetSafety(TSAdapt adapt,PetscReal safety,PetscReal reject_safety) 428 { 429 PetscFunctionBegin; 430 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 431 PetscValidLogicalCollectiveReal(adapt,safety,2); 432 PetscValidLogicalCollectiveReal(adapt,reject_safety,3); 433 if (safety != PETSC_DEFAULT && safety < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Safety factor %g must be non negative",(double)safety); 434 if (safety != PETSC_DEFAULT && safety > 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Safety factor %g must be less than one",(double)safety); 435 if (reject_safety != PETSC_DEFAULT && reject_safety < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Reject safety factor %g must be non negative",(double)reject_safety); 436 if (reject_safety != PETSC_DEFAULT && reject_safety > 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Reject safety factor %g must be less than one",(double)reject_safety); 437 if (safety != PETSC_DEFAULT) adapt->safety = safety; 438 if (reject_safety != PETSC_DEFAULT) adapt->reject_safety = reject_safety; 439 PetscFunctionReturn(0); 440 } 441 442 /*@ 443 TSAdaptGetSafety - Get safety factors 444 445 Not Collective 446 447 Input Arguments: 448 . adapt - adaptive controller context 449 450 Ouput Arguments: 451 . safety - safety factor relative to target error/stability goal 452 + reject_safety - extra safety factor to apply if the last step was rejected 453 454 Level: intermediate 455 456 .seealso: TSAdapt, TSAdaptSetSafety(), TSAdaptChoose() 457 @*/ 458 PetscErrorCode TSAdaptGetSafety(TSAdapt adapt,PetscReal *safety,PetscReal *reject_safety) 459 { 460 PetscFunctionBegin; 461 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 462 if (safety) PetscValidRealPointer(safety,2); 463 if (reject_safety) PetscValidRealPointer(reject_safety,3); 464 if (safety) *safety = adapt->safety; 465 if (reject_safety) *reject_safety = adapt->reject_safety; 466 PetscFunctionReturn(0); 467 } 468 469 /*@ 470 TSAdaptSetClip - Sets the admissible decrease/increase factor in step size 471 472 Logically collective on TSAdapt 473 474 Input Arguments: 475 + adapt - adaptive controller context 476 . low - admissible decrease factor 477 - high - admissible increase factor 478 479 Options Database Keys: 480 . -ts_adapt_clip <low>,<high> - to set admissible time step decrease and increase factors 481 482 Level: intermediate 483 484 .seealso: TSAdaptChoose(), TSAdaptGetClip() 485 @*/ 486 PetscErrorCode TSAdaptSetClip(TSAdapt adapt,PetscReal low,PetscReal high) 487 { 488 PetscFunctionBegin; 489 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 490 PetscValidLogicalCollectiveReal(adapt,low,2); 491 PetscValidLogicalCollectiveReal(adapt,high,3); 492 if (low != PETSC_DEFAULT && low < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Decrease factor %g must be non negative",(double)low); 493 if (low != PETSC_DEFAULT && low > 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Decrease factor %g must be less than one",(double)low); 494 if (high != PETSC_DEFAULT && high < 1) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Increase factor %g must be geather than one",(double)high); 495 if (low != PETSC_DEFAULT) adapt->clip[0] = low; 496 if (high != PETSC_DEFAULT) adapt->clip[1] = high; 497 PetscFunctionReturn(0); 498 } 499 500 /*@ 501 TSAdaptGetClip - Gets the admissible decrease/increase factor in step size 502 503 Not Collective 504 505 Input Arguments: 506 . adapt - adaptive controller context 507 508 Ouput Arguments: 509 + low - optional, admissible decrease factor 510 - high - optional, admissible increase factor 511 512 Level: intermediate 513 514 .seealso: TSAdaptChoose(), TSAdaptSetClip() 515 @*/ 516 PetscErrorCode TSAdaptGetClip(TSAdapt adapt,PetscReal *low,PetscReal *high) 517 { 518 PetscFunctionBegin; 519 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 520 if (low) PetscValidRealPointer(low,2); 521 if (high) PetscValidRealPointer(high,3); 522 if (low) *low = adapt->clip[0]; 523 if (high) *high = adapt->clip[1]; 524 PetscFunctionReturn(0); 525 } 526 527 /*@ 528 TSAdaptSetStepLimits - Set the minimum and maximum step sizes to be considered by the controller 529 530 Logically collective on TSAdapt 531 532 Input Arguments: 533 + adapt - time step adaptivity context, usually gotten with TSGetAdapt() 534 . hmin - minimum time step 535 - hmax - maximum time step 536 537 Options Database Keys: 538 + -ts_adapt_dt_min <min> - to set minimum time step 539 - -ts_adapt_dt_max <max> - to set maximum time step 540 541 Level: intermediate 542 543 .seealso: TSAdapt, TSAdaptGetStepLimits(), TSAdaptChoose() 544 @*/ 545 PetscErrorCode TSAdaptSetStepLimits(TSAdapt adapt,PetscReal hmin,PetscReal hmax) 546 { 547 548 PetscFunctionBegin; 549 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 550 PetscValidLogicalCollectiveReal(adapt,hmin,2); 551 PetscValidLogicalCollectiveReal(adapt,hmax,3); 552 if (hmin != PETSC_DEFAULT && hmin < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Minimum time step %g must be non negative",(double)hmin); 553 if (hmax != PETSC_DEFAULT && hmax < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Minimum time step %g must be non negative",(double)hmax); 554 if (hmin != PETSC_DEFAULT) adapt->dt_min = hmin; 555 if (hmax != PETSC_DEFAULT) adapt->dt_max = hmax; 556 hmin = adapt->dt_min; 557 hmax = adapt->dt_max; 558 if (hmax <= hmin) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Maximum time step %g must geather than minimum time step %g",(double)hmax,(double)hmin); 559 PetscFunctionReturn(0); 560 } 561 562 /*@ 563 TSAdaptGetStepLimits - Get the minimum and maximum step sizes to be considered by the controller 564 565 Not Collective 566 567 Input Arguments: 568 . adapt - time step adaptivity context, usually gotten with TSGetAdapt() 569 570 Output Arguments: 571 + hmin - minimum time step 572 - hmax - maximum time step 573 574 Level: intermediate 575 576 .seealso: TSAdapt, TSAdaptSetStepLimits(), TSAdaptChoose() 577 @*/ 578 PetscErrorCode TSAdaptGetStepLimits(TSAdapt adapt,PetscReal *hmin,PetscReal *hmax) 579 { 580 581 PetscFunctionBegin; 582 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 583 if (hmin) PetscValidRealPointer(hmin,2); 584 if (hmax) PetscValidRealPointer(hmax,3); 585 if (hmin) *hmin = adapt->dt_min; 586 if (hmax) *hmax = adapt->dt_max; 587 PetscFunctionReturn(0); 588 } 589 590 /* 591 TSAdaptSetFromOptions - Sets various TSAdapt parameters from user options. 592 593 Collective on TSAdapt 594 595 Input Parameter: 596 . adapt - the TSAdapt context 597 598 Options Database Keys: 599 + -ts_adapt_type <type> - algorithm to use for adaptivity 600 . -ts_adapt_always_accept - always accept steps regardless of error/stability goals 601 . -ts_adapt_safety <safety> - safety factor relative to target error/stability goal 602 . -ts_adapt_reject_safety <safety> - extra safety factor to apply if the last step was rejected 603 . -ts_adapt_clip <low,high> - admissible time step decrease and increase factors 604 . -ts_adapt_dt_min <min> - minimum timestep to use 605 . -ts_adapt_dt_max <max> - maximum timestep to use 606 . -ts_adapt_scale_solve_failed <scale> - scale timestep by this factor if a solve fails 607 . -ts_adapt_wnormtype <2 or infinity> - type of norm for computing error estimates 608 - -ts_adapt_time_step_increase_delay - number of timesteps to delay increasing the time step after it has been decreased due to failed solver 609 610 Level: advanced 611 612 Notes: 613 This function is automatically called by TSSetFromOptions() 614 615 .keywords: TS, TSGetAdapt(), TSAdaptSetType(), TSAdaptSetStepLimits() 616 617 .seealso: TSGetAdapt(), TSAdaptSetType(), TSAdaptSetAlwaysAccept(), TSAdaptSetSafety(), 618 TSAdaptSetClip(), TSAdaptSetStepLimits(), TSAdaptSetMonitor() 619 */ 620 PetscErrorCode TSAdaptSetFromOptions(PetscOptionItems *PetscOptionsObject,TSAdapt adapt) 621 { 622 PetscErrorCode ierr; 623 char type[256] = TSADAPTBASIC; 624 PetscReal safety,reject_safety,clip[2],hmin,hmax; 625 PetscBool set,flg; 626 PetscInt two; 627 628 PetscFunctionBegin; 629 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 630 /* This should use PetscOptionsBegin() if/when this becomes an object used outside of TS, but currently this 631 * function can only be called from inside TSSetFromOptions() */ 632 ierr = PetscOptionsHead(PetscOptionsObject,"TS Adaptivity options");CHKERRQ(ierr); 633 ierr = PetscOptionsFList("-ts_adapt_type","Algorithm to use for adaptivity","TSAdaptSetType",TSAdaptList,((PetscObject)adapt)->type_name ? ((PetscObject)adapt)->type_name : type,type,sizeof(type),&flg);CHKERRQ(ierr); 634 if (flg || !((PetscObject)adapt)->type_name) { 635 ierr = TSAdaptSetType(adapt,type);CHKERRQ(ierr); 636 } 637 638 ierr = PetscOptionsBool("-ts_adapt_always_accept","Always accept the step","TSAdaptSetAlwaysAccept",adapt->always_accept,&flg,&set);CHKERRQ(ierr); 639 if (set) {ierr = TSAdaptSetAlwaysAccept(adapt,flg);CHKERRQ(ierr);} 640 641 safety = adapt->safety; reject_safety = adapt->reject_safety; 642 ierr = PetscOptionsReal("-ts_adapt_safety","Safety factor relative to target error/stability goal","TSAdaptSetSafety",safety,&safety,&set);CHKERRQ(ierr); 643 ierr = PetscOptionsReal("-ts_adapt_reject_safety","Extra safety factor to apply if the last step was rejected","TSAdaptSetSafety",reject_safety,&reject_safety,&flg);CHKERRQ(ierr); 644 if (set || flg) {ierr = TSAdaptSetSafety(adapt,safety,reject_safety);CHKERRQ(ierr);} 645 646 two = 2; clip[0] = adapt->clip[0]; clip[1] = adapt->clip[1]; 647 ierr = PetscOptionsRealArray("-ts_adapt_clip","Admissible decrease/increase factor in step size","TSAdaptSetClip",clip,&two,&set);CHKERRQ(ierr); 648 if (set && (two != 2)) SETERRQ(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_OUTOFRANGE,"Must give exactly two values to -ts_adapt_clip"); 649 if (set) {ierr = TSAdaptSetClip(adapt,clip[0],clip[1]);CHKERRQ(ierr);} 650 651 hmin = adapt->dt_min; hmax = adapt->dt_max; 652 ierr = PetscOptionsReal("-ts_adapt_dt_min","Minimum time step considered","TSAdaptSetStepLimits",hmin,&hmin,&set);CHKERRQ(ierr); 653 ierr = PetscOptionsReal("-ts_adapt_dt_max","Maximum time step considered","TSAdaptSetStepLimits",hmax,&hmax,&flg);CHKERRQ(ierr); 654 if (set || flg) {ierr = TSAdaptSetStepLimits(adapt,hmin,hmax);CHKERRQ(ierr);} 655 656 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); 657 658 ierr = PetscOptionsEnum("-ts_adapt_wnormtype","Type of norm computed for error estimation","",NormTypes,(PetscEnum)adapt->wnormtype,(PetscEnum*)&adapt->wnormtype,NULL);CHKERRQ(ierr); 659 if (adapt->wnormtype != NORM_2 && adapt->wnormtype != NORM_INFINITY) SETERRQ(PetscObjectComm((PetscObject)adapt),PETSC_ERR_SUP,"Only 2-norm and infinite norm supported"); 660 661 ierr = 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);CHKERRQ(ierr); 662 663 ierr = PetscOptionsBool("-ts_adapt_monitor","Print choices made by adaptive controller","TSAdaptSetMonitor",adapt->monitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr); 664 if (set) {ierr = TSAdaptSetMonitor(adapt,flg);CHKERRQ(ierr);} 665 666 if (adapt->ops->setfromoptions) {ierr = (*adapt->ops->setfromoptions)(PetscOptionsObject,adapt);CHKERRQ(ierr);} 667 ierr = PetscOptionsTail();CHKERRQ(ierr); 668 PetscFunctionReturn(0); 669 } 670 671 /*@ 672 TSAdaptCandidatesClear - clear any previously set candidate schemes 673 674 Logically collective on TSAdapt 675 676 Input Argument: 677 . adapt - adaptive controller 678 679 Level: developer 680 681 .seealso: TSAdapt, TSAdaptCreate(), TSAdaptCandidateAdd(), TSAdaptChoose() 682 @*/ 683 PetscErrorCode TSAdaptCandidatesClear(TSAdapt adapt) 684 { 685 PetscErrorCode ierr; 686 687 PetscFunctionBegin; 688 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 689 ierr = PetscMemzero(&adapt->candidates,sizeof(adapt->candidates));CHKERRQ(ierr); 690 PetscFunctionReturn(0); 691 } 692 693 /*@C 694 TSAdaptCandidateAdd - add a candidate scheme for the adaptive controller to select from 695 696 Logically collective on TSAdapt 697 698 Input Arguments: 699 + adapt - time step adaptivity context, obtained with TSGetAdapt() or TSAdaptCreate() 700 . name - name of the candidate scheme to add 701 . order - order of the candidate scheme 702 . stageorder - stage order of the candidate scheme 703 . ccfl - stability coefficient relative to explicit Euler, used for CFL constraints 704 . cost - relative measure of the amount of work required for the candidate scheme 705 - inuse - indicates that this scheme is the one currently in use, this flag can only be set for one scheme 706 707 Note: 708 This routine is not available in Fortran. 709 710 Level: developer 711 712 .seealso: TSAdaptCandidatesClear(), TSAdaptChoose() 713 @*/ 714 PetscErrorCode TSAdaptCandidateAdd(TSAdapt adapt,const char name[],PetscInt order,PetscInt stageorder,PetscReal ccfl,PetscReal cost,PetscBool inuse) 715 { 716 PetscInt c; 717 718 PetscFunctionBegin; 719 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 720 if (order < 1) SETERRQ1(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_OUTOFRANGE,"Classical order %D must be a positive integer",order); 721 if (inuse) { 722 if (adapt->candidates.inuse_set) SETERRQ(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_WRONGSTATE,"Cannot set the inuse method twice, maybe forgot to call TSAdaptCandidatesClear()"); 723 adapt->candidates.inuse_set = PETSC_TRUE; 724 } 725 /* first slot if this is the current scheme, otherwise the next available slot */ 726 c = inuse ? 0 : !adapt->candidates.inuse_set + adapt->candidates.n; 727 728 adapt->candidates.name[c] = name; 729 adapt->candidates.order[c] = order; 730 adapt->candidates.stageorder[c] = stageorder; 731 adapt->candidates.ccfl[c] = ccfl; 732 adapt->candidates.cost[c] = cost; 733 adapt->candidates.n++; 734 PetscFunctionReturn(0); 735 } 736 737 /*@C 738 TSAdaptCandidatesGet - Get the list of candidate orders of accuracy and cost 739 740 Not Collective 741 742 Input Arguments: 743 . adapt - time step adaptivity context 744 745 Output Arguments: 746 + n - number of candidate schemes, always at least 1 747 . order - the order of each candidate scheme 748 . stageorder - the stage order of each candidate scheme 749 . ccfl - the CFL coefficient of each scheme 750 - cost - the relative cost of each scheme 751 752 Level: developer 753 754 Note: 755 The current scheme is always returned in the first slot 756 757 .seealso: TSAdaptCandidatesClear(), TSAdaptCandidateAdd(), TSAdaptChoose() 758 @*/ 759 PetscErrorCode TSAdaptCandidatesGet(TSAdapt adapt,PetscInt *n,const PetscInt **order,const PetscInt **stageorder,const PetscReal **ccfl,const PetscReal **cost) 760 { 761 PetscFunctionBegin; 762 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 763 if (n) *n = adapt->candidates.n; 764 if (order) *order = adapt->candidates.order; 765 if (stageorder) *stageorder = adapt->candidates.stageorder; 766 if (ccfl) *ccfl = adapt->candidates.ccfl; 767 if (cost) *cost = adapt->candidates.cost; 768 PetscFunctionReturn(0); 769 } 770 771 /*@C 772 TSAdaptChoose - choose which method and step size to use for the next step 773 774 Collective on TSAdapt 775 776 Input Arguments: 777 + adapt - adaptive contoller 778 - h - current step size 779 780 Output Arguments: 781 + next_sc - optional, scheme to use for the next step 782 . next_h - step size to use for the next step 783 - accept - PETSC_TRUE to accept the current step, PETSC_FALSE to repeat the current step with the new step size 784 785 Note: 786 The input value of parameter accept is retained from the last time step, so it will be PETSC_FALSE if the step is 787 being retried after an initial rejection. 788 789 Level: developer 790 791 .seealso: TSAdapt, TSAdaptCandidatesClear(), TSAdaptCandidateAdd() 792 @*/ 793 PetscErrorCode TSAdaptChoose(TSAdapt adapt,TS ts,PetscReal h,PetscInt *next_sc,PetscReal *next_h,PetscBool *accept) 794 { 795 PetscErrorCode ierr; 796 PetscInt ncandidates = adapt->candidates.n; 797 PetscInt scheme = 0; 798 PetscReal wlte = -1.0; 799 PetscReal wltea = -1.0; 800 PetscReal wlter = -1.0; 801 802 PetscFunctionBegin; 803 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 804 PetscValidHeaderSpecific(ts,TS_CLASSID,2); 805 if (next_sc) PetscValidIntPointer(next_sc,4); 806 PetscValidPointer(next_h,5); 807 PetscValidIntPointer(accept,6); 808 if (next_sc) *next_sc = 0; 809 810 /* Do not mess with adaptivity while handling events*/ 811 if (ts->event && ts->event->status != TSEVENT_NONE) { 812 *next_h = h; 813 *accept = PETSC_TRUE; 814 PetscFunctionReturn(0); 815 } 816 817 ierr = (*adapt->ops->choose)(adapt,ts,h,&scheme,next_h,accept,&wlte,&wltea,&wlter);CHKERRQ(ierr); 818 if (scheme < 0 || (ncandidates > 0 && scheme >= ncandidates)) SETERRQ2(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_OUTOFRANGE,"Chosen scheme %D not in valid range 0..%D",scheme,ncandidates-1); 819 if (*next_h < 0) SETERRQ1(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_OUTOFRANGE,"Computed step size %g must be positive",(double)*next_h); 820 if (next_sc) *next_sc = scheme; 821 822 if (*accept && ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP) { 823 /* Increase/reduce step size if end time of next step is close to or overshoots max time */ 824 PetscReal t = ts->ptime + ts->time_step, h = *next_h; 825 PetscReal tend = t + h, tmax = ts->max_time, hmax = tmax - t; 826 PetscReal a = (PetscReal)(1.0 + adapt->matchstepfac[0]); 827 PetscReal b = adapt->matchstepfac[1]; 828 if (t < tmax && tend > tmax) *next_h = hmax; 829 if (t < tmax && tend < tmax && h*b > hmax) *next_h = hmax/2; 830 if (t < tmax && tend < tmax && h*a > hmax) *next_h = hmax; 831 } 832 833 if (adapt->monitor) { 834 const char *sc_name = (scheme < ncandidates) ? adapt->candidates.name[scheme] : ""; 835 ierr = PetscViewerASCIIAddTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr); 836 if (wlte < 0) { 837 ierr = PetscViewerASCIIPrintf(adapt->monitor," TSAdapt %s %s %D:%s step %3D %s t=%-11g+%10.3e dt=%-10.3e\n",((PetscObject)adapt)->type_name,((PetscObject)ts)->type_name,scheme,sc_name,ts->steps,*accept ? "accepted" : "rejected",(double)ts->ptime,(double)h,(double)*next_h);CHKERRQ(ierr); 838 } else { 839 ierr = PetscViewerASCIIPrintf(adapt->monitor," TSAdapt %s %s %D:%s step %3D %s t=%-11g+%10.3e dt=%-10.3e wlte=%5.3g wltea=%5.3g wlter=%5.3g\n",((PetscObject)adapt)->type_name,((PetscObject)ts)->type_name,scheme,sc_name,ts->steps,*accept ? "accepted" : "rejected",(double)ts->ptime,(double)h,(double)*next_h,(double)wlte,(double)wltea,(double)wlter);CHKERRQ(ierr); 840 } 841 ierr = PetscViewerASCIISubtractTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr); 842 } 843 PetscFunctionReturn(0); 844 } 845 846 /*@ 847 TSAdaptSetTimeStepIncreaseDelay - The number of timesteps to wait after a decrease in the timestep due to failed solver 848 before increasing the time step. 849 850 Logicially Collective on TSAdapt 851 852 Input Arguments: 853 + adapt - adaptive controller context 854 - cnt - the number of timesteps 855 856 Options Database Key: 857 . -ts_adapt_time_step_increase_delay cnt - number of steps to delay the increase 858 859 Notes: This is to prevent an adaptor from bouncing back and forth between two nearby timesteps. The default is 0. 860 The successful use of this option is problem dependent 861 862 Developer Note: there is no theory to support this option 863 864 Level: advanced 865 866 .seealso: 867 @*/ 868 PetscErrorCode TSAdaptSetTimeStepIncreaseDelay(TSAdapt adapt,PetscInt cnt) 869 { 870 PetscFunctionBegin; 871 adapt->timestepjustdecreased_delay = cnt; 872 PetscFunctionReturn(0); 873 } 874 875 876 /*@ 877 TSAdaptCheckStage - checks whether to accept a stage, (e.g. reject and change time step size if nonlinear solve fails) 878 879 Collective on TSAdapt 880 881 Input Arguments: 882 + adapt - adaptive controller context 883 . ts - time stepper 884 . t - Current simulation time 885 - Y - Current solution vector 886 887 Output Arguments: 888 . accept - PETSC_TRUE to accept the stage, PETSC_FALSE to reject 889 890 Level: developer 891 892 .seealso: 893 @*/ 894 PetscErrorCode TSAdaptCheckStage(TSAdapt adapt,TS ts,PetscReal t,Vec Y,PetscBool *accept) 895 { 896 PetscErrorCode ierr; 897 SNESConvergedReason snesreason = SNES_CONVERGED_ITERATING; 898 899 PetscFunctionBegin; 900 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 901 PetscValidHeaderSpecific(ts,TS_CLASSID,2); 902 PetscValidIntPointer(accept,3); 903 904 if (ts->snes) {ierr = SNESGetConvergedReason(ts->snes,&snesreason);CHKERRQ(ierr);} 905 if (snesreason < 0) { 906 *accept = PETSC_FALSE; 907 if (++ts->num_snes_failures >= ts->max_snes_failures && ts->max_snes_failures > 0) { 908 ts->reason = TS_DIVERGED_NONLINEAR_SOLVE; 909 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); 910 if (adapt->monitor) { 911 ierr = PetscViewerASCIIAddTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr); 912 ierr = PetscViewerASCIIPrintf(adapt->monitor," TSAdapt %s step %3D stage rejected t=%-11g+%10.3e, nonlinear solve failures %D greater than current TS allowed\n",((PetscObject)adapt)->type_name,ts->steps,(double)ts->ptime,(double)ts->time_step,ts->num_snes_failures);CHKERRQ(ierr); 913 ierr = PetscViewerASCIISubtractTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr); 914 } 915 } 916 } else { 917 *accept = PETSC_TRUE; 918 ierr = TSFunctionDomainError(ts,t,Y,accept);CHKERRQ(ierr); 919 if(*accept && adapt->checkstage) { 920 ierr = (*adapt->checkstage)(adapt,ts,t,Y,accept);CHKERRQ(ierr); 921 } 922 } 923 924 if(!(*accept) && !ts->reason) { 925 PetscReal dt,new_dt; 926 ierr = TSGetTimeStep(ts,&dt);CHKERRQ(ierr); 927 new_dt = dt * adapt->scale_solve_failed; 928 ierr = TSSetTimeStep(ts,new_dt);CHKERRQ(ierr); 929 adapt->timestepjustdecreased += adapt->timestepjustdecreased_delay; 930 if (adapt->monitor) { 931 ierr = PetscViewerASCIIAddTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr); 932 ierr = PetscViewerASCIIPrintf(adapt->monitor," TSAdapt %s step %3D stage rejected (%s) t=%-11g+%10.3e retrying with dt=%-10.3e\n",((PetscObject)adapt)->type_name,ts->steps,SNESConvergedReasons[snesreason],(double)ts->ptime,(double)dt,(double)new_dt);CHKERRQ(ierr); 933 ierr = PetscViewerASCIISubtractTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr); 934 } 935 } 936 PetscFunctionReturn(0); 937 } 938 939 /*@ 940 TSAdaptCreate - create an adaptive controller context for time stepping 941 942 Collective on MPI_Comm 943 944 Input Parameter: 945 . comm - The communicator 946 947 Output Parameter: 948 . adapt - new TSAdapt object 949 950 Level: developer 951 952 Notes: 953 TSAdapt creation is handled by TS, so users should not need to call this function. 954 955 .keywords: TSAdapt, create 956 .seealso: TSGetAdapt(), TSAdaptSetType(), TSAdaptDestroy() 957 @*/ 958 PetscErrorCode TSAdaptCreate(MPI_Comm comm,TSAdapt *inadapt) 959 { 960 PetscErrorCode ierr; 961 TSAdapt adapt; 962 963 PetscFunctionBegin; 964 PetscValidPointer(inadapt,1); 965 *inadapt = NULL; 966 ierr = TSAdaptInitializePackage();CHKERRQ(ierr); 967 968 ierr = PetscHeaderCreate(adapt,TSADAPT_CLASSID,"TSAdapt","Time stepping adaptivity","TS",comm,TSAdaptDestroy,TSAdaptView);CHKERRQ(ierr); 969 970 adapt->always_accept = PETSC_FALSE; 971 adapt->safety = 0.9; 972 adapt->reject_safety = 0.5; 973 adapt->clip[0] = 0.1; 974 adapt->clip[1] = 10.; 975 adapt->dt_min = 1e-20; 976 adapt->dt_max = 1e+20; 977 adapt->scale_solve_failed = 0.25; 978 /* these two safety factors are not public, and they are used only in the TS_EXACTFINALTIME_MATCHSTEP case 979 to prevent from situations were unreasonably small time steps are taken in order to match the final time */ 980 adapt->matchstepfac[0] = 0.01; /* allow 1% step size increase in the last step */ 981 adapt->matchstepfac[1] = 2.0; /* halve last step if it is greater than what remains divided this factor */ 982 adapt->wnormtype = NORM_2; 983 adapt->timestepjustdecreased_delay = 0; 984 985 *inadapt = adapt; 986 PetscFunctionReturn(0); 987 } 988