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