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_GLEE(TSAdapt); 11 PETSC_EXTERN PetscErrorCode TSAdaptCreate_None(TSAdapt); 12 PETSC_EXTERN PetscErrorCode TSAdaptCreate_Basic(TSAdapt); 13 PETSC_EXTERN PetscErrorCode TSAdaptCreate_CFL(TSAdapt); 14 15 /*@C 16 TSAdaptRegister - adds a TSAdapt implementation 17 18 Not Collective 19 20 Input Parameters: 21 + name_scheme - name of user-defined adaptivity scheme 22 - routine_create - routine to create method context 23 24 Notes: 25 TSAdaptRegister() may be called multiple times to add several user-defined families. 26 27 Sample usage: 28 .vb 29 TSAdaptRegister("my_scheme",MySchemeCreate); 30 .ve 31 32 Then, your scheme can be chosen with the procedural interface via 33 $ TSAdaptSetType(ts,"my_scheme") 34 or at runtime via the option 35 $ -ts_adapt_type my_scheme 36 37 Level: advanced 38 39 .keywords: TSAdapt, register 40 41 .seealso: TSAdaptRegisterAll() 42 @*/ 43 PetscErrorCode TSAdaptRegister(const char sname[],PetscErrorCode (*function)(TSAdapt)) 44 { 45 PetscErrorCode ierr; 46 47 PetscFunctionBegin; 48 ierr = PetscFunctionListAdd(&TSAdaptList,sname,function);CHKERRQ(ierr); 49 PetscFunctionReturn(0); 50 } 51 52 /*@C 53 TSAdaptRegisterAll - Registers all of the adaptivity schemes in TSAdapt 54 55 Not Collective 56 57 Level: advanced 58 59 .keywords: TSAdapt, register, all 60 61 .seealso: TSAdaptRegisterDestroy() 62 @*/ 63 PetscErrorCode TSAdaptRegisterAll(void) 64 { 65 PetscErrorCode ierr; 66 67 PetscFunctionBegin; 68 if (TSAdaptRegisterAllCalled) PetscFunctionReturn(0); 69 TSAdaptRegisterAllCalled = PETSC_TRUE; 70 ierr = TSAdaptRegister(TSADAPTGLEE ,TSAdaptCreate_GLEE);CHKERRQ(ierr); 71 ierr = TSAdaptRegister(TSADAPTNONE, TSAdaptCreate_None);CHKERRQ(ierr); 72 ierr = TSAdaptRegister(TSADAPTBASIC,TSAdaptCreate_Basic);CHKERRQ(ierr); 73 ierr = TSAdaptRegister(TSADAPTCFL, TSAdaptCreate_CFL);CHKERRQ(ierr); 74 PetscFunctionReturn(0); 75 } 76 77 /*@C 78 TSAdaptFinalizePackage - This function destroys everything in the TS package. It is 79 called from PetscFinalize(). 80 81 Level: developer 82 83 .keywords: Petsc, destroy, package 84 .seealso: PetscFinalize() 85 @*/ 86 PetscErrorCode TSAdaptFinalizePackage(void) 87 { 88 PetscErrorCode ierr; 89 90 PetscFunctionBegin; 91 ierr = PetscFunctionListDestroy(&TSAdaptList);CHKERRQ(ierr); 92 TSAdaptPackageInitialized = PETSC_FALSE; 93 TSAdaptRegisterAllCalled = PETSC_FALSE; 94 PetscFunctionReturn(0); 95 } 96 97 /*@C 98 TSAdaptInitializePackage - This function initializes everything in the TSAdapt package. It is 99 called from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to 100 TSCreate_GLLE() when using static libraries. 101 102 Level: developer 103 104 .keywords: TSAdapt, initialize, package 105 .seealso: PetscInitialize() 106 @*/ 107 PetscErrorCode TSAdaptInitializePackage(void) 108 { 109 PetscErrorCode ierr; 110 111 PetscFunctionBegin; 112 if (TSAdaptPackageInitialized) PetscFunctionReturn(0); 113 TSAdaptPackageInitialized = PETSC_TRUE; 114 ierr = PetscClassIdRegister("TSAdapt",&TSADAPT_CLASSID);CHKERRQ(ierr); 115 ierr = TSAdaptRegisterAll();CHKERRQ(ierr); 116 ierr = PetscRegisterFinalize(TSAdaptFinalizePackage);CHKERRQ(ierr); 117 PetscFunctionReturn(0); 118 } 119 120 /*@C 121 TSAdaptSetType - sets the approach used for the error adapter, currently there is only TSADAPTBASIC and TSADAPTNONE 122 123 Logicially Collective on TSAdapt 124 125 Input Parameter: 126 + adapt - the TS error adapter, most likely obtained with TSGetAdapt() 127 - type - either TSADAPTBASIC or TSADAPTNONE 128 129 Options Database: 130 . -ts_adapt_type basic or none - to setting the adapter type 131 132 Level: intermediate 133 134 .keywords: TSAdapt, create 135 136 .seealso: TSGetAdapt(), TSAdaptDestroy(), TSAdaptType, TSAdaptGetType() 137 @*/ 138 PetscErrorCode TSAdaptSetType(TSAdapt adapt,TSAdaptType type) 139 { 140 PetscBool match; 141 PetscErrorCode ierr,(*r)(TSAdapt); 142 143 PetscFunctionBegin; 144 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 145 ierr = PetscObjectTypeCompare((PetscObject)adapt,type,&match);CHKERRQ(ierr); 146 if (match) PetscFunctionReturn(0); 147 ierr = PetscFunctionListFind(TSAdaptList,type,&r);CHKERRQ(ierr); 148 if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown TSAdapt type \"%s\" given",type); 149 if (adapt->ops->destroy) {ierr = (*adapt->ops->destroy)(adapt);CHKERRQ(ierr);} 150 ierr = PetscMemzero(adapt->ops,sizeof(struct _TSAdaptOps));CHKERRQ(ierr); 151 ierr = PetscObjectChangeTypeName((PetscObject)adapt,type);CHKERRQ(ierr); 152 ierr = (*r)(adapt);CHKERRQ(ierr); 153 PetscFunctionReturn(0); 154 } 155 156 PetscErrorCode TSAdaptSetOptionsPrefix(TSAdapt adapt,const char prefix[]) 157 { 158 PetscErrorCode ierr; 159 160 PetscFunctionBegin; 161 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 162 ierr = PetscObjectSetOptionsPrefix((PetscObject)adapt,prefix);CHKERRQ(ierr); 163 PetscFunctionReturn(0); 164 } 165 166 /*@C 167 TSAdaptLoad - Loads a TSAdapt that has been stored in binary with TSAdaptView(). 168 169 Collective on PetscViewer 170 171 Input Parameters: 172 + newdm - the newly loaded TSAdapt, this needs to have been created with TSAdaptCreate() or 173 some related function before a call to TSAdaptLoad(). 174 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or 175 HDF5 file viewer, obtained from PetscViewerHDF5Open() 176 177 Level: intermediate 178 179 Notes: 180 The type is determined by the data in the file, any type set into the TSAdapt before this call is ignored. 181 182 Notes for advanced users: 183 Most users should not need to know the details of the binary storage 184 format, since TSAdaptLoad() and TSAdaptView() completely hide these details. 185 But for anyone who's interested, the standard binary matrix storage 186 format is 187 .vb 188 has not yet been determined 189 .ve 190 191 .seealso: PetscViewerBinaryOpen(), TSAdaptView(), MatLoad(), VecLoad() 192 @*/ 193 PetscErrorCode TSAdaptLoad(TSAdapt adapt,PetscViewer viewer) 194 { 195 PetscErrorCode ierr; 196 PetscBool isbinary; 197 char type[256]; 198 199 PetscFunctionBegin; 200 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 201 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 202 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 203 if (!isbinary) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen()"); 204 205 ierr = PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);CHKERRQ(ierr); 206 ierr = TSAdaptSetType(adapt,type);CHKERRQ(ierr); 207 if (adapt->ops->load) { 208 ierr = (*adapt->ops->load)(adapt,viewer);CHKERRQ(ierr); 209 } 210 PetscFunctionReturn(0); 211 } 212 213 PetscErrorCode TSAdaptView(TSAdapt adapt,PetscViewer viewer) 214 { 215 PetscErrorCode ierr; 216 PetscBool iascii,isbinary; 217 218 PetscFunctionBegin; 219 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 220 if (!viewer) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)adapt),&viewer);CHKERRQ(ierr);} 221 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 222 PetscCheckSameComm(adapt,1,viewer,2); 223 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 224 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 225 if (iascii) { 226 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)adapt,viewer);CHKERRQ(ierr); 227 ierr = PetscViewerASCIIPrintf(viewer," number of candidates %D\n",adapt->candidates.n);CHKERRQ(ierr); 228 ierr = PetscViewerASCIIPrintf(viewer," maximum allowed timestep %g minimum %g\n",adapt->dt_max,&adapt->dt_min);CHKERRQ(ierr); 229 if (adapt->ops->view) { 230 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 231 ierr = (*adapt->ops->view)(adapt,viewer);CHKERRQ(ierr); 232 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 233 } 234 } else if (isbinary) { 235 char type[256]; 236 237 /* need to save FILE_CLASS_ID for adapt class */ 238 ierr = PetscStrncpy(type,((PetscObject)adapt)->type_name,256);CHKERRQ(ierr); 239 ierr = PetscViewerBinaryWrite(viewer,type,256,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr); 240 } else if (adapt->ops->view) { 241 ierr = (*adapt->ops->view)(adapt,viewer);CHKERRQ(ierr); 242 } 243 PetscFunctionReturn(0); 244 } 245 246 /*@ 247 TSAdaptReset - Resets a TSAdapt context. 248 249 Collective on TS 250 251 Input Parameter: 252 . adapt - the TSAdapt context obtained from TSAdaptCreate() 253 254 Level: developer 255 256 .seealso: TSAdaptCreate(), TSAdaptDestroy() 257 @*/ 258 PetscErrorCode TSAdaptReset(TSAdapt adapt) 259 { 260 PetscErrorCode ierr; 261 262 PetscFunctionBegin; 263 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 264 if (adapt->ops->reset) {ierr = (*adapt->ops->reset)(adapt);CHKERRQ(ierr);} 265 PetscFunctionReturn(0); 266 } 267 268 PetscErrorCode TSAdaptDestroy(TSAdapt *adapt) 269 { 270 PetscErrorCode ierr; 271 272 PetscFunctionBegin; 273 if (!*adapt) PetscFunctionReturn(0); 274 PetscValidHeaderSpecific(*adapt,TSADAPT_CLASSID,1); 275 if (--((PetscObject)(*adapt))->refct > 0) {*adapt = NULL; PetscFunctionReturn(0);} 276 277 ierr = TSAdaptReset(*adapt);CHKERRQ(ierr); 278 279 if ((*adapt)->ops->destroy) {ierr = (*(*adapt)->ops->destroy)(*adapt);CHKERRQ(ierr);} 280 ierr = PetscViewerDestroy(&(*adapt)->monitor);CHKERRQ(ierr); 281 ierr = PetscHeaderDestroy(adapt);CHKERRQ(ierr); 282 PetscFunctionReturn(0); 283 } 284 285 /*@ 286 TSAdaptSetMonitor - Monitor the choices made by the adaptive controller 287 288 Collective on TSAdapt 289 290 Input Arguments: 291 + adapt - adaptive controller context 292 - flg - PETSC_TRUE to active a monitor, PETSC_FALSE to disable 293 294 Level: intermediate 295 296 .seealso: TSAdaptChoose() 297 @*/ 298 PetscErrorCode TSAdaptSetMonitor(TSAdapt adapt,PetscBool flg) 299 { 300 PetscErrorCode ierr; 301 302 PetscFunctionBegin; 303 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 304 PetscValidLogicalCollectiveBool(adapt,flg,2); 305 if (flg) { 306 if (!adapt->monitor) {ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)adapt),"stdout",&adapt->monitor);CHKERRQ(ierr);} 307 } else { 308 ierr = PetscViewerDestroy(&adapt->monitor);CHKERRQ(ierr); 309 } 310 PetscFunctionReturn(0); 311 } 312 313 /*@C 314 TSAdaptSetCheckStage - set a callback to check convergence for a stage 315 316 Logically collective on TSAdapt 317 318 Input Arguments: 319 + adapt - adaptive controller context 320 - func - stage check function 321 322 Arguments of func: 323 $ PetscErrorCode func(TSAdapt adapt,TS ts,PetscBool *accept) 324 325 + adapt - adaptive controller context 326 . ts - time stepping context 327 - accept - pending choice of whether to accept, can be modified by this routine 328 329 Level: advanced 330 331 .seealso: TSAdaptChoose() 332 @*/ 333 PetscErrorCode TSAdaptSetCheckStage(TSAdapt adapt,PetscErrorCode (*func)(TSAdapt,TS,PetscReal,Vec,PetscBool*)) 334 { 335 336 PetscFunctionBegin; 337 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 338 adapt->checkstage = func; 339 PetscFunctionReturn(0); 340 } 341 342 /*@ 343 TSAdaptSetStepLimits - Set minimum and maximum step sizes to be considered by the controller 344 345 Logically Collective 346 347 Input Arguments: 348 + adapt - time step adaptivity context, usually gotten with TSGetAdapt() 349 . hmin - minimum time step 350 - hmax - maximum time step 351 352 Options Database Keys: 353 + -ts_adapt_dt_min - minimum time step 354 - -ts_adapt_dt_max - maximum time step 355 356 Level: intermediate 357 358 .seealso: TSAdapt 359 @*/ 360 PetscErrorCode TSAdaptSetStepLimits(TSAdapt adapt,PetscReal hmin,PetscReal hmax) 361 { 362 363 PetscFunctionBegin; 364 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 365 PetscValidLogicalCollectiveReal(adapt,hmin,2); 366 PetscValidLogicalCollectiveReal(adapt,hmax,3); 367 if (hmin != PETSC_DEFAULT && hmin < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Minimum time step %g must be non negative",(double)hmin); 368 if (hmax != PETSC_DEFAULT && hmax < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Minimum time step %g must be non negative",(double)hmax); 369 if (hmin != PETSC_DEFAULT) adapt->dt_min = hmin; 370 if (hmax != PETSC_DEFAULT) adapt->dt_max = hmax; 371 #if defined(PETSC_USE_DEBUG) 372 hmin = adapt->dt_min; 373 hmax = adapt->dt_max; 374 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); 375 #endif 376 PetscFunctionReturn(0); 377 } 378 379 /* 380 TSAdaptSetFromOptions - Sets various TSAdapt parameters from user options. 381 382 Collective on TSAdapt 383 384 Input Parameter: 385 . adapt - the TSAdapt context 386 387 Options Database Keys: 388 + -ts_adapt_type <type> - basic 389 . -ts_adapt_dt_min <min> - minimum timestep to use 390 . -ts_adapt_dt_max <max> - maximum timestep to use 391 . -ts_adapt_scale_solve_failed <scale> - scale timestep by this factor if a solve fails 392 - -ts_adapt_wnormtype <2 or infinity> - type of norm for computing error estimates 393 394 Level: advanced 395 396 Notes: 397 This function is automatically called by TSSetFromOptions() 398 399 .keywords: TS, TSGetAdapt(), TSAdaptSetType(), TSAdaptSetStepLimits() 400 401 .seealso: TSGetType() 402 */ 403 PetscErrorCode TSAdaptSetFromOptions(PetscOptionItems *PetscOptionsObject,TSAdapt adapt) 404 { 405 PetscErrorCode ierr; 406 char type[256] = TSADAPTBASIC; 407 PetscBool set,flg; 408 409 PetscFunctionBegin; 410 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 411 /* This should use PetscOptionsBegin() if/when this becomes an object used outside of TS, but currently this 412 * function can only be called from inside TSSetFromOptions() */ 413 ierr = PetscOptionsHead(PetscOptionsObject,"TS Adaptivity options");CHKERRQ(ierr); 414 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); 415 if (flg || !((PetscObject)adapt)->type_name) { 416 ierr = TSAdaptSetType(adapt,type);CHKERRQ(ierr); 417 } 418 ierr = PetscOptionsReal("-ts_adapt_dt_min","Minimum time step considered","TSAdaptSetStepLimits",adapt->dt_min,&adapt->dt_min,NULL);CHKERRQ(ierr); 419 ierr = PetscOptionsReal("-ts_adapt_dt_max","Maximum time step considered","TSAdaptSetStepLimits",adapt->dt_max,&adapt->dt_max,NULL);CHKERRQ(ierr); 420 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); 421 ierr = PetscOptionsBool("-ts_adapt_monitor","Print choices made by adaptive controller","TSAdaptSetMonitor",adapt->monitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr); 422 ierr = PetscOptionsEnum("-ts_adapt_wnormtype","Type of norm computed for error estimation","",NormTypes,(PetscEnum)adapt->wnormtype,(PetscEnum*)&adapt->wnormtype,NULL);CHKERRQ(ierr); 423 if (adapt->wnormtype != NORM_2 && adapt->wnormtype != NORM_INFINITY) SETERRQ(PetscObjectComm((PetscObject)adapt),PETSC_ERR_SUP,"Only 2-norm and infinite norm supported"); 424 if (set) {ierr = TSAdaptSetMonitor(adapt,flg);CHKERRQ(ierr);} 425 if (adapt->ops->setfromoptions) {ierr = (*adapt->ops->setfromoptions)(PetscOptionsObject,adapt);CHKERRQ(ierr);} 426 ierr = PetscOptionsTail();CHKERRQ(ierr); 427 PetscFunctionReturn(0); 428 } 429 430 /*@ 431 TSAdaptCandidatesClear - clear any previously set candidate schemes 432 433 Logically Collective 434 435 Input Argument: 436 . adapt - adaptive controller 437 438 Level: developer 439 440 .seealso: TSAdapt, TSAdaptCreate(), TSAdaptCandidateAdd(), TSAdaptChoose() 441 @*/ 442 PetscErrorCode TSAdaptCandidatesClear(TSAdapt adapt) 443 { 444 PetscErrorCode ierr; 445 446 PetscFunctionBegin; 447 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 448 ierr = PetscMemzero(&adapt->candidates,sizeof(adapt->candidates));CHKERRQ(ierr); 449 PetscFunctionReturn(0); 450 } 451 452 /*@C 453 TSAdaptCandidateAdd - add a candidate scheme for the adaptive controller to select from 454 455 Logically Collective 456 457 Input Arguments: 458 + adapt - time step adaptivity context, obtained with TSGetAdapt() or TSAdaptCreate() 459 . name - name of the candidate scheme to add 460 . order - order of the candidate scheme 461 . stageorder - stage order of the candidate scheme 462 . ccfl - stability coefficient relative to explicit Euler, used for CFL constraints 463 . cost - relative measure of the amount of work required for the candidate scheme 464 - inuse - indicates that this scheme is the one currently in use, this flag can only be set for one scheme 465 466 Note: 467 This routine is not available in Fortran. 468 469 Level: developer 470 471 .seealso: TSAdaptCandidatesClear(), TSAdaptChoose() 472 @*/ 473 PetscErrorCode TSAdaptCandidateAdd(TSAdapt adapt,const char name[],PetscInt order,PetscInt stageorder,PetscReal ccfl,PetscReal cost,PetscBool inuse) 474 { 475 PetscInt c; 476 477 PetscFunctionBegin; 478 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 479 if (order < 1) SETERRQ1(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_OUTOFRANGE,"Classical order %D must be a positive integer",order); 480 if (inuse) { 481 if (adapt->candidates.inuse_set) SETERRQ(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_WRONGSTATE,"Cannot set the inuse method twice, maybe forgot to call TSAdaptCandidatesClear()"); 482 adapt->candidates.inuse_set = PETSC_TRUE; 483 } 484 /* first slot if this is the current scheme, otherwise the next available slot */ 485 c = inuse ? 0 : !adapt->candidates.inuse_set + adapt->candidates.n; 486 487 adapt->candidates.name[c] = name; 488 adapt->candidates.order[c] = order; 489 adapt->candidates.stageorder[c] = stageorder; 490 adapt->candidates.ccfl[c] = ccfl; 491 adapt->candidates.cost[c] = cost; 492 adapt->candidates.n++; 493 PetscFunctionReturn(0); 494 } 495 496 /*@C 497 TSAdaptCandidatesGet - Get the list of candidate orders of accuracy and cost 498 499 Not Collective 500 501 Input Arguments: 502 . adapt - time step adaptivity context 503 504 Output Arguments: 505 + n - number of candidate schemes, always at least 1 506 . order - the order of each candidate scheme 507 . stageorder - the stage order of each candidate scheme 508 . ccfl - the CFL coefficient of each scheme 509 - cost - the relative cost of each scheme 510 511 Level: developer 512 513 Note: 514 The current scheme is always returned in the first slot 515 516 .seealso: TSAdaptCandidatesClear(), TSAdaptCandidateAdd(), TSAdaptChoose() 517 @*/ 518 PetscErrorCode TSAdaptCandidatesGet(TSAdapt adapt,PetscInt *n,const PetscInt **order,const PetscInt **stageorder,const PetscReal **ccfl,const PetscReal **cost) 519 { 520 PetscFunctionBegin; 521 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 522 if (n) *n = adapt->candidates.n; 523 if (order) *order = adapt->candidates.order; 524 if (stageorder) *stageorder = adapt->candidates.stageorder; 525 if (ccfl) *ccfl = adapt->candidates.ccfl; 526 if (cost) *cost = adapt->candidates.cost; 527 PetscFunctionReturn(0); 528 } 529 530 /*@C 531 TSAdaptChoose - choose which method and step size to use for the next step 532 533 Logically Collective 534 535 Input Arguments: 536 + adapt - adaptive contoller 537 - h - current step size 538 539 Output Arguments: 540 + next_sc - optional, scheme to use for the next step 541 . next_h - step size to use for the next step 542 - accept - PETSC_TRUE to accept the current step, PETSC_FALSE to repeat the current step with the new step size 543 544 Note: 545 The input value of parameter accept is retained from the last time step, so it will be PETSC_FALSE if the step is 546 being retried after an initial rejection. 547 548 Level: developer 549 550 .seealso: TSAdapt, TSAdaptCandidatesClear(), TSAdaptCandidateAdd() 551 @*/ 552 PetscErrorCode TSAdaptChoose(TSAdapt adapt,TS ts,PetscReal h,PetscInt *next_sc,PetscReal *next_h,PetscBool *accept) 553 { 554 PetscErrorCode ierr; 555 PetscInt ncandidates = adapt->candidates.n; 556 PetscInt scheme = 0; 557 PetscReal wlte = -1.0; 558 PetscReal wltea = -1.0; 559 PetscReal wlter = -1.0; 560 561 PetscFunctionBegin; 562 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 563 PetscValidHeaderSpecific(ts,TS_CLASSID,2); 564 if (next_sc) PetscValidIntPointer(next_sc,4); 565 PetscValidPointer(next_h,5); 566 PetscValidIntPointer(accept,6); 567 if (next_sc) *next_sc = 0; 568 569 /* Do not mess with adaptivity while handling events*/ 570 if (ts->event && ts->event->status != TSEVENT_NONE) { 571 *next_h = h; 572 *accept = PETSC_TRUE; 573 PetscFunctionReturn(0); 574 } 575 576 ierr = (*adapt->ops->choose)(adapt,ts,h,&scheme,next_h,accept,&wlte,&wltea,&wlter);CHKERRQ(ierr); 577 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); 578 if (*next_h < 0) SETERRQ1(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_OUTOFRANGE,"Computed step size %g must be positive",(double)*next_h); 579 if (next_sc) *next_sc = scheme; 580 581 if (*accept && ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP) { 582 /* Reduce time step if it overshoots max time */ 583 if (ts->ptime + ts->time_step + *next_h >= ts->max_time) { 584 PetscReal next_dt = ts->max_time - (ts->ptime + ts->time_step); 585 if (next_dt > PETSC_SMALL) *next_h = next_dt; 586 else ts->reason = TS_CONVERGED_TIME; 587 } 588 } 589 590 if (adapt->monitor) { 591 const char *sc_name = (scheme < ncandidates) ? adapt->candidates.name[scheme] : ""; 592 ierr = PetscViewerASCIIAddTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr); 593 if (wlte < 0) { 594 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); 595 } else { 596 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); 597 } 598 ierr = PetscViewerASCIISubtractTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr); 599 } 600 PetscFunctionReturn(0); 601 } 602 603 /*@ 604 TSAdaptCheckStage - checks whether to accept a stage, (e.g. reject and change time step size if nonlinear solve fails) 605 606 Collective 607 608 Input Arguments: 609 + adapt - adaptive controller context 610 . ts - time stepper 611 . t - Current simulation time 612 - Y - Current solution vector 613 614 Output Arguments: 615 . accept - PETSC_TRUE to accept the stage, PETSC_FALSE to reject 616 617 Level: developer 618 619 .seealso: 620 @*/ 621 PetscErrorCode TSAdaptCheckStage(TSAdapt adapt,TS ts,PetscReal t,Vec Y,PetscBool *accept) 622 { 623 PetscErrorCode ierr; 624 SNESConvergedReason snesreason = SNES_CONVERGED_ITERATING; 625 626 PetscFunctionBegin; 627 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 628 PetscValidHeaderSpecific(ts,TS_CLASSID,2); 629 PetscValidIntPointer(accept,3); 630 631 if (ts->snes) {ierr = SNESGetConvergedReason(ts->snes,&snesreason);CHKERRQ(ierr);} 632 if (snesreason < 0) { 633 *accept = PETSC_FALSE; 634 if (++ts->num_snes_failures >= ts->max_snes_failures && ts->max_snes_failures > 0) { 635 ts->reason = TS_DIVERGED_NONLINEAR_SOLVE; 636 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); 637 if (adapt->monitor) { 638 ierr = PetscViewerASCIIAddTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr); 639 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); 640 ierr = PetscViewerASCIISubtractTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr); 641 } 642 } 643 } else { 644 *accept = PETSC_TRUE; 645 ierr = TSFunctionDomainError(ts,t,Y,accept);CHKERRQ(ierr); 646 if(*accept && adapt->checkstage) { 647 ierr = (*adapt->checkstage)(adapt,ts,t,Y,accept);CHKERRQ(ierr); 648 } 649 } 650 651 if(!(*accept) && !ts->reason) { 652 PetscReal dt,new_dt; 653 ierr = TSGetTimeStep(ts,&dt);CHKERRQ(ierr); 654 new_dt = dt * adapt->scale_solve_failed; 655 ierr = TSSetTimeStep(ts,new_dt);CHKERRQ(ierr); 656 adapt->timestepjustincreased += 4; 657 if (adapt->monitor) { 658 ierr = PetscViewerASCIIAddTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr); 659 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); 660 ierr = PetscViewerASCIISubtractTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr); 661 } 662 } 663 PetscFunctionReturn(0); 664 } 665 666 /*@ 667 TSAdaptCreate - create an adaptive controller context for time stepping 668 669 Collective on MPI_Comm 670 671 Input Parameter: 672 . comm - The communicator 673 674 Output Parameter: 675 . adapt - new TSAdapt object 676 677 Level: developer 678 679 Notes: 680 TSAdapt creation is handled by TS, so users should not need to call this function. 681 682 .keywords: TSAdapt, create 683 .seealso: TSGetAdapt(), TSAdaptSetType(), TSAdaptDestroy() 684 @*/ 685 PetscErrorCode TSAdaptCreate(MPI_Comm comm,TSAdapt *inadapt) 686 { 687 PetscErrorCode ierr; 688 TSAdapt adapt; 689 690 PetscFunctionBegin; 691 PetscValidPointer(inadapt,1); 692 *inadapt = NULL; 693 ierr = TSAdaptInitializePackage();CHKERRQ(ierr); 694 695 ierr = PetscHeaderCreate(adapt,TSADAPT_CLASSID,"TSAdapt","Time stepping adaptivity","TS",comm,TSAdaptDestroy,TSAdaptView);CHKERRQ(ierr); 696 697 adapt->dt_min = 1e-20; 698 adapt->dt_max = 1e50; 699 adapt->scale_solve_failed = 0.25; 700 adapt->wnormtype = NORM_2; 701 ierr = TSAdaptSetType(adapt,TSADAPTBASIC);CHKERRQ(ierr); 702 703 *inadapt = adapt; 704 PetscFunctionReturn(0); 705 } 706