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