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