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