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 if (adapt->ops->view) { 229 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 230 ierr = (*adapt->ops->view)(adapt,viewer);CHKERRQ(ierr); 231 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 232 } 233 } else if (isbinary) { 234 char type[256]; 235 236 /* need to save FILE_CLASS_ID for adapt class */ 237 ierr = PetscStrncpy(type,((PetscObject)adapt)->type_name,256);CHKERRQ(ierr); 238 ierr = PetscViewerBinaryWrite(viewer,type,256,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr); 239 } else if (adapt->ops->view) { 240 ierr = (*adapt->ops->view)(adapt,viewer);CHKERRQ(ierr); 241 } 242 PetscFunctionReturn(0); 243 } 244 245 /*@ 246 TSAdaptReset - Resets a TSAdapt context. 247 248 Collective on TS 249 250 Input Parameter: 251 . adapt - the TSAdapt context obtained from TSAdaptCreate() 252 253 Level: developer 254 255 .seealso: TSAdaptCreate(), TSAdaptDestroy() 256 @*/ 257 PetscErrorCode TSAdaptReset(TSAdapt adapt) 258 { 259 PetscErrorCode ierr; 260 261 PetscFunctionBegin; 262 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 263 if (adapt->ops->reset) {ierr = (*adapt->ops->reset)(adapt);CHKERRQ(ierr);} 264 PetscFunctionReturn(0); 265 } 266 267 PetscErrorCode TSAdaptDestroy(TSAdapt *adapt) 268 { 269 PetscErrorCode ierr; 270 271 PetscFunctionBegin; 272 if (!*adapt) PetscFunctionReturn(0); 273 PetscValidHeaderSpecific(*adapt,TSADAPT_CLASSID,1); 274 if (--((PetscObject)(*adapt))->refct > 0) {*adapt = NULL; PetscFunctionReturn(0);} 275 276 ierr = TSAdaptReset(*adapt);CHKERRQ(ierr); 277 278 if ((*adapt)->ops->destroy) {ierr = (*(*adapt)->ops->destroy)(*adapt);CHKERRQ(ierr);} 279 ierr = PetscViewerDestroy(&(*adapt)->monitor);CHKERRQ(ierr); 280 ierr = PetscHeaderDestroy(adapt);CHKERRQ(ierr); 281 PetscFunctionReturn(0); 282 } 283 284 /*@ 285 TSAdaptSetMonitor - Monitor the choices made by the adaptive controller 286 287 Collective on TSAdapt 288 289 Input Arguments: 290 + adapt - adaptive controller context 291 - flg - PETSC_TRUE to active a monitor, PETSC_FALSE to disable 292 293 Level: intermediate 294 295 .seealso: TSAdaptChoose() 296 @*/ 297 PetscErrorCode TSAdaptSetMonitor(TSAdapt adapt,PetscBool flg) 298 { 299 PetscErrorCode ierr; 300 301 PetscFunctionBegin; 302 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 303 PetscValidLogicalCollectiveBool(adapt,flg,2); 304 if (flg) { 305 if (!adapt->monitor) {ierr = PetscViewerASCIIOpen(PetscObjectComm((PetscObject)adapt),"stdout",&adapt->monitor);CHKERRQ(ierr);} 306 } else { 307 ierr = PetscViewerDestroy(&adapt->monitor);CHKERRQ(ierr); 308 } 309 PetscFunctionReturn(0); 310 } 311 312 /*@C 313 TSAdaptSetCheckStage - set a callback to check convergence for a stage 314 315 Logically collective on TSAdapt 316 317 Input Arguments: 318 + adapt - adaptive controller context 319 - func - stage check function 320 321 Arguments of func: 322 $ PetscErrorCode func(TSAdapt adapt,TS ts,PetscBool *accept) 323 324 + adapt - adaptive controller context 325 . ts - time stepping context 326 - accept - pending choice of whether to accept, can be modified by this routine 327 328 Level: advanced 329 330 .seealso: TSAdaptChoose() 331 @*/ 332 PetscErrorCode TSAdaptSetCheckStage(TSAdapt adapt,PetscErrorCode (*func)(TSAdapt,TS,PetscReal,Vec,PetscBool*)) 333 { 334 335 PetscFunctionBegin; 336 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 337 adapt->checkstage = func; 338 PetscFunctionReturn(0); 339 } 340 341 /*@ 342 TSAdaptSetStepLimits - Set minimum and maximum step sizes to be considered by the controller 343 344 Logically Collective 345 346 Input Arguments: 347 + adapt - time step adaptivity context, usually gotten with TSGetAdapt() 348 . hmin - minimum time step 349 - hmax - maximum time step 350 351 Options Database Keys: 352 + -ts_adapt_dt_min - minimum time step 353 - -ts_adapt_dt_max - maximum time step 354 355 Level: intermediate 356 357 .seealso: TSAdapt 358 @*/ 359 PetscErrorCode TSAdaptSetStepLimits(TSAdapt adapt,PetscReal hmin,PetscReal hmax) 360 { 361 362 PetscFunctionBegin; 363 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 364 PetscValidLogicalCollectiveReal(adapt,hmin,2); 365 PetscValidLogicalCollectiveReal(adapt,hmax,3); 366 if (hmin != PETSC_DEFAULT && hmin < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Minimum time step %g must be non negative",(double)hmin); 367 if (hmax != PETSC_DEFAULT && hmax < 0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Minimum time step %g must be non negative",(double)hmax); 368 if (hmin != PETSC_DEFAULT) adapt->dt_min = hmin; 369 if (hmax != PETSC_DEFAULT) adapt->dt_max = hmax; 370 #if defined(PETSC_USE_DEBUG) 371 hmin = adapt->dt_min; 372 hmax = adapt->dt_max; 373 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); 374 #endif 375 PetscFunctionReturn(0); 376 } 377 378 /* 379 TSAdaptSetFromOptions - Sets various TSAdapt parameters from user options. 380 381 Collective on TSAdapt 382 383 Input Parameter: 384 . adapt - the TSAdapt context 385 386 Options Database Keys: 387 + -ts_adapt_type <type> - basic 388 . -ts_adapt_dt_min <min> - minimum timestep to use 389 . -ts_adapt_dt_max <max> - maximum timestep to use 390 . -ts_adapt_scale_solve_failed <scale> - scale timestep by this factor if a solve fails 391 - -ts_adapt_wnormtype <2 or infinity> - type of norm for computing error estimates 392 393 Level: advanced 394 395 Notes: 396 This function is automatically called by TSSetFromOptions() 397 398 .keywords: TS, TSGetAdapt(), TSAdaptSetType(), TSAdaptSetStepLimits() 399 400 .seealso: TSGetType() 401 */ 402 PetscErrorCode TSAdaptSetFromOptions(PetscOptionItems *PetscOptionsObject,TSAdapt adapt) 403 { 404 PetscErrorCode ierr; 405 char type[256] = TSADAPTBASIC; 406 PetscBool set,flg; 407 408 PetscFunctionBegin; 409 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 410 /* This should use PetscOptionsBegin() if/when this becomes an object used outside of TS, but currently this 411 * function can only be called from inside TSSetFromOptions() */ 412 ierr = PetscOptionsHead(PetscOptionsObject,"TS Adaptivity options");CHKERRQ(ierr); 413 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); 414 if (flg || !((PetscObject)adapt)->type_name) { 415 ierr = TSAdaptSetType(adapt,type);CHKERRQ(ierr); 416 } 417 ierr = PetscOptionsReal("-ts_adapt_dt_min","Minimum time step considered","TSAdaptSetStepLimits",adapt->dt_min,&adapt->dt_min,NULL);CHKERRQ(ierr); 418 ierr = PetscOptionsReal("-ts_adapt_dt_max","Maximum time step considered","TSAdaptSetStepLimits",adapt->dt_max,&adapt->dt_max,NULL);CHKERRQ(ierr); 419 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); 420 ierr = PetscOptionsBool("-ts_adapt_monitor","Print choices made by adaptive controller","TSAdaptSetMonitor",adapt->monitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr); 421 ierr = PetscOptionsEnum("-ts_adapt_wnormtype","Type of norm computed for error estimation","",NormTypes,(PetscEnum)adapt->wnormtype,(PetscEnum*)&adapt->wnormtype,NULL);CHKERRQ(ierr); 422 if (adapt->wnormtype != NORM_2 && adapt->wnormtype != NORM_INFINITY) SETERRQ(PetscObjectComm((PetscObject)adapt),PETSC_ERR_SUP,"Only 2-norm and infinite norm supported"); 423 if (set) {ierr = TSAdaptSetMonitor(adapt,flg);CHKERRQ(ierr);} 424 if (adapt->ops->setfromoptions) {ierr = (*adapt->ops->setfromoptions)(PetscOptionsObject,adapt);CHKERRQ(ierr);} 425 ierr = PetscOptionsTail();CHKERRQ(ierr); 426 PetscFunctionReturn(0); 427 } 428 429 /*@ 430 TSAdaptCandidatesClear - clear any previously set candidate schemes 431 432 Logically Collective 433 434 Input Argument: 435 . adapt - adaptive controller 436 437 Level: developer 438 439 .seealso: TSAdapt, TSAdaptCreate(), TSAdaptCandidateAdd(), TSAdaptChoose() 440 @*/ 441 PetscErrorCode TSAdaptCandidatesClear(TSAdapt adapt) 442 { 443 PetscErrorCode ierr; 444 445 PetscFunctionBegin; 446 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 447 ierr = PetscMemzero(&adapt->candidates,sizeof(adapt->candidates));CHKERRQ(ierr); 448 PetscFunctionReturn(0); 449 } 450 451 /*@C 452 TSAdaptCandidateAdd - add a candidate scheme for the adaptive controller to select from 453 454 Logically Collective 455 456 Input Arguments: 457 + adapt - time step adaptivity context, obtained with TSGetAdapt() or TSAdaptCreate() 458 . name - name of the candidate scheme to add 459 . order - order of the candidate scheme 460 . stageorder - stage order of the candidate scheme 461 . ccfl - stability coefficient relative to explicit Euler, used for CFL constraints 462 . cost - relative measure of the amount of work required for the candidate scheme 463 - inuse - indicates that this scheme is the one currently in use, this flag can only be set for one scheme 464 465 Note: 466 This routine is not available in Fortran. 467 468 Level: developer 469 470 .seealso: TSAdaptCandidatesClear(), TSAdaptChoose() 471 @*/ 472 PetscErrorCode TSAdaptCandidateAdd(TSAdapt adapt,const char name[],PetscInt order,PetscInt stageorder,PetscReal ccfl,PetscReal cost,PetscBool inuse) 473 { 474 PetscInt c; 475 476 PetscFunctionBegin; 477 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 478 if (order < 1) SETERRQ1(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_OUTOFRANGE,"Classical order %D must be a positive integer",order); 479 if (inuse) { 480 if (adapt->candidates.inuse_set) SETERRQ(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_WRONGSTATE,"Cannot set the inuse method twice, maybe forgot to call TSAdaptCandidatesClear()"); 481 adapt->candidates.inuse_set = PETSC_TRUE; 482 } 483 /* first slot if this is the current scheme, otherwise the next available slot */ 484 c = inuse ? 0 : !adapt->candidates.inuse_set + adapt->candidates.n; 485 486 adapt->candidates.name[c] = name; 487 adapt->candidates.order[c] = order; 488 adapt->candidates.stageorder[c] = stageorder; 489 adapt->candidates.ccfl[c] = ccfl; 490 adapt->candidates.cost[c] = cost; 491 adapt->candidates.n++; 492 PetscFunctionReturn(0); 493 } 494 495 /*@C 496 TSAdaptCandidatesGet - Get the list of candidate orders of accuracy and cost 497 498 Not Collective 499 500 Input Arguments: 501 . adapt - time step adaptivity context 502 503 Output Arguments: 504 + n - number of candidate schemes, always at least 1 505 . order - the order of each candidate scheme 506 . stageorder - the stage order of each candidate scheme 507 . ccfl - the CFL coefficient of each scheme 508 - cost - the relative cost of each scheme 509 510 Level: developer 511 512 Note: 513 The current scheme is always returned in the first slot 514 515 .seealso: TSAdaptCandidatesClear(), TSAdaptCandidateAdd(), TSAdaptChoose() 516 @*/ 517 PetscErrorCode TSAdaptCandidatesGet(TSAdapt adapt,PetscInt *n,const PetscInt **order,const PetscInt **stageorder,const PetscReal **ccfl,const PetscReal **cost) 518 { 519 PetscFunctionBegin; 520 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 521 if (n) *n = adapt->candidates.n; 522 if (order) *order = adapt->candidates.order; 523 if (stageorder) *stageorder = adapt->candidates.stageorder; 524 if (ccfl) *ccfl = adapt->candidates.ccfl; 525 if (cost) *cost = adapt->candidates.cost; 526 PetscFunctionReturn(0); 527 } 528 529 /*@C 530 TSAdaptChoose - choose which method and step size to use for the next step 531 532 Logically Collective 533 534 Input Arguments: 535 + adapt - adaptive contoller 536 - h - current step size 537 538 Output Arguments: 539 + next_sc - optional, scheme to use for the next step 540 . next_h - step size to use for the next step 541 - accept - PETSC_TRUE to accept the current step, PETSC_FALSE to repeat the current step with the new step size 542 543 Note: 544 The input value of parameter accept is retained from the last time step, so it will be PETSC_FALSE if the step is 545 being retried after an initial rejection. 546 547 Level: developer 548 549 .seealso: TSAdapt, TSAdaptCandidatesClear(), TSAdaptCandidateAdd() 550 @*/ 551 PetscErrorCode TSAdaptChoose(TSAdapt adapt,TS ts,PetscReal h,PetscInt *next_sc,PetscReal *next_h,PetscBool *accept) 552 { 553 PetscErrorCode ierr; 554 PetscInt ncandidates = adapt->candidates.n; 555 PetscInt scheme = 0; 556 PetscReal wlte = -1.0; 557 PetscReal wltea = -1.0; 558 PetscReal wlter = -1.0; 559 560 PetscFunctionBegin; 561 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 562 PetscValidHeaderSpecific(ts,TS_CLASSID,2); 563 if (next_sc) PetscValidIntPointer(next_sc,4); 564 PetscValidPointer(next_h,5); 565 PetscValidIntPointer(accept,6); 566 if (next_sc) *next_sc = 0; 567 568 /* Do not mess with adaptivity while handling events*/ 569 if (ts->event && ts->event->status != TSEVENT_NONE) { 570 *next_h = h; 571 *accept = PETSC_TRUE; 572 PetscFunctionReturn(0); 573 } 574 575 ierr = (*adapt->ops->choose)(adapt,ts,h,&scheme,next_h,accept,&wlte,&wltea,&wlter);CHKERRQ(ierr); 576 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); 577 if (*next_h < 0) SETERRQ1(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_OUTOFRANGE,"Computed step size %g must be positive",(double)*next_h); 578 if (next_sc) *next_sc = scheme; 579 580 if (*accept && ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP) { 581 /* Reduce time step if it overshoots max time */ 582 if (ts->ptime + ts->time_step + *next_h >= ts->max_time) { 583 PetscReal next_dt = ts->max_time - (ts->ptime + ts->time_step); 584 if (next_dt > PETSC_SMALL) *next_h = next_dt; 585 else ts->reason = TS_CONVERGED_TIME; 586 } 587 } 588 589 if (adapt->monitor) { 590 const char *sc_name = (scheme < ncandidates) ? adapt->candidates.name[scheme] : ""; 591 ierr = PetscViewerASCIIAddTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr); 592 if (wlte < 0) { 593 ierr = PetscViewerASCIIPrintf(adapt->monitor," TSAdapt '%s': step %3D %s t=%-11g+%10.3e family='%s' scheme=%D:'%s' dt=%-10.3e\n",((PetscObject)adapt)->type_name,ts->steps,*accept ? "accepted" : "rejected",(double)ts->ptime,(double)h,((PetscObject)ts)->type_name,scheme,sc_name,(double)*next_h);CHKERRQ(ierr); 594 } else { 595 ierr = PetscViewerASCIIPrintf(adapt->monitor," TSAdapt '%s': step %3D %s t=%-11g+%10.3e wlte=%5.3g family='%s' scheme=%D:'%s' dt=%-10.3e\n",((PetscObject)adapt)->type_name,ts->steps,*accept ? "accepted" : "rejected",(double)ts->ptime,(double)h,(double)wlte,((PetscObject)ts)->type_name,scheme,sc_name,(double)*next_h);CHKERRQ(ierr); 596 ierr = PetscViewerASCIIPrintf(adapt->monitor," wlte=%5.3g wltea=%5.3g wlter=%5.3g \n",(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 if (adapt->monitor) { 657 ierr = PetscViewerASCIIAddTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr); 658 ierr = PetscViewerASCIIPrintf(adapt->monitor," TSAdapt '%s': step %3D stage rejected t=%-11g+%10.3e retrying with dt=%-10.3e\n",((PetscObject)adapt)->type_name,ts->steps,(double)ts->ptime,(double)dt,(double)new_dt);CHKERRQ(ierr); 659 ierr = PetscViewerASCIISubtractTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr); 660 } 661 } 662 PetscFunctionReturn(0); 663 } 664 665 /*@ 666 TSAdaptCreate - create an adaptive controller context for time stepping 667 668 Collective on MPI_Comm 669 670 Input Parameter: 671 . comm - The communicator 672 673 Output Parameter: 674 . adapt - new TSAdapt object 675 676 Level: developer 677 678 Notes: 679 TSAdapt creation is handled by TS, so users should not need to call this function. 680 681 .keywords: TSAdapt, create 682 .seealso: TSGetAdapt(), TSAdaptSetType(), TSAdaptDestroy() 683 @*/ 684 PetscErrorCode TSAdaptCreate(MPI_Comm comm,TSAdapt *inadapt) 685 { 686 PetscErrorCode ierr; 687 TSAdapt adapt; 688 689 PetscFunctionBegin; 690 PetscValidPointer(inadapt,1); 691 *inadapt = NULL; 692 ierr = TSAdaptInitializePackage();CHKERRQ(ierr); 693 694 ierr = PetscHeaderCreate(adapt,TSADAPT_CLASSID,"TSAdapt","Time stepping adaptivity","TS",comm,TSAdaptDestroy,TSAdaptView);CHKERRQ(ierr); 695 696 adapt->dt_min = 1e-20; 697 adapt->dt_max = 1e50; 698 adapt->scale_solve_failed = 0.25; 699 adapt->wnormtype = NORM_2; 700 ierr = TSAdaptSetType(adapt,TSADAPTBASIC);CHKERRQ(ierr); 701 702 *inadapt = adapt; 703 PetscFunctionReturn(0); 704 } 705