1 2 #include <petsc/private/tsimpl.h> /*I "petscts.h" I*/ 3 4 static PetscFunctionList TSAdaptList; 5 static PetscBool TSAdaptPackageInitialized; 6 static PetscBool TSAdaptRegisterAllCalled; 7 static PetscClassId TSADAPT_CLASSID; 8 9 PETSC_EXTERN PetscErrorCode TSAdaptCreate_Basic(TSAdapt); 10 PETSC_EXTERN PetscErrorCode TSAdaptCreate_None(TSAdapt); 11 PETSC_EXTERN PetscErrorCode TSAdaptCreate_CFL(TSAdapt); 12 13 #undef __FUNCT__ 14 #define __FUNCT__ "TSAdaptRegister" 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 #undef __FUNCT__ 53 #define __FUNCT__ "TSAdaptRegisterAll" 54 /*@C 55 TSAdaptRegisterAll - Registers all of the adaptivity schemes in TSAdapt 56 57 Not Collective 58 59 Level: advanced 60 61 .keywords: TSAdapt, register, all 62 63 .seealso: TSAdaptRegisterDestroy() 64 @*/ 65 PetscErrorCode TSAdaptRegisterAll(void) 66 { 67 PetscErrorCode ierr; 68 69 PetscFunctionBegin; 70 if (TSAdaptRegisterAllCalled) PetscFunctionReturn(0); 71 TSAdaptRegisterAllCalled = PETSC_TRUE; 72 ierr = TSAdaptRegister(TSADAPTBASIC,TSAdaptCreate_Basic);CHKERRQ(ierr); 73 ierr = TSAdaptRegister(TSADAPTNONE, TSAdaptCreate_None);CHKERRQ(ierr); 74 ierr = TSAdaptRegister(TSADAPTCFL, TSAdaptCreate_CFL);CHKERRQ(ierr); 75 PetscFunctionReturn(0); 76 } 77 78 #undef __FUNCT__ 79 #define __FUNCT__ "TSAdaptFinalizePackage" 80 /*@C 81 TSFinalizePackage - This function destroys everything in the TS package. It is 82 called from PetscFinalize(). 83 84 Level: developer 85 86 .keywords: Petsc, destroy, package 87 .seealso: PetscFinalize() 88 @*/ 89 PetscErrorCode TSAdaptFinalizePackage(void) 90 { 91 PetscErrorCode ierr; 92 93 PetscFunctionBegin; 94 ierr = PetscFunctionListDestroy(&TSAdaptList);CHKERRQ(ierr); 95 TSAdaptPackageInitialized = PETSC_FALSE; 96 TSAdaptRegisterAllCalled = PETSC_FALSE; 97 PetscFunctionReturn(0); 98 } 99 100 #undef __FUNCT__ 101 #define __FUNCT__ "TSAdaptInitializePackage" 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 TSCreate_GL() 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 #undef __FUNCT__ 126 #define __FUNCT__ "TSAdaptSetType" 127 PetscErrorCode TSAdaptSetType(TSAdapt adapt,TSAdaptType type) 128 { 129 PetscBool match; 130 PetscErrorCode ierr,(*r)(TSAdapt); 131 132 PetscFunctionBegin; 133 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 134 ierr = PetscObjectTypeCompare((PetscObject)adapt,type,&match);CHKERRQ(ierr); 135 if (match) PetscFunctionReturn(0); 136 ierr = PetscFunctionListFind(TSAdaptList,type,&r);CHKERRQ(ierr); 137 if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown TSAdapt type \"%s\" given",type); 138 if (adapt->ops->destroy) {ierr = (*adapt->ops->destroy)(adapt);CHKERRQ(ierr);} 139 ierr = PetscMemzero(adapt->ops,sizeof(struct _TSAdaptOps));CHKERRQ(ierr); 140 ierr = PetscObjectChangeTypeName((PetscObject)adapt,type);CHKERRQ(ierr); 141 ierr = (*r)(adapt);CHKERRQ(ierr); 142 PetscFunctionReturn(0); 143 } 144 145 #undef __FUNCT__ 146 #define __FUNCT__ "TSAdaptSetOptionsPrefix" 147 PetscErrorCode TSAdaptSetOptionsPrefix(TSAdapt adapt,const char prefix[]) 148 { 149 PetscErrorCode ierr; 150 151 PetscFunctionBegin; 152 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 153 ierr = PetscObjectSetOptionsPrefix((PetscObject)adapt,prefix);CHKERRQ(ierr); 154 PetscFunctionReturn(0); 155 } 156 157 #undef __FUNCT__ 158 #define __FUNCT__ "TSAdaptLoad" 159 /*@C 160 TSAdaptLoad - Loads a TSAdapt that has been stored in binary with TSAdaptView(). 161 162 Collective on PetscViewer 163 164 Input Parameters: 165 + newdm - the newly loaded TSAdapt, this needs to have been created with TSAdaptCreate() or 166 some related function before a call to TSAdaptLoad(). 167 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() or 168 HDF5 file viewer, obtained from PetscViewerHDF5Open() 169 170 Level: intermediate 171 172 Notes: 173 The type is determined by the data in the file, any type set into the TSAdapt before this call is ignored. 174 175 Notes for advanced users: 176 Most users should not need to know the details of the binary storage 177 format, since TSAdaptLoad() and TSAdaptView() completely hide these details. 178 But for anyone who's interested, the standard binary matrix storage 179 format is 180 .vb 181 has not yet been determined 182 .ve 183 184 .seealso: PetscViewerBinaryOpen(), TSAdaptView(), MatLoad(), VecLoad() 185 @*/ 186 PetscErrorCode TSAdaptLoad(TSAdapt adapt,PetscViewer viewer) 187 { 188 PetscErrorCode ierr; 189 PetscBool isbinary; 190 char type[256]; 191 192 PetscFunctionBegin; 193 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 194 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 195 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 196 if (!isbinary) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen()"); 197 198 ierr = PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);CHKERRQ(ierr); 199 ierr = TSAdaptSetType(adapt, type);CHKERRQ(ierr); 200 if (adapt->ops->load) { 201 ierr = (*adapt->ops->load)(adapt,viewer);CHKERRQ(ierr); 202 } 203 PetscFunctionReturn(0); 204 } 205 206 #undef __FUNCT__ 207 #define __FUNCT__ "TSAdaptView" 208 PetscErrorCode TSAdaptView(TSAdapt adapt,PetscViewer viewer) 209 { 210 PetscErrorCode ierr; 211 PetscBool iascii,isbinary; 212 213 PetscFunctionBegin; 214 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 215 if (!viewer) {ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)adapt),&viewer);CHKERRQ(ierr);} 216 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 217 PetscCheckSameComm(adapt,1,viewer,2); 218 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 219 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 220 if (iascii) { 221 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)adapt,viewer);CHKERRQ(ierr); 222 ierr = PetscViewerASCIIPrintf(viewer," number of candidates %D\n",adapt->candidates.n);CHKERRQ(ierr); 223 if (adapt->ops->view) { 224 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 225 ierr = (*adapt->ops->view)(adapt,viewer);CHKERRQ(ierr); 226 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 227 } 228 } else if (isbinary) { 229 char type[256]; 230 231 /* need to save FILE_CLASS_ID for adapt class */ 232 ierr = PetscStrncpy(type,((PetscObject)adapt)->type_name,256);CHKERRQ(ierr); 233 ierr = PetscViewerBinaryWrite(viewer,type,256,PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr); 234 } else if (adapt->ops->view) { 235 ierr = (*adapt->ops->view)(adapt,viewer);CHKERRQ(ierr); 236 } 237 PetscFunctionReturn(0); 238 } 239 240 #undef __FUNCT__ 241 #define __FUNCT__ "TSAdaptReset" 242 /*@ 243 TSAdaptReset - Resets a TSAdapt context. 244 245 Collective on TS 246 247 Input Parameter: 248 . adapt - the TSAdapt context obtained from TSAdaptCreate() 249 250 Level: developer 251 252 .seealso: TSAdaptCreate(), TSAdaptDestroy() 253 @*/ 254 PetscErrorCode TSAdaptReset(TSAdapt adapt) 255 { 256 PetscErrorCode ierr; 257 258 PetscFunctionBegin; 259 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 260 if (adapt->ops->reset) {ierr = (*adapt->ops->reset)(adapt);CHKERRQ(ierr);} 261 PetscFunctionReturn(0); 262 } 263 264 #undef __FUNCT__ 265 #define __FUNCT__ "TSAdaptDestroy" 266 PetscErrorCode TSAdaptDestroy(TSAdapt *adapt) 267 { 268 PetscErrorCode ierr; 269 270 PetscFunctionBegin; 271 if (!*adapt) PetscFunctionReturn(0); 272 PetscValidHeaderSpecific(*adapt,TSADAPT_CLASSID,1); 273 if (--((PetscObject)(*adapt))->refct > 0) {*adapt = NULL; PetscFunctionReturn(0);} 274 275 ierr = TSAdaptReset(*adapt);CHKERRQ(ierr); 276 277 if ((*adapt)->ops->destroy) {ierr = (*(*adapt)->ops->destroy)(*adapt);CHKERRQ(ierr);} 278 ierr = PetscViewerDestroy(&(*adapt)->monitor);CHKERRQ(ierr); 279 ierr = PetscHeaderDestroy(adapt);CHKERRQ(ierr); 280 PetscFunctionReturn(0); 281 } 282 283 #undef __FUNCT__ 284 #define __FUNCT__ "TSAdaptSetMonitor" 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 #undef __FUNCT__ 314 #define __FUNCT__ "TSAdaptSetCheckStage" 315 /*@C 316 TSAdaptSetCheckStage - set a callback to check convergence for a stage 317 318 Logically collective on TSAdapt 319 320 Input Arguments: 321 + adapt - adaptive controller context 322 - func - stage check function 323 324 Arguments of func: 325 $ PetscErrorCode func(TSAdapt adapt,TS ts,PetscBool *accept) 326 327 + adapt - adaptive controller context 328 . ts - time stepping context 329 - accept - pending choice of whether to accept, can be modified by this routine 330 331 Level: advanced 332 333 .seealso: TSAdaptChoose() 334 @*/ 335 PetscErrorCode TSAdaptSetCheckStage(TSAdapt adapt,PetscErrorCode (*func)(TSAdapt,TS,PetscBool*)) 336 { 337 338 PetscFunctionBegin; 339 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 340 adapt->checkstage = func; 341 PetscFunctionReturn(0); 342 } 343 344 #undef __FUNCT__ 345 #define __FUNCT__ "TSAdaptSetStepLimits" 346 /*@ 347 TSAdaptSetStepLimits - Set minimum and maximum step sizes to be considered by the controller 348 349 Logically Collective 350 351 Input Arguments: 352 + adapt - time step adaptivity context, usually gotten with TSGetAdapt() 353 . hmin - minimum time step 354 - hmax - maximum time step 355 356 Options Database Keys: 357 + -ts_adapt_dt_min - minimum time step 358 - -ts_adapt_dt_max - maximum time step 359 360 Level: intermediate 361 362 .seealso: TSAdapt 363 @*/ 364 PetscErrorCode TSAdaptSetStepLimits(TSAdapt adapt,PetscReal hmin,PetscReal hmax) 365 { 366 367 PetscFunctionBegin; 368 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 369 if (hmin != PETSC_DECIDE) adapt->dt_min = hmin; 370 if (hmax != PETSC_DECIDE) adapt->dt_max = hmax; 371 PetscFunctionReturn(0); 372 } 373 374 #undef __FUNCT__ 375 #define __FUNCT__ "TSAdaptSetFromOptions" 376 /* 377 TSAdaptSetFromOptions - Sets various TSAdapt parameters from user options. 378 379 Collective on TSAdapt 380 381 Input Parameter: 382 . adapt - the TSAdapt context 383 384 Options Database Keys: 385 . -ts_adapt_type <type> - basic 386 387 Level: advanced 388 389 Notes: 390 This function is automatically called by TSSetFromOptions() 391 392 .keywords: TS, TSGetAdapt(), TSAdaptSetType() 393 394 .seealso: TSGetType() 395 */ 396 PetscErrorCode TSAdaptSetFromOptions(PetscOptions *PetscOptionsObject,TSAdapt adapt) 397 { 398 PetscErrorCode ierr; 399 char type[256] = TSADAPTBASIC; 400 PetscBool set,flg; 401 402 PetscFunctionBegin; 403 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 404 /* This should use PetscOptionsBegin() if/when this becomes an object used outside of TS, but currently this 405 * function can only be called from inside TSSetFromOptions_GL() */ 406 ierr = PetscOptionsHead(PetscOptionsObject,"TS Adaptivity options");CHKERRQ(ierr); 407 ierr = PetscOptionsFList("-ts_adapt_type","Algorithm to use for adaptivity","TSAdaptSetType",TSAdaptList, 408 ((PetscObject)adapt)->type_name ? ((PetscObject)adapt)->type_name : type,type,sizeof(type),&flg);CHKERRQ(ierr); 409 if (flg || !((PetscObject)adapt)->type_name) { 410 ierr = TSAdaptSetType(adapt,type);CHKERRQ(ierr); 411 } 412 ierr = PetscOptionsReal("-ts_adapt_dt_min","Minimum time step considered","TSAdaptSetStepLimits",adapt->dt_min,&adapt->dt_min,NULL);CHKERRQ(ierr); 413 ierr = PetscOptionsReal("-ts_adapt_dt_max","Maximum time step considered","TSAdaptSetStepLimits",adapt->dt_max,&adapt->dt_max,NULL);CHKERRQ(ierr); 414 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); 415 ierr = PetscOptionsBool("-ts_adapt_monitor","Print choices made by adaptive controller","TSAdaptSetMonitor",adapt->monitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr); 416 ierr = PetscOptionsEnum("-ts_adapt_wnormtype","Type of norm computed for error estimation","",NormTypes,(PetscEnum)adapt->wnormtype,(PetscEnum*)&adapt->wnormtype,NULL);CHKERRQ(ierr); 417 if (adapt->wnormtype != NORM_2 && adapt->wnormtype != NORM_INFINITY) SETERRQ(PetscObjectComm((PetscObject)adapt),PETSC_ERR_SUP,"Only 2-norm and infinite norm supported"); 418 if (set) {ierr = TSAdaptSetMonitor(adapt,flg);CHKERRQ(ierr);} 419 if (adapt->ops->setfromoptions) {ierr = (*adapt->ops->setfromoptions)(PetscOptionsObject,adapt);CHKERRQ(ierr);} 420 ierr = PetscOptionsTail();CHKERRQ(ierr); 421 PetscFunctionReturn(0); 422 } 423 424 #undef __FUNCT__ 425 #define __FUNCT__ "TSAdaptCandidatesClear" 426 /*@ 427 TSAdaptCandidatesClear - clear any previously set candidate schemes 428 429 Logically Collective 430 431 Input Argument: 432 . adapt - adaptive controller 433 434 Level: developer 435 436 .seealso: TSAdapt, TSAdaptCreate(), TSAdaptCandidateAdd(), TSAdaptChoose() 437 @*/ 438 PetscErrorCode TSAdaptCandidatesClear(TSAdapt adapt) 439 { 440 PetscErrorCode ierr; 441 442 PetscFunctionBegin; 443 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 444 ierr = PetscMemzero(&adapt->candidates,sizeof(adapt->candidates));CHKERRQ(ierr); 445 PetscFunctionReturn(0); 446 } 447 448 #undef __FUNCT__ 449 #define __FUNCT__ "TSAdaptCandidateAdd" 450 /*@C 451 TSAdaptCandidateAdd - add a candidate scheme for the adaptive controller to select from 452 453 Logically Collective 454 455 Input Arguments: 456 + adapt - time step adaptivity context, obtained with TSGetAdapt() or TSAdaptCreate() 457 . name - name of the candidate scheme to add 458 . order - order of the candidate scheme 459 . stageorder - stage order of the candidate scheme 460 . ccfl - stability coefficient relative to explicit Euler, used for CFL constraints 461 . cost - relative measure of the amount of work required for the candidate scheme 462 - inuse - indicates that this scheme is the one currently in use, this flag can only be set for one scheme 463 464 Note: 465 This routine is not available in Fortran. 466 467 Level: developer 468 469 .seealso: TSAdaptCandidatesClear(), TSAdaptChoose() 470 @*/ 471 PetscErrorCode TSAdaptCandidateAdd(TSAdapt adapt,const char name[],PetscInt order,PetscInt stageorder,PetscReal ccfl,PetscReal cost,PetscBool inuse) 472 { 473 PetscInt c; 474 475 PetscFunctionBegin; 476 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 477 if (order < 1) SETERRQ1(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_OUTOFRANGE,"Classical order %D must be a positive integer",order); 478 if (inuse) { 479 if (adapt->candidates.inuse_set) SETERRQ(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_WRONGSTATE,"Cannot set the inuse method twice, maybe forgot to call TSAdaptCandidatesClear()"); 480 adapt->candidates.inuse_set = PETSC_TRUE; 481 } 482 /* first slot if this is the current scheme, otherwise the next available slot */ 483 c = inuse ? 0 : !adapt->candidates.inuse_set + adapt->candidates.n; 484 485 adapt->candidates.name[c] = name; 486 adapt->candidates.order[c] = order; 487 adapt->candidates.stageorder[c] = stageorder; 488 adapt->candidates.ccfl[c] = ccfl; 489 adapt->candidates.cost[c] = cost; 490 adapt->candidates.n++; 491 PetscFunctionReturn(0); 492 } 493 494 #undef __FUNCT__ 495 #define __FUNCT__ "TSAdaptCandidatesGet" 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 #undef __FUNCT__ 531 #define __FUNCT__ "TSAdaptChoose" 532 /*@C 533 TSAdaptChoose - choose which method and step size to use for the next step 534 535 Logically Collective 536 537 Input Arguments: 538 + adapt - adaptive contoller 539 - h - current step size 540 541 Output Arguments: 542 + next_sc - scheme to use for the next step 543 . next_h - step size to use for the next step 544 - accept - PETSC_TRUE to accept the current step, PETSC_FALSE to repeat the current step with the new step size 545 546 Note: 547 The input value of parameter accept is retained from the last time step, so it will be PETSC_FALSE if the step is 548 being retried after an initial rejection. 549 550 Level: developer 551 552 .seealso: TSAdapt, TSAdaptCandidatesClear(), TSAdaptCandidateAdd() 553 @*/ 554 PetscErrorCode TSAdaptChoose(TSAdapt adapt,TS ts,PetscReal h,PetscInt *next_sc,PetscReal *next_h,PetscBool *accept) 555 { 556 PetscErrorCode ierr; 557 PetscReal wlte = -1.0; 558 559 PetscFunctionBegin; 560 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 561 PetscValidHeaderSpecific(ts,TS_CLASSID,2); 562 PetscValidIntPointer(next_sc,4); 563 PetscValidPointer(next_h,5); 564 PetscValidIntPointer(accept,6); 565 if (adapt->candidates.n < 1) SETERRQ1(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_WRONGSTATE,"%D candidates have been registered",adapt->candidates.n); 566 if (!adapt->candidates.inuse_set) SETERRQ1(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_WRONGSTATE,"The current in-use scheme is not among the %D candidates",adapt->candidates.n); 567 ierr = (*adapt->ops->choose)(adapt,ts,h,next_sc,next_h,accept,&wlte);CHKERRQ(ierr); 568 if (*accept && ts->exact_final_time == TS_EXACTFINALTIME_MATCHSTEP) { 569 /* Reduce time step if it overshoots max time */ 570 PetscReal max_time = ts->max_time; 571 PetscReal next_dt = 0.0; 572 if (ts->ptime + ts->time_step + *next_h >= max_time) { 573 next_dt = max_time - (ts->ptime + ts->time_step); 574 if (next_dt > PETSC_SMALL) *next_h = next_dt; 575 else ts->reason = TS_CONVERGED_TIME; 576 } 577 } 578 if (*next_sc < 0 || adapt->candidates.n <= *next_sc) SETERRQ2(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_OUTOFRANGE,"Chosen scheme %D not in valid range 0..%D",*next_sc,adapt->candidates.n-1); 579 if (!(*next_h > 0.)) SETERRQ1(PetscObjectComm((PetscObject)adapt),PETSC_ERR_ARG_OUTOFRANGE,"Computed step size %g must be positive",(double)*next_h); 580 581 if (adapt->monitor) { 582 ierr = PetscViewerASCIIAddTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr); 583 if (wlte < 0) { 584 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,*next_sc,adapt->candidates.name[*next_sc],(double)*next_h);CHKERRQ(ierr); 585 } else { 586 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,*next_sc,adapt->candidates.name[*next_sc],(double)*next_h);CHKERRQ(ierr); 587 } 588 ierr = PetscViewerASCIISubtractTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr); 589 } 590 PetscFunctionReturn(0); 591 } 592 593 #undef __FUNCT__ 594 #define __FUNCT__ "TSAdaptCheckStage" 595 /*@ 596 TSAdaptCheckStage - checks whether to accept a stage, (e.g. reject and change time step size if nonlinear solve fails) 597 598 Collective 599 600 Input Arguments: 601 + adapt - adaptive controller context 602 - ts - time stepper 603 604 Output Arguments: 605 . accept - PETSC_TRUE to accept the stage, PETSC_FALSE to reject 606 607 Level: developer 608 609 .seealso: 610 @*/ 611 PetscErrorCode TSAdaptCheckStage(TSAdapt adapt,TS ts,PetscBool *accept) 612 { 613 PetscErrorCode ierr; 614 SNES snes; 615 SNESConvergedReason snesreason; 616 617 PetscFunctionBegin; 618 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 619 PetscValidHeaderSpecific(ts,TS_CLASSID,2); 620 PetscValidIntPointer(accept,3); 621 *accept = PETSC_TRUE; 622 ierr = TSGetSNES(ts,&snes);CHKERRQ(ierr); 623 ierr = SNESGetConvergedReason(snes,&snesreason);CHKERRQ(ierr); 624 if (snesreason < 0) { 625 PetscReal dt,new_dt; 626 *accept = PETSC_FALSE; 627 ierr = TSGetTimeStep(ts,&dt);CHKERRQ(ierr); 628 if (++ts->num_snes_failures >= ts->max_snes_failures && ts->max_snes_failures > 0) { 629 ts->reason = TS_DIVERGED_NONLINEAR_SOLVE; 630 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); 631 if (adapt->monitor) { 632 ierr = PetscViewerASCIIAddTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr); 633 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,dt,ts->num_snes_failures);CHKERRQ(ierr); 634 ierr = PetscViewerASCIISubtractTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr); 635 } 636 } else { 637 new_dt = dt*adapt->scale_solve_failed; 638 ierr = TSSetTimeStep(ts,new_dt);CHKERRQ(ierr); 639 if (adapt->monitor) { 640 ierr = PetscViewerASCIIAddTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr); 641 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); 642 ierr = PetscViewerASCIISubtractTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr); 643 } 644 } 645 } 646 if (adapt->checkstage) {ierr = (*adapt->checkstage)(adapt,ts,accept);CHKERRQ(ierr);} 647 PetscFunctionReturn(0); 648 } 649 650 651 652 #undef __FUNCT__ 653 #define __FUNCT__ "TSAdaptCreate" 654 /*@ 655 TSAdaptCreate - create an adaptive controller context for time stepping 656 657 Collective on MPI_Comm 658 659 Input Parameter: 660 . comm - The communicator 661 662 Output Parameter: 663 . adapt - new TSAdapt object 664 665 Level: developer 666 667 Notes: 668 TSAdapt creation is handled by TS, so users should not need to call this function. 669 670 .keywords: TSAdapt, create 671 .seealso: TSGetAdapt(), TSAdaptSetType(), TSAdaptDestroy() 672 @*/ 673 PetscErrorCode TSAdaptCreate(MPI_Comm comm,TSAdapt *inadapt) 674 { 675 PetscErrorCode ierr; 676 TSAdapt adapt; 677 678 PetscFunctionBegin; 679 PetscValidPointer(inadapt,1); 680 *inadapt = NULL; 681 ierr = TSAdaptInitializePackage();CHKERRQ(ierr); 682 683 ierr = PetscHeaderCreate(adapt,TSADAPT_CLASSID,"TSAdapt","Time stepping adaptivity","TS",comm,TSAdaptDestroy,TSAdaptView);CHKERRQ(ierr); 684 685 adapt->dt_min = 1e-20; 686 adapt->dt_max = 1e50; 687 adapt->scale_solve_failed = 0.25; 688 adapt->wnormtype = NORM_2; 689 690 *inadapt = adapt; 691 PetscFunctionReturn(0); 692 } 693