1 2 #include <private/tsimpl.h> /*I "petscts.h" I*/ 3 4 static PetscFList TSAdaptList; 5 static PetscBool TSAdaptPackageInitialized; 6 static PetscBool TSAdaptRegisterAllCalled; 7 static PetscClassId TSADAPT_CLASSID; 8 9 EXTERN_C_BEGIN 10 PetscErrorCode TSAdaptCreate_Basic(TSAdapt); 11 PetscErrorCode TSAdaptCreate_CFL(TSAdapt); 12 EXTERN_C_END 13 14 #undef __FUNCT__ 15 #define __FUNCT__ "TSAdaptRegister" 16 /*@C 17 TSAdaptRegister - see TSAdaptRegisterDynamic() 18 19 Level: advanced 20 @*/ 21 PetscErrorCode TSAdaptRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(TSAdapt)) 22 { 23 PetscErrorCode ierr; 24 char fullname[PETSC_MAX_PATH_LEN]; 25 26 PetscFunctionBegin; 27 ierr = PetscFListConcat(path,name,fullname);CHKERRQ(ierr); 28 ierr = PetscFListAdd(&TSAdaptList,sname,fullname,(void(*)(void))function);CHKERRQ(ierr); 29 PetscFunctionReturn(0); 30 } 31 32 #undef __FUNCT__ 33 #define __FUNCT__ "TSAdaptRegisterAll" 34 /*@C 35 TSAdaptRegisterAll - Registers all of the adaptivity schemes in TSAdapt 36 37 Not Collective 38 39 Level: advanced 40 41 .keywords: TSAdapt, register, all 42 43 .seealso: TSAdaptRegisterDestroy() 44 @*/ 45 PetscErrorCode TSAdaptRegisterAll(const char path[]) 46 { 47 PetscErrorCode ierr; 48 49 PetscFunctionBegin; 50 ierr = TSAdaptRegisterDynamic(TSADAPTBASIC,path,"TSAdaptCreate_Basic",TSAdaptCreate_Basic);CHKERRQ(ierr); 51 ierr = TSAdaptRegisterDynamic(TSADAPTCFL, path,"TSAdaptCreate_CFL", TSAdaptCreate_CFL);CHKERRQ(ierr); 52 PetscFunctionReturn(0); 53 } 54 55 #undef __FUNCT__ 56 #define __FUNCT__ "TSAdaptFinalizePackage" 57 /*@C 58 TSFinalizePackage - This function destroys everything in the TS package. It is 59 called from PetscFinalize(). 60 61 Level: developer 62 63 .keywords: Petsc, destroy, package 64 .seealso: PetscFinalize() 65 @*/ 66 PetscErrorCode TSAdaptFinalizePackage(void) 67 { 68 PetscFunctionBegin; 69 TSAdaptPackageInitialized = PETSC_FALSE; 70 TSAdaptRegisterAllCalled = PETSC_FALSE; 71 TSAdaptList = PETSC_NULL; 72 PetscFunctionReturn(0); 73 } 74 75 #undef __FUNCT__ 76 #define __FUNCT__ "TSAdaptInitializePackage" 77 /*@C 78 TSAdaptInitializePackage - This function initializes everything in the TSAdapt package. It is 79 called from PetscDLLibraryRegister() when using dynamic libraries, and on the first call to 80 TSCreate_GL() when using static libraries. 81 82 Input Parameter: 83 path - The dynamic library path, or PETSC_NULL 84 85 Level: developer 86 87 .keywords: TSAdapt, initialize, package 88 .seealso: PetscInitialize() 89 @*/ 90 PetscErrorCode TSAdaptInitializePackage(const char path[]) 91 { 92 PetscErrorCode ierr; 93 94 PetscFunctionBegin; 95 if (TSAdaptPackageInitialized) PetscFunctionReturn(0); 96 TSAdaptPackageInitialized = PETSC_TRUE; 97 ierr = PetscClassIdRegister("TSAdapt",&TSADAPT_CLASSID);CHKERRQ(ierr); 98 ierr = TSAdaptRegisterAll(path);CHKERRQ(ierr); 99 ierr = PetscRegisterFinalize(TSAdaptFinalizePackage);CHKERRQ(ierr); 100 PetscFunctionReturn(0); 101 } 102 103 #undef __FUNCT__ 104 #define __FUNCT__ "TSAdaptRegisterDestroy" 105 /*@C 106 TSAdaptRegisterDestroy - Frees the list of adaptivity schemes that were registered by TSAdaptRegister()/TSAdaptRegisterDynamic(). 107 108 Not Collective 109 110 Level: advanced 111 112 .keywords: TSAdapt, register, destroy 113 .seealso: TSAdaptRegister(), TSAdaptRegisterAll(), TSAdaptRegisterDynamic() 114 @*/ 115 PetscErrorCode TSAdaptRegisterDestroy(void) 116 { 117 PetscErrorCode ierr; 118 119 PetscFunctionBegin; 120 ierr = PetscFListDestroy(&TSAdaptList);CHKERRQ(ierr); 121 TSAdaptRegisterAllCalled = PETSC_FALSE; 122 PetscFunctionReturn(0); 123 } 124 125 126 #undef __FUNCT__ 127 #define __FUNCT__ "TSAdaptSetType" 128 PetscErrorCode TSAdaptSetType(TSAdapt adapt,const TSAdaptType type) 129 { 130 PetscErrorCode ierr,(*r)(TSAdapt); 131 132 PetscFunctionBegin; 133 ierr = PetscFListFind(TSAdaptList,((PetscObject)adapt)->comm,type,PETSC_TRUE,(void(**)(void))&r);CHKERRQ(ierr); 134 if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unknown TSAdapt type \"%s\" given",type); 135 if (((PetscObject)adapt)->type_name) {ierr = (*adapt->ops->destroy)(adapt);CHKERRQ(ierr);} 136 ierr = (*r)(adapt);CHKERRQ(ierr); 137 ierr = PetscObjectChangeTypeName((PetscObject)adapt,type);CHKERRQ(ierr); 138 PetscFunctionReturn(0); 139 } 140 141 #undef __FUNCT__ 142 #define __FUNCT__ "TSAdaptSetOptionsPrefix" 143 PetscErrorCode TSAdaptSetOptionsPrefix(TSAdapt adapt,const char prefix[]) 144 { 145 PetscErrorCode ierr; 146 147 PetscFunctionBegin; 148 ierr = PetscObjectSetOptionsPrefix((PetscObject)adapt,prefix);CHKERRQ(ierr); 149 PetscFunctionReturn(0); 150 } 151 152 #undef __FUNCT__ 153 #define __FUNCT__ "TSAdaptView" 154 PetscErrorCode TSAdaptView(TSAdapt adapt,PetscViewer viewer) 155 { 156 PetscErrorCode ierr; 157 PetscBool iascii; 158 159 PetscFunctionBegin; 160 ierr = PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 161 if (iascii) { 162 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)adapt,viewer,"TSAdapt Object");CHKERRQ(ierr); 163 ierr = PetscViewerASCIIPrintf(viewer,"number of candidates %D\n",adapt->candidates.n);CHKERRQ(ierr); 164 if (adapt->ops->view) { 165 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 166 ierr = (*adapt->ops->view)(adapt,viewer);CHKERRQ(ierr); 167 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 168 } 169 } else { 170 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Viewer type %s not supported",((PetscObject)viewer)->type_name); 171 } 172 PetscFunctionReturn(0); 173 } 174 175 #undef __FUNCT__ 176 #define __FUNCT__ "TSAdaptDestroy" 177 PetscErrorCode TSAdaptDestroy(TSAdapt *adapt) 178 { 179 PetscErrorCode ierr; 180 181 PetscFunctionBegin; 182 if (!*adapt) PetscFunctionReturn(0); 183 PetscValidHeaderSpecific(*adapt,TSADAPT_CLASSID,1); 184 if (--((PetscObject)(*adapt))->refct > 0) {*adapt = 0; PetscFunctionReturn(0);} 185 if ((*adapt)->ops->destroy) {ierr = (*(*adapt)->ops->destroy)(*adapt);CHKERRQ(ierr);} 186 ierr = PetscViewerDestroy(&(*adapt)->monitor);CHKERRQ(ierr); 187 ierr = PetscHeaderDestroy(adapt);CHKERRQ(ierr); 188 PetscFunctionReturn(0); 189 } 190 191 #undef __FUNCT__ 192 #define __FUNCT__ "TSAdaptSetMonitor" 193 /*@ 194 TSAdaptSetMonitor - Monitor the choices made by the adaptive controller 195 196 Collective on TSAdapt 197 198 Input Arguments: 199 + adapt - adaptive controller context 200 - flg - PETSC_TRUE to active a monitor, PETSC_FALSE to disable 201 202 Level: intermediate 203 204 .seealso: TSAdaptChoose() 205 @*/ 206 PetscErrorCode TSAdaptSetMonitor(TSAdapt adapt,PetscBool flg) 207 { 208 PetscErrorCode ierr; 209 210 PetscFunctionBegin; 211 if (flg) { 212 if (!adapt->monitor) {ierr = PetscViewerASCIIOpen(((PetscObject)adapt)->comm,"stdout",&adapt->monitor);CHKERRQ(ierr);} 213 } else { 214 ierr = PetscViewerDestroy(&adapt->monitor);CHKERRQ(ierr); 215 } 216 PetscFunctionReturn(0); 217 } 218 219 #undef __FUNCT__ 220 #define __FUNCT__ "TSAdaptSetStepLimits" 221 /*@ 222 TSAdaptSetStepLimits - Set minimum and maximum step sizes to be considered by the controller 223 224 Logically Collective 225 226 Input Arguments: 227 + adapt - time step adaptivity context, usually gotten with TSGetAdapt() 228 . hmin - minimum time step 229 - hmax - maximum time step 230 231 Options Database Keys: 232 + -ts_adapt_dt_min - minimum time step 233 - -ts_adapt_dt_max - maximum time step 234 235 Level: intermediate 236 237 .seealso: TSAdapt 238 @*/ 239 PetscErrorCode TSAdaptSetStepLimits(TSAdapt adapt,PetscReal hmin,PetscReal hmax) 240 { 241 242 PetscFunctionBegin; 243 if (hmin != PETSC_DECIDE) adapt->dt_min = hmin; 244 if (hmax != PETSC_DECIDE) adapt->dt_max = hmax; 245 PetscFunctionReturn(0); 246 } 247 248 #undef __FUNCT__ 249 #define __FUNCT__ "TSAdaptSetFromOptions" 250 /*@ 251 TSAdaptSetFromOptions - Sets various TSAdapt parameters from user options. 252 253 Collective on TSAdapt 254 255 Input Parameter: 256 . adapt - the TSAdapt context 257 258 Options Database Keys: 259 . -ts_adapt_type <type> - basic 260 261 Level: advanced 262 263 Notes: 264 This function is automatically called by TSSetFromOptions() 265 266 .keywords: TS, TSGetAdapt(), TSAdaptSetType() 267 268 .seealso: TSGetType() 269 @*/ 270 PetscErrorCode TSAdaptSetFromOptions(TSAdapt adapt) 271 { 272 PetscErrorCode ierr; 273 char type[256] = TSADAPTBASIC; 274 PetscBool set,flg; 275 276 PetscFunctionBegin; 277 /* This should use PetscOptionsBegin() if/when this becomes an object used outside of TS, but currently this 278 * function can only be called from inside TSSetFromOptions_GL() */ 279 ierr = PetscOptionsHead("TS Adaptivity options");CHKERRQ(ierr); 280 ierr = PetscOptionsList("-ts_adapt_type","Algorithm to use for adaptivity","TSAdaptSetType",TSAdaptList, 281 ((PetscObject)adapt)->type_name?((PetscObject)adapt)->type_name:type,type,sizeof type,&flg);CHKERRQ(ierr); 282 if (flg || !((PetscObject)adapt)->type_name) { 283 ierr = TSAdaptSetType(adapt,type);CHKERRQ(ierr); 284 } 285 if (adapt->ops->setfromoptions) {ierr = (*adapt->ops->setfromoptions)(adapt);CHKERRQ(ierr);} 286 ierr = PetscOptionsReal("-ts_adapt_dt_min","Minimum time step considered","TSAdaptSetStepLimits",adapt->dt_min,&adapt->dt_min,PETSC_NULL);CHKERRQ(ierr); 287 ierr = PetscOptionsReal("-ts_adapt_dt_max","Maximum time step considered","TSAdaptSetStepLimits",adapt->dt_max,&adapt->dt_max,PETSC_NULL);CHKERRQ(ierr); 288 ierr = PetscOptionsBool("-ts_adapt_monitor","Print choices made by adaptive controller","TSAdaptSetMonitor",adapt->monitor ? PETSC_TRUE : PETSC_FALSE,&flg,&set);CHKERRQ(ierr); 289 if (set) {ierr = TSAdaptSetMonitor(adapt,flg);CHKERRQ(ierr);} 290 ierr = PetscOptionsTail();CHKERRQ(ierr); 291 PetscFunctionReturn(0); 292 } 293 294 #undef __FUNCT__ 295 #define __FUNCT__ "TSAdaptCandidatesClear" 296 /*@ 297 TSAdaptCandidatesClear - clear any previously set candidate schemes 298 299 Logically Collective 300 301 Input Argument: 302 . adapt - adaptive controller 303 304 Level: developer 305 306 .seealso: TSAdapt, TSAdaptCreate(), TSAdaptCandidateAdd(), TSAdaptChoose() 307 @*/ 308 PetscErrorCode TSAdaptCandidatesClear(TSAdapt adapt) 309 { 310 PetscErrorCode ierr; 311 312 PetscFunctionBegin; 313 ierr = PetscMemzero(&adapt->candidates,sizeof(adapt->candidates));CHKERRQ(ierr); 314 PetscFunctionReturn(0); 315 } 316 317 #undef __FUNCT__ 318 #define __FUNCT__ "TSAdaptCandidateAdd" 319 /*@C 320 TSAdaptCandidateAdd - add a candidate scheme for the adaptive controller to select from 321 322 Logically Collective 323 324 Input Arguments: 325 + adapt - time step adaptivity context, obtained with TSGetAdapt() or TSAdaptCreate() 326 . name - name of the candidate scheme to add 327 . order - order of the candidate scheme 328 . stageorder - stage order of the candidate scheme 329 . ccfl - stability coefficient relative to explicit Euler, used for CFL constraints 330 . cost - relative measure of the amount of work required for the candidate scheme 331 - inuse - indicates that this scheme is the one currently in use, this flag can only be set for one scheme 332 333 Note: 334 This routine is not available in Fortran. 335 336 Level: developer 337 338 .seealso: TSAdaptCandidatesClear(), TSAdaptChoose() 339 @*/ 340 PetscErrorCode TSAdaptCandidateAdd(TSAdapt adapt,const char name[],PetscInt order,PetscInt stageorder,PetscReal ccfl,PetscReal cost,PetscBool inuse) 341 { 342 PetscInt c; 343 344 PetscFunctionBegin; 345 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 346 if (order < 1) SETERRQ1(((PetscObject)adapt)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Classical order %D must be a positive integer",order); 347 if (inuse) { 348 if (adapt->candidates.inuse_set) SETERRQ(((PetscObject)adapt)->comm,PETSC_ERR_ARG_WRONGSTATE,"Cannot set the inuse method twice, maybe forgot to call TSAdaptCandidatesClear()"); 349 adapt->candidates.inuse_set = PETSC_TRUE; 350 } 351 /* first slot if this is the current scheme, otherwise the next available slot */ 352 c = inuse ? 0 : !adapt->candidates.inuse_set + adapt->candidates.n; 353 adapt->candidates.name[c] = name; 354 adapt->candidates.order[c] = order; 355 adapt->candidates.stageorder[c] = stageorder; 356 adapt->candidates.ccfl[c] = ccfl; 357 adapt->candidates.cost[c] = cost; 358 adapt->candidates.n++; 359 PetscFunctionReturn(0); 360 } 361 362 #undef __FUNCT__ 363 #define __FUNCT__ "TSAdaptCandidatesGet" 364 /*@C 365 TSAdaptCandidatesGet - Get the list of candidate orders of accuracy and cost 366 367 Not Collective 368 369 Input Arguments: 370 . adapt - time step adaptivity context 371 372 Output Arguments: 373 + n - number of candidate schemes, always at least 1 374 . order - the order of each candidate scheme 375 . stageorder - the stage order of each candidate scheme 376 . ccfl - the CFL coefficient of each scheme 377 - cost - the relative cost of each scheme 378 379 Level: developer 380 381 Note: 382 The current scheme is always returned in the first slot 383 384 .seealso: TSAdaptCandidatesClear(), TSAdaptCandidateAdd(), TSAdaptChoose() 385 @*/ 386 PetscErrorCode TSAdaptCandidatesGet(TSAdapt adapt,PetscInt *n,const PetscInt **order,const PetscInt **stageorder,const PetscReal **ccfl,const PetscReal **cost) 387 { 388 PetscFunctionBegin; 389 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 390 if (n) *n = adapt->candidates.n; 391 if (order) *order = adapt->candidates.order; 392 if (stageorder) *stageorder = adapt->candidates.stageorder; 393 if (ccfl) *ccfl = adapt->candidates.ccfl; 394 if (cost) *cost = adapt->candidates.cost; 395 PetscFunctionReturn(0); 396 } 397 398 #undef __FUNCT__ 399 #define __FUNCT__ "TSAdaptChoose" 400 /*@C 401 TSAdaptChoose - choose which method and step size to use for the next step 402 403 Logically Collective 404 405 Input Arguments: 406 + adapt - adaptive contoller 407 - h - current step size 408 409 Output Arguments: 410 + next_sc - scheme to use for the next step 411 . next_h - step size to use for the next step 412 - accept - PETSC_TRUE to accept the current step, PETSC_FALSE to repeat the current step with the new step size 413 414 Note: 415 The input value of parameter accept is retained from the last time step, so it will be PETSC_FALSE if the step is 416 being retried after an initial rejection. 417 418 Level: developer 419 420 .seealso: TSAdapt, TSAdaptCandidatesClear(), TSAdaptCandidateAdd() 421 @*/ 422 PetscErrorCode TSAdaptChoose(TSAdapt adapt,TS ts,PetscReal h,PetscInt *next_sc,PetscReal *next_h,PetscBool *accept) 423 { 424 PetscErrorCode ierr; 425 426 PetscFunctionBegin; 427 PetscValidHeaderSpecific(adapt,TSADAPT_CLASSID,1); 428 PetscValidHeaderSpecific(ts,TS_CLASSID,2); 429 PetscValidIntPointer(next_sc,4); 430 PetscValidPointer(next_h,5); 431 PetscValidIntPointer(accept,6); 432 if (adapt->candidates.n < 1) SETERRQ1(((PetscObject)adapt)->comm,PETSC_ERR_ARG_WRONGSTATE,"%D candidates have been registered",adapt->candidates.n); 433 if (!adapt->candidates.inuse_set) SETERRQ1(((PetscObject)adapt)->comm,PETSC_ERR_ARG_WRONGSTATE,"The current in-use scheme is not among the %D candidates",adapt->candidates.n); 434 ierr = (*adapt->ops->choose)(adapt,ts,h,next_sc,next_h,accept);CHKERRQ(ierr); 435 if (*next_sc < 0 || adapt->candidates.n <= *next_sc) SETERRQ2(((PetscObject)adapt)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Chosen scheme %D not in valid range 0..%D",*next_sc,adapt->candidates.n-1); 436 if (!(*next_h > 0.)) SETERRQ1(((PetscObject)adapt)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Computed step size %G must be positive",*next_h); 437 438 if (adapt->monitor) { 439 ierr = PetscViewerASCIIAddTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr); 440 ierr = PetscViewerASCIIPrintf(adapt->monitor," TSAdapt '%s': step %s family='%s' scheme=%D:'%s' dt=%G\n",((PetscObject)adapt)->type_name,accept?"accepted":"rejected",((PetscObject)ts)->type_name,*next_sc,adapt->candidates.name[*next_sc],*next_h);CHKERRQ(ierr); 441 ierr = PetscViewerASCIISubtractTab(adapt->monitor,((PetscObject)adapt)->tablevel);CHKERRQ(ierr); 442 } 443 PetscFunctionReturn(0); 444 } 445 446 #undef __FUNCT__ 447 #define __FUNCT__ "TSAdaptCreate" 448 /*@ 449 TSAdaptCreate - create an adaptive controller context for time stepping 450 451 Collective on MPI_Comm 452 453 Input Parameter: 454 . comm - The communicator 455 456 Output Parameter: 457 . adapt - new TSAdapt object 458 459 Level: developer 460 461 Notes: 462 TSAdapt creation is handled by TS, so users should not need to call this function. 463 464 .keywords: TSAdapt, create 465 .seealso: TSGetAdapt(), TSAdaptSetType(), TSAdaptDestroy() 466 @*/ 467 PetscErrorCode TSAdaptCreate(MPI_Comm comm,TSAdapt *inadapt) 468 { 469 PetscErrorCode ierr; 470 TSAdapt adapt; 471 472 PetscFunctionBegin; 473 *inadapt = 0; 474 ierr = PetscHeaderCreate(adapt,_p_TSAdapt,struct _TSAdaptOps,TSADAPT_CLASSID,0,"TSAdapt","General Linear adaptivity","TS",comm,TSAdaptDestroy,TSAdaptView);CHKERRQ(ierr); 475 476 adapt->dt_min = 1e-20; 477 adapt->dt_max = 1e50; 478 479 *inadapt = adapt; 480 PetscFunctionReturn(0); 481 } 482