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