1 #define PETSCTS_DLL 2 3 /* 4 Code for Timestepping with implicit backwards Euler. 5 */ 6 #include "include/private/tsimpl.h" /*I "petscts.h" I*/ 7 8 typedef struct { 9 Vec update; /* work vector where new solution is formed */ 10 Vec func; /* work vector where F(t[i],u[i]) is stored */ 11 Vec rhs; /* work vector for RHS; vec_sol/dt */ 12 13 /* information used for Pseudo-timestepping */ 14 15 PetscErrorCode (*dt)(TS,PetscReal*,void*); /* compute next timestep, and related context */ 16 void *dtctx; 17 PetscErrorCode (*verify)(TS,Vec,void*,PetscReal*,PetscTruth*); /* verify previous timestep and related context */ 18 void *verifyctx; 19 20 PetscReal initial_fnorm,fnorm; /* original and current norm of F(u) */ 21 PetscReal fnorm_previous; 22 23 PetscReal dt_increment; /* scaling that dt is incremented each time-step */ 24 PetscTruth increment_dt_from_initial_dt; 25 } TS_Pseudo; 26 27 /* ------------------------------------------------------------------------------*/ 28 29 #undef __FUNCT__ 30 #define __FUNCT__ "TSPseudoComputeTimeStep" 31 /*@ 32 TSPseudoComputeTimeStep - Computes the next timestep for a currently running 33 pseudo-timestepping process. 34 35 Collective on TS 36 37 Input Parameter: 38 . ts - timestep context 39 40 Output Parameter: 41 . dt - newly computed timestep 42 43 Level: advanced 44 45 Notes: 46 The routine to be called here to compute the timestep should be 47 set by calling TSPseudoSetTimeStep(). 48 49 .keywords: timestep, pseudo, compute 50 51 .seealso: TSPseudoDefaultTimeStep(), TSPseudoSetTimeStep() 52 @*/ 53 PetscErrorCode PETSCTS_DLLEXPORT TSPseudoComputeTimeStep(TS ts,PetscReal *dt) 54 { 55 TS_Pseudo *pseudo = (TS_Pseudo*)ts->data; 56 PetscErrorCode ierr; 57 58 PetscFunctionBegin; 59 ierr = PetscLogEventBegin(TS_PseudoComputeTimeStep,ts,0,0,0);CHKERRQ(ierr); 60 ierr = (*pseudo->dt)(ts,dt,pseudo->dtctx);CHKERRQ(ierr); 61 ierr = PetscLogEventEnd(TS_PseudoComputeTimeStep,ts,0,0,0);CHKERRQ(ierr); 62 PetscFunctionReturn(0); 63 } 64 65 66 /* ------------------------------------------------------------------------------*/ 67 #undef __FUNCT__ 68 #define __FUNCT__ "TSPseudoDefaultVerifyTimeStep" 69 /*@C 70 TSPseudoDefaultVerifyTimeStep - Default code to verify the quality of the last timestep. 71 72 Collective on TS 73 74 Input Parameters: 75 + ts - the timestep context 76 . dtctx - unused timestep context 77 - update - latest solution vector 78 79 Output Parameters: 80 + newdt - the timestep to use for the next step 81 - flag - flag indicating whether the last time step was acceptable 82 83 Level: advanced 84 85 Note: 86 This routine always returns a flag of 1, indicating an acceptable 87 timestep. 88 89 .keywords: timestep, pseudo, default, verify 90 91 .seealso: TSPseudoSetVerifyTimeStep(), TSPseudoVerifyTimeStep() 92 @*/ 93 PetscErrorCode PETSCTS_DLLEXPORT TSPseudoDefaultVerifyTimeStep(TS ts,Vec update,void *dtctx,PetscReal *newdt,PetscTruth *flag) 94 { 95 PetscFunctionBegin; 96 *flag = PETSC_TRUE; 97 PetscFunctionReturn(0); 98 } 99 100 101 #undef __FUNCT__ 102 #define __FUNCT__ "TSPseudoVerifyTimeStep" 103 /*@ 104 TSPseudoVerifyTimeStep - Verifies whether the last timestep was acceptable. 105 106 Collective on TS 107 108 Input Parameters: 109 + ts - timestep context 110 - update - latest solution vector 111 112 Output Parameters: 113 + dt - newly computed timestep (if it had to shrink) 114 - flag - indicates if current timestep was ok 115 116 Level: advanced 117 118 Notes: 119 The routine to be called here to compute the timestep should be 120 set by calling TSPseudoSetVerifyTimeStep(). 121 122 .keywords: timestep, pseudo, verify 123 124 .seealso: TSPseudoSetVerifyTimeStep(), TSPseudoDefaultVerifyTimeStep() 125 @*/ 126 PetscErrorCode PETSCTS_DLLEXPORT TSPseudoVerifyTimeStep(TS ts,Vec update,PetscReal *dt,PetscTruth *flag) 127 { 128 TS_Pseudo *pseudo = (TS_Pseudo*)ts->data; 129 PetscErrorCode ierr; 130 131 PetscFunctionBegin; 132 if (!pseudo->verify) {*flag = PETSC_TRUE; PetscFunctionReturn(0);} 133 134 ierr = (*pseudo->verify)(ts,update,pseudo->verifyctx,dt,flag);CHKERRQ(ierr); 135 136 PetscFunctionReturn(0); 137 } 138 139 /* --------------------------------------------------------------------------------*/ 140 141 #undef __FUNCT__ 142 #define __FUNCT__ "TSStep_Pseudo" 143 static PetscErrorCode TSStep_Pseudo(TS ts,PetscInt *steps,PetscReal *ptime) 144 { 145 Vec sol = ts->vec_sol; 146 PetscErrorCode ierr; 147 PetscInt i,max_steps = ts->max_steps,its,lits; 148 PetscTruth ok; 149 TS_Pseudo *pseudo = (TS_Pseudo*)ts->data; 150 PetscReal current_time_step; 151 152 PetscFunctionBegin; 153 *steps = -ts->steps; 154 155 ierr = VecCopy(sol,pseudo->update);CHKERRQ(ierr); 156 for (i=0; i<max_steps && ts->ptime < ts->max_time; i++) { 157 ierr = TSPseudoComputeTimeStep(ts,&ts->time_step);CHKERRQ(ierr); 158 ierr = TSMonitor(ts,ts->steps,ts->ptime,sol);CHKERRQ(ierr); 159 current_time_step = ts->time_step; 160 while (PETSC_TRUE) { 161 ts->ptime += current_time_step; 162 ierr = SNESSolve(ts->snes,PETSC_NULL,pseudo->update);CHKERRQ(ierr); 163 ierr = SNESGetLinearSolveIterations(ts->snes,&lits);CHKERRQ(ierr); 164 ierr = SNESGetIterationNumber(ts->snes,&its);CHKERRQ(ierr); 165 ts->nonlinear_its += its; ts->linear_its += lits; 166 ierr = TSPseudoVerifyTimeStep(ts,pseudo->update,&ts->time_step,&ok);CHKERRQ(ierr); 167 if (ok) break; 168 ts->ptime -= current_time_step; 169 current_time_step = ts->time_step; 170 } 171 ierr = VecCopy(pseudo->update,sol);CHKERRQ(ierr); 172 ts->steps++; 173 } 174 ierr = TSComputeRHSFunction(ts,ts->ptime,ts->vec_sol,pseudo->func);CHKERRQ(ierr); 175 ierr = VecNorm(pseudo->func,NORM_2,&pseudo->fnorm);CHKERRQ(ierr); 176 ierr = TSMonitor(ts,ts->steps,ts->ptime,sol);CHKERRQ(ierr); 177 178 *steps += ts->steps; 179 *ptime = ts->ptime; 180 PetscFunctionReturn(0); 181 } 182 183 /*------------------------------------------------------------*/ 184 #undef __FUNCT__ 185 #define __FUNCT__ "TSDestroy_Pseudo" 186 static PetscErrorCode TSDestroy_Pseudo(TS ts) 187 { 188 TS_Pseudo *pseudo = (TS_Pseudo*)ts->data; 189 PetscErrorCode ierr; 190 191 PetscFunctionBegin; 192 if (pseudo->update) {ierr = VecDestroy(pseudo->update);CHKERRQ(ierr);} 193 if (pseudo->func) {ierr = VecDestroy(pseudo->func);CHKERRQ(ierr);} 194 if (pseudo->rhs) {ierr = VecDestroy(pseudo->rhs);CHKERRQ(ierr);} 195 ierr = PetscFree(pseudo);CHKERRQ(ierr); 196 PetscFunctionReturn(0); 197 } 198 199 200 /*------------------------------------------------------------*/ 201 202 /* 203 This defines the nonlinear equation that is to be solved with SNES 204 205 (U^{n+1} - U^{n})/dt - F(U^{n+1}) 206 */ 207 #undef __FUNCT__ 208 #define __FUNCT__ "TSPseudoFunction" 209 PetscErrorCode TSPseudoFunction(SNES snes,Vec x,Vec y,void *ctx) 210 { 211 TS ts = (TS) ctx; 212 PetscScalar mdt = 1.0/ts->time_step,*unp1,*un,*Funp1; 213 PetscErrorCode ierr; 214 PetscInt i,n; 215 216 PetscFunctionBegin; 217 /* apply user provided function */ 218 ierr = TSComputeRHSFunction(ts,ts->ptime,x,y);CHKERRQ(ierr); 219 /* compute (u^{n+1) - u^{n})/dt - F(u^{n+1}) */ 220 ierr = VecGetArray(ts->vec_sol,&un);CHKERRQ(ierr); 221 ierr = VecGetArray(x,&unp1);CHKERRQ(ierr); 222 ierr = VecGetArray(y,&Funp1);CHKERRQ(ierr); 223 ierr = VecGetLocalSize(x,&n);CHKERRQ(ierr); 224 for (i=0; i<n; i++) { 225 Funp1[i] = mdt*(unp1[i] - un[i]) - Funp1[i]; 226 } 227 ierr = VecRestoreArray(ts->vec_sol,&un);CHKERRQ(ierr); 228 ierr = VecRestoreArray(x,&unp1);CHKERRQ(ierr); 229 ierr = VecRestoreArray(y,&Funp1);CHKERRQ(ierr); 230 PetscFunctionReturn(0); 231 } 232 233 /* 234 This constructs the Jacobian needed for SNES 235 236 J = I/dt - J_{F} where J_{F} is the given Jacobian of F. 237 */ 238 #undef __FUNCT__ 239 #define __FUNCT__ "TSPseudoJacobian" 240 PetscErrorCode TSPseudoJacobian(SNES snes,Vec x,Mat *AA,Mat *BB,MatStructure *str,void *ctx) 241 { 242 TS ts = (TS) ctx; 243 PetscErrorCode ierr; 244 245 PetscFunctionBegin; 246 /* construct users Jacobian */ 247 ierr = TSComputeRHSJacobian(ts,ts->ptime,x,AA,BB,str);CHKERRQ(ierr); 248 249 /* shift and scale Jacobian */ 250 ierr = TSScaleShiftMatrices(ts,*AA,*BB,*str);CHKERRQ(ierr); 251 PetscFunctionReturn(0); 252 } 253 254 255 #undef __FUNCT__ 256 #define __FUNCT__ "TSSetUp_Pseudo" 257 static PetscErrorCode TSSetUp_Pseudo(TS ts) 258 { 259 TS_Pseudo *pseudo = (TS_Pseudo*)ts->data; 260 PetscErrorCode ierr; 261 262 PetscFunctionBegin; 263 ierr = VecDuplicate(ts->vec_sol,&pseudo->update);CHKERRQ(ierr); 264 ierr = VecDuplicate(ts->vec_sol,&pseudo->func);CHKERRQ(ierr); 265 ierr = SNESSetFunction(ts->snes,pseudo->func,TSPseudoFunction,ts);CHKERRQ(ierr); 266 ierr = SNESSetJacobian(ts->snes,ts->Arhs,ts->B,TSPseudoJacobian,ts);CHKERRQ(ierr); 267 PetscFunctionReturn(0); 268 } 269 /*------------------------------------------------------------*/ 270 271 #undef __FUNCT__ 272 #define __FUNCT__ "TSPseudoMonitorDefault" 273 PetscErrorCode TSPseudoMonitorDefault(TS ts,PetscInt step,PetscReal ptime,Vec v,void *ctx) 274 { 275 TS_Pseudo *pseudo = (TS_Pseudo*)ts->data; 276 PetscErrorCode ierr; 277 PetscViewerASCIIMonitor viewer = (PetscViewerASCIIMonitor)ctx; 278 279 PetscFunctionBegin; 280 if (!ctx) { 281 ierr = PetscViewerASCIIMonitorCreate(ts->comm,"stdout",0,&viewer);CHKERRQ(ierr); 282 } 283 ierr = PetscViewerASCIIMonitorPrintf(viewer,"TS %D dt %G time %G fnorm %G\n",step,ts->time_step,ptime,pseudo->fnorm);CHKERRQ(ierr); 284 if (!ctx) { 285 ierr = PetscViewerASCIIMonitorDestroy(viewer);CHKERRQ(ierr); 286 } 287 PetscFunctionReturn(0); 288 } 289 290 #undef __FUNCT__ 291 #define __FUNCT__ "TSSetFromOptions_Pseudo" 292 static PetscErrorCode TSSetFromOptions_Pseudo(TS ts) 293 { 294 TS_Pseudo *pseudo = (TS_Pseudo*)ts->data; 295 PetscErrorCode ierr; 296 PetscTruth flg; 297 PetscViewerASCIIMonitor viewer; 298 299 PetscFunctionBegin; 300 ierr = PetscOptionsHead("Pseudo-timestepping options");CHKERRQ(ierr); 301 ierr = PetscOptionsName("-ts_monitor","Monitor convergence","TSPseudoMonitorDefault",&flg);CHKERRQ(ierr); 302 if (flg) { 303 ierr = PetscViewerASCIIMonitorCreate(ts->comm,"stdout",0,&viewer);CHKERRQ(ierr); 304 ierr = TSMonitorSet(ts,TSPseudoMonitorDefault,viewer,(PetscErrorCode (*)(void*))PetscViewerASCIIMonitorDestroy);CHKERRQ(ierr); 305 } 306 ierr = PetscOptionsName("-ts_pseudo_increment_dt_from_initial_dt","Increase dt as a ratio from original dt","TSPseudoIncrementDtFromInitialDt",&flg);CHKERRQ(ierr); 307 if (flg) { 308 ierr = TSPseudoIncrementDtFromInitialDt(ts);CHKERRQ(ierr); 309 } 310 ierr = PetscOptionsReal("-ts_pseudo_increment","Ratio to increase dt","TSPseudoSetTimeStepIncrement",pseudo->dt_increment,&pseudo->dt_increment,0);CHKERRQ(ierr); 311 ierr = PetscOptionsTail();CHKERRQ(ierr); 312 PetscFunctionReturn(0); 313 } 314 315 #undef __FUNCT__ 316 #define __FUNCT__ "TSView_Pseudo" 317 static PetscErrorCode TSView_Pseudo(TS ts,PetscViewer viewer) 318 { 319 PetscFunctionBegin; 320 PetscFunctionReturn(0); 321 } 322 323 /* ----------------------------------------------------------------------------- */ 324 #undef __FUNCT__ 325 #define __FUNCT__ "TSPseudoSetVerifyTimeStep" 326 /*@C 327 TSPseudoSetVerifyTimeStep - Sets a user-defined routine to verify the quality of the 328 last timestep. 329 330 Collective on TS 331 332 Input Parameters: 333 + ts - timestep context 334 . dt - user-defined function to verify timestep 335 - ctx - [optional] user-defined context for private data 336 for the timestep verification routine (may be PETSC_NULL) 337 338 Level: advanced 339 340 Calling sequence of func: 341 . func (TS ts,Vec update,void *ctx,PetscReal *newdt,PetscTruth *flag); 342 343 . update - latest solution vector 344 . ctx - [optional] timestep context 345 . newdt - the timestep to use for the next step 346 . flag - flag indicating whether the last time step was acceptable 347 348 Notes: 349 The routine set here will be called by TSPseudoVerifyTimeStep() 350 during the timestepping process. 351 352 .keywords: timestep, pseudo, set, verify 353 354 .seealso: TSPseudoDefaultVerifyTimeStep(), TSPseudoVerifyTimeStep() 355 @*/ 356 PetscErrorCode PETSCTS_DLLEXPORT TSPseudoSetVerifyTimeStep(TS ts,PetscErrorCode (*dt)(TS,Vec,void*,PetscReal*,PetscTruth*),void* ctx) 357 { 358 PetscErrorCode ierr,(*f)(TS,PetscErrorCode (*)(TS,Vec,void*,PetscReal *,PetscTruth *),void *); 359 360 PetscFunctionBegin; 361 PetscValidHeaderSpecific(ts,TS_COOKIE,1); 362 363 ierr = PetscObjectQueryFunction((PetscObject)ts,"TSPseudoSetVerifyTimeStep_C",(void (**)(void))&f);CHKERRQ(ierr); 364 if (f) { 365 ierr = (*f)(ts,dt,ctx);CHKERRQ(ierr); 366 } 367 PetscFunctionReturn(0); 368 } 369 370 #undef __FUNCT__ 371 #define __FUNCT__ "TSPseudoSetTimeStepIncrement" 372 /*@ 373 TSPseudoSetTimeStepIncrement - Sets the scaling increment applied to 374 dt when using the TSPseudoDefaultTimeStep() routine. 375 376 Collective on TS 377 378 Input Parameters: 379 + ts - the timestep context 380 - inc - the scaling factor >= 1.0 381 382 Options Database Key: 383 $ -ts_pseudo_increment <increment> 384 385 Level: advanced 386 387 .keywords: timestep, pseudo, set, increment 388 389 .seealso: TSPseudoSetTimeStep(), TSPseudoDefaultTimeStep() 390 @*/ 391 PetscErrorCode PETSCTS_DLLEXPORT TSPseudoSetTimeStepIncrement(TS ts,PetscReal inc) 392 { 393 PetscErrorCode ierr,(*f)(TS,PetscReal); 394 395 PetscFunctionBegin; 396 PetscValidHeaderSpecific(ts,TS_COOKIE,1); 397 398 ierr = PetscObjectQueryFunction((PetscObject)ts,"TSPseudoSetTimeStepIncrement_C",(void (**)(void))&f);CHKERRQ(ierr); 399 if (f) { 400 ierr = (*f)(ts,inc);CHKERRQ(ierr); 401 } 402 PetscFunctionReturn(0); 403 } 404 405 #undef __FUNCT__ 406 #define __FUNCT__ "TSPseudoIncrementDtFromInitialDt" 407 /*@ 408 TSPseudoIncrementDtFromInitialDt - Indicates that a new timestep 409 is computed via the formula 410 $ dt = initial_dt*initial_fnorm/current_fnorm 411 rather than the default update, 412 $ dt = current_dt*previous_fnorm/current_fnorm. 413 414 Collective on TS 415 416 Input Parameter: 417 . ts - the timestep context 418 419 Options Database Key: 420 $ -ts_pseudo_increment_dt_from_initial_dt 421 422 Level: advanced 423 424 .keywords: timestep, pseudo, set, increment 425 426 .seealso: TSPseudoSetTimeStep(), TSPseudoDefaultTimeStep() 427 @*/ 428 PetscErrorCode PETSCTS_DLLEXPORT TSPseudoIncrementDtFromInitialDt(TS ts) 429 { 430 PetscErrorCode ierr,(*f)(TS); 431 432 PetscFunctionBegin; 433 PetscValidHeaderSpecific(ts,TS_COOKIE,1); 434 435 ierr = PetscObjectQueryFunction((PetscObject)ts,"TSPseudoIncrementDtFromInitialDt_C",(void (**)(void))&f);CHKERRQ(ierr); 436 if (f) { 437 ierr = (*f)(ts);CHKERRQ(ierr); 438 } 439 PetscFunctionReturn(0); 440 } 441 442 443 #undef __FUNCT__ 444 #define __FUNCT__ "TSPseudoSetTimeStep" 445 /*@C 446 TSPseudoSetTimeStep - Sets the user-defined routine to be 447 called at each pseudo-timestep to update the timestep. 448 449 Collective on TS 450 451 Input Parameters: 452 + ts - timestep context 453 . dt - function to compute timestep 454 - ctx - [optional] user-defined context for private data 455 required by the function (may be PETSC_NULL) 456 457 Level: intermediate 458 459 Calling sequence of func: 460 . func (TS ts,PetscReal *newdt,void *ctx); 461 462 . newdt - the newly computed timestep 463 . ctx - [optional] timestep context 464 465 Notes: 466 The routine set here will be called by TSPseudoComputeTimeStep() 467 during the timestepping process. 468 469 .keywords: timestep, pseudo, set 470 471 .seealso: TSPseudoDefaultTimeStep(), TSPseudoComputeTimeStep() 472 @*/ 473 PetscErrorCode PETSCTS_DLLEXPORT TSPseudoSetTimeStep(TS ts,PetscErrorCode (*dt)(TS,PetscReal*,void*),void* ctx) 474 { 475 PetscErrorCode ierr,(*f)(TS,PetscErrorCode (*)(TS,PetscReal *,void *),void *); 476 477 PetscFunctionBegin; 478 PetscValidHeaderSpecific(ts,TS_COOKIE,1); 479 480 ierr = PetscObjectQueryFunction((PetscObject)ts,"TSPseudoSetTimeStep_C",(void (**)(void))&f);CHKERRQ(ierr); 481 if (f) { 482 ierr = (*f)(ts,dt,ctx);CHKERRQ(ierr); 483 } 484 PetscFunctionReturn(0); 485 } 486 487 /* ----------------------------------------------------------------------------- */ 488 489 typedef PetscErrorCode (*FCN1)(TS,Vec,void*,PetscReal*,PetscTruth*); /* force argument to next function to not be extern C*/ 490 EXTERN_C_BEGIN 491 #undef __FUNCT__ 492 #define __FUNCT__ "TSPseudoSetVerifyTimeStep_Pseudo" 493 PetscErrorCode PETSCTS_DLLEXPORT TSPseudoSetVerifyTimeStep_Pseudo(TS ts,FCN1 dt,void* ctx) 494 { 495 TS_Pseudo *pseudo; 496 497 PetscFunctionBegin; 498 pseudo = (TS_Pseudo*)ts->data; 499 pseudo->verify = dt; 500 pseudo->verifyctx = ctx; 501 PetscFunctionReturn(0); 502 } 503 EXTERN_C_END 504 505 EXTERN_C_BEGIN 506 #undef __FUNCT__ 507 #define __FUNCT__ "TSPseudoSetTimeStepIncrement_Pseudo" 508 PetscErrorCode PETSCTS_DLLEXPORT TSPseudoSetTimeStepIncrement_Pseudo(TS ts,PetscReal inc) 509 { 510 TS_Pseudo *pseudo = (TS_Pseudo*)ts->data; 511 512 PetscFunctionBegin; 513 pseudo->dt_increment = inc; 514 PetscFunctionReturn(0); 515 } 516 EXTERN_C_END 517 518 EXTERN_C_BEGIN 519 #undef __FUNCT__ 520 #define __FUNCT__ "TSPseudoIncrementDtFromInitialDt_Pseudo" 521 PetscErrorCode PETSCTS_DLLEXPORT TSPseudoIncrementDtFromInitialDt_Pseudo(TS ts) 522 { 523 TS_Pseudo *pseudo = (TS_Pseudo*)ts->data; 524 525 PetscFunctionBegin; 526 pseudo->increment_dt_from_initial_dt = PETSC_TRUE; 527 PetscFunctionReturn(0); 528 } 529 EXTERN_C_END 530 531 typedef PetscErrorCode (*FCN2)(TS,PetscReal*,void*); /* force argument to next function to not be extern C*/ 532 EXTERN_C_BEGIN 533 #undef __FUNCT__ 534 #define __FUNCT__ "TSPseudoSetTimeStep_Pseudo" 535 PetscErrorCode PETSCTS_DLLEXPORT TSPseudoSetTimeStep_Pseudo(TS ts,FCN2 dt,void* ctx) 536 { 537 TS_Pseudo *pseudo = (TS_Pseudo*)ts->data; 538 539 PetscFunctionBegin; 540 pseudo->dt = dt; 541 pseudo->dtctx = ctx; 542 PetscFunctionReturn(0); 543 } 544 EXTERN_C_END 545 546 /* ----------------------------------------------------------------------------- */ 547 548 EXTERN_C_BEGIN 549 #undef __FUNCT__ 550 #define __FUNCT__ "TSCreate_Pseudo" 551 PetscErrorCode PETSCTS_DLLEXPORT TSCreate_Pseudo(TS ts) 552 { 553 TS_Pseudo *pseudo; 554 PetscErrorCode ierr; 555 556 PetscFunctionBegin; 557 ts->ops->destroy = TSDestroy_Pseudo; 558 ts->ops->view = TSView_Pseudo; 559 560 if (ts->problem_type == TS_LINEAR) { 561 SETERRQ(PETSC_ERR_ARG_WRONG,"Only for nonlinear problems"); 562 } 563 if (!ts->Arhs) { 564 SETERRQ(PETSC_ERR_ARG_WRONGSTATE,"Must set Jacobian"); 565 } 566 567 ts->ops->setup = TSSetUp_Pseudo; 568 ts->ops->step = TSStep_Pseudo; 569 ts->ops->setfromoptions = TSSetFromOptions_Pseudo; 570 571 /* create the required nonlinear solver context */ 572 ierr = SNESCreate(ts->comm,&ts->snes);CHKERRQ(ierr); 573 574 ierr = PetscNewLog(ts,TS_Pseudo,&pseudo);CHKERRQ(ierr); 575 ts->data = (void*)pseudo; 576 577 pseudo->dt_increment = 1.1; 578 pseudo->increment_dt_from_initial_dt = PETSC_FALSE; 579 pseudo->dt = TSPseudoDefaultTimeStep; 580 581 ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSPseudoSetVerifyTimeStep_C", 582 "TSPseudoSetVerifyTimeStep_Pseudo", 583 TSPseudoSetVerifyTimeStep_Pseudo);CHKERRQ(ierr); 584 ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSPseudoSetTimeStepIncrement_C", 585 "TSPseudoSetTimeStepIncrement_Pseudo", 586 TSPseudoSetTimeStepIncrement_Pseudo);CHKERRQ(ierr); 587 ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSPseudoIncrementDtFromInitialDt_C", 588 "TSPseudoIncrementDtFromInitialDt_Pseudo", 589 TSPseudoIncrementDtFromInitialDt_Pseudo);CHKERRQ(ierr); 590 ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSPseudoSetTimeStep_C", 591 "TSPseudoSetTimeStep_Pseudo", 592 TSPseudoSetTimeStep_Pseudo);CHKERRQ(ierr); 593 PetscFunctionReturn(0); 594 } 595 EXTERN_C_END 596 597 #undef __FUNCT__ 598 #define __FUNCT__ "TSPseudoDefaultTimeStep" 599 /*@C 600 TSPseudoDefaultTimeStep - Default code to compute pseudo-timestepping. 601 Use with TSPseudoSetTimeStep(). 602 603 Collective on TS 604 605 Input Parameters: 606 . ts - the timestep context 607 . dtctx - unused timestep context 608 609 Output Parameter: 610 . newdt - the timestep to use for the next step 611 612 Level: advanced 613 614 .keywords: timestep, pseudo, default 615 616 .seealso: TSPseudoSetTimeStep(), TSPseudoComputeTimeStep() 617 @*/ 618 PetscErrorCode PETSCTS_DLLEXPORT TSPseudoDefaultTimeStep(TS ts,PetscReal* newdt,void* dtctx) 619 { 620 TS_Pseudo *pseudo = (TS_Pseudo*)ts->data; 621 PetscReal inc = pseudo->dt_increment,fnorm_previous = pseudo->fnorm_previous; 622 PetscErrorCode ierr; 623 624 PetscFunctionBegin; 625 ierr = TSComputeRHSFunction(ts,ts->ptime,ts->vec_sol,pseudo->func);CHKERRQ(ierr); 626 ierr = VecNorm(pseudo->func,NORM_2,&pseudo->fnorm);CHKERRQ(ierr); 627 if (pseudo->initial_fnorm == 0.0) { 628 /* first time through so compute initial function norm */ 629 pseudo->initial_fnorm = pseudo->fnorm; 630 fnorm_previous = pseudo->fnorm; 631 } 632 if (pseudo->fnorm == 0.0) { 633 *newdt = 1.e12*inc*ts->time_step; 634 } else if (pseudo->increment_dt_from_initial_dt) { 635 *newdt = inc*ts->initial_time_step*pseudo->initial_fnorm/pseudo->fnorm; 636 } else { 637 *newdt = inc*ts->time_step*fnorm_previous/pseudo->fnorm; 638 } 639 pseudo->fnorm_previous = pseudo->fnorm; 640 PetscFunctionReturn(0); 641 } 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659