1 /*$Id: posindep.c,v 1.46 2000/09/02 02:50:00 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,double*,void*); /* compute next timestep, and related context */ 15 void *dtctx; 16 int (*verify)(TS,Vec,void*,double*,int*); /* verify previous timestep and related context */ 17 void *verifyctx; 18 19 double initial_fnorm,fnorm; /* original and current norm of F(u) */ 20 double fnorm_previous; 21 22 double 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 __FUNC__ 29 #define __FUNC__ /*<a name=""></a>*/"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,double *dt) 53 { 54 TS_Pseudo *pseudo = (TS_Pseudo*)ts->data; 55 int ierr; 56 57 PetscFunctionBegin; 58 ierr = PLogEventBegin(TS_PseudoComputeTimeStep,ts,0,0,0);CHKERRQ(ierr); 59 ierr = (*pseudo->dt)(ts,dt,pseudo->dtctx);CHKERRQ(ierr); 60 ierr = PLogEventEnd(TS_PseudoComputeTimeStep,ts,0,0,0);CHKERRQ(ierr); 61 PetscFunctionReturn(0); 62 } 63 64 65 /* ------------------------------------------------------------------------------*/ 66 #undef __FUNC__ 67 #define __FUNC__ /*<a name=""></a>*/"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,double *newdt,int *flag) 93 { 94 PetscFunctionBegin; 95 *flag = 1; 96 PetscFunctionReturn(0); 97 } 98 99 100 #undef __FUNC__ 101 #define __FUNC__ /*<a name=""></a>*/"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,double *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 __FUNC__ 141 #define __FUNC__ /*<a name=""></a>*/"TSStep_Pseudo" 142 static int TSStep_Pseudo(TS ts,int *steps,double *time) 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 double 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 *time = ts->ptime; 173 PetscFunctionReturn(0); 174 } 175 176 /*------------------------------------------------------------*/ 177 #undef __FUNC__ 178 #define __FUNC__ /*<a name=""></a>*/"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 __FUNC__ 200 #define __FUNC__ /*<a name=""></a>*/"TSPseudoMatMult" 201 int TSPseudoMatMult(Mat mat,Vec x,Vec y) 202 { 203 TS ts; 204 Scalar 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 __FUNC__ 224 #define __FUNC__ /*<a name=""></a>*/"TSPseudoFunction" 225 int TSPseudoFunction(SNES snes,Vec x,Vec y,void *ctx) 226 { 227 TS ts = (TS) ctx; 228 Scalar 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 __FUNC__ 255 #define __FUNC__ /*<a name=""></a>*/"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 Scalar mone = -1.0,mdt = 1.0/ts->time_step; 261 MatType mtype; 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 = MatGetType(*AA,&mtype,PETSC_NULL);CHKERRQ(ierr); 269 if (mtype != MATSHELL) { 270 ierr = MatScale(&mone,*AA);CHKERRQ(ierr); 271 ierr = MatShift(&mdt,*AA);CHKERRQ(ierr); 272 } 273 ierr = MatGetType(*BB,&mtype,PETSC_NULL);CHKERRQ(ierr); 274 if (*BB != *AA && *str != SAME_PRECONDITIONER && mtype != MATSHELL) { 275 ierr = MatScale(&mone,*BB);CHKERRQ(ierr); 276 ierr = MatShift(&mdt,*BB);CHKERRQ(ierr); 277 } 278 279 PetscFunctionReturn(0); 280 } 281 282 283 #undef __FUNC__ 284 #define __FUNC__ /*<a name=""></a>*/"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 = VecDuplicate(ts->vec_sol,&pseudo->update);CHKERRQ(ierr); 292 ierr = VecDuplicate(ts->vec_sol,&pseudo->func);CHKERRQ(ierr); 293 ierr = SNESSetFunction(ts->snes,pseudo->func,TSPseudoFunction,ts);CHKERRQ(ierr); 294 if (ts->Ashell) { /* construct new shell matrix */ 295 ierr = VecGetSize(ts->vec_sol,&M);CHKERRQ(ierr); 296 ierr = VecGetLocalSize(ts->vec_sol,&m);CHKERRQ(ierr); 297 ierr = MatCreateShell(ts->comm,m,M,M,M,ts,&ts->A);CHKERRQ(ierr); 298 ierr = MatShellSetOperation(ts->A,MATOP_MULT,(void*)TSPseudoMatMult);CHKERRQ(ierr); 299 } 300 ierr = SNESSetJacobian(ts->snes,ts->A,ts->B,TSPseudoJacobian,ts);CHKERRQ(ierr); 301 PetscFunctionReturn(0); 302 } 303 /*------------------------------------------------------------*/ 304 305 #undef __FUNC__ 306 #define __FUNC__ /*<a name=""></a>*/"TSPseudoDefaultMonitor" 307 int TSPseudoDefaultMonitor(TS ts,int step,double time,Vec v,void *ctx) 308 { 309 TS_Pseudo *pseudo = (TS_Pseudo*)ts->data; 310 int ierr; 311 312 PetscFunctionBegin; 313 ierr = (*PetscHelpPrintf)(ts->comm,"TS %d dt %g time %g fnorm %g\n",step,ts->time_step,time,pseudo->fnorm);CHKERRQ(ierr); 314 PetscFunctionReturn(0); 315 } 316 317 #undef __FUNC__ 318 #define __FUNC__ /*<a name=""></a>*/"TSSetFromOptions_Pseudo" 319 static int TSSetFromOptions_Pseudo(TS ts) 320 { 321 TS_Pseudo *pseudo = (TS_Pseudo*)ts->data; 322 int ierr; 323 PetscTruth flg; 324 325 PetscFunctionBegin; 326 327 ierr = OptionsHead("Pseudo-timestepping options");CHKERRQ(ierr); 328 ierr = OptionsName("-ts_monitor","Monitor convergence","TSPseudoDefaultMonitor",&flg);CHKERRQ(ierr); 329 if (flg) { 330 ierr = TSSetMonitor(ts,TSPseudoDefaultMonitor,PETSC_NULL,PETSC_NULL);CHKERRQ(ierr); 331 } 332 ierr = OptionsName("-ts_pseudo_increment_dt_from_initial_dt","Increase dt as a ratio from original dt","TSPseudoIncrementDtFromInitialDt",&flg);CHKERRQ(ierr); 333 if (flg) { 334 ierr = TSPseudoIncrementDtFromInitialDt(ts);CHKERRQ(ierr); 335 } 336 ierr = OptionsDouble("-ts_pseudo_increment","Ratio to increase dt","TSPseudoSetTimeStepIncrement",pseudo->dt_increment,&pseudo->dt_increment,0);CHKERRQ(ierr); 337 ierr = OptionsTail();CHKERRQ(ierr); 338 339 ierr = SNESSetFromOptions(ts->snes);CHKERRQ(ierr); 340 PetscFunctionReturn(0); 341 } 342 343 #undef __FUNC__ 344 #define __FUNC__ /*<a name=""></a>*/"TSView_Pseudo" 345 static int TSView_Pseudo(TS ts,Viewer viewer) 346 { 347 PetscFunctionBegin; 348 PetscFunctionReturn(0); 349 } 350 351 /* ----------------------------------------------------------------------------- */ 352 #undef __FUNC__ 353 #define __FUNC__ /*<a name=""></a>*/"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,double *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*,double*,int*),void* ctx) 385 { 386 int ierr,(*f)(TS,int (*)(TS,Vec,void*,double *,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 __FUNC__ 399 #define __FUNC__ /*<a name=""></a>*/"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,double inc) 420 { 421 int ierr,(*f)(TS,double); 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 __FUNC__ 434 #define __FUNC__ /*<a name=""></a>*/"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 __FUNC__ 472 #define __FUNC__ /*<a name=""></a>*/"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,double *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,double*,void*),void* ctx) 502 { 503 int ierr,(*f)(TS,int (*)(TS,double *,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 __FUNC__ 519 #define __FUNC__ /*<a name=""></a>*/"TSPseudoSetVerifyTimeStep_Pseudo" 520 int TSPseudoSetVerifyTimeStep_Pseudo(TS ts,int (*dt)(TS,Vec,void*,double*,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 __FUNC__ 534 #define __FUNC__ /*<a name=""></a>*/"TSPseudoSetTimeStepIncrement_Pseudo" 535 int TSPseudoSetTimeStepIncrement_Pseudo(TS ts,double 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 __FUNC__ 547 #define __FUNC__ /*<a name=""></a>*/"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 __FUNC__ 560 #define __FUNC__ /*<a name=""></a>*/"TSPseudoSetTimeStep_Pseudo" 561 int TSPseudoSetTimeStep_Pseudo(TS ts,int (*dt)(TS,double*,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 __FUNC__ 576 #define __FUNC__ /*<a name=""></a>*/"TSCreate_Pseudo" 577 int TSCreate_Pseudo(TS ts) 578 { 579 TS_Pseudo *pseudo; 580 int ierr; 581 MatType mtype; 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,0,"Only for nonlinear problems"); 589 } 590 if (!ts->A) { 591 SETERRQ(PETSC_ERR_ARG_WRONGSTATE,0,"Must set Jacobian"); 592 } 593 ierr = MatGetType(ts->A,&mtype,PETSC_NULL);CHKERRQ(ierr); 594 if (mtype == MATSHELL) { 595 ts->Ashell = ts->A; 596 } 597 ts->setup = TSSetUp_Pseudo; 598 ts->step = TSStep_Pseudo; 599 ts->setfromoptions = TSSetFromOptions_Pseudo; 600 601 /* create the required nonlinear solver context */ 602 ierr = SNESCreate(ts->comm,SNES_NONLINEAR_EQUATIONS,&ts->snes);CHKERRQ(ierr); 603 604 pseudo = PetscNew(TS_Pseudo);CHKPTRQ(pseudo); 605 PLogObjectMemory(ts,sizeof(TS_Pseudo)); 606 607 ierr = PetscMemzero(pseudo,sizeof(TS_Pseudo));CHKERRQ(ierr); 608 ts->data = (void*)pseudo; 609 610 pseudo->dt_increment = 1.1; 611 pseudo->increment_dt_from_initial_dt = PETSC_FALSE; 612 pseudo->dt = TSPseudoDefaultTimeStep; 613 614 ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSPseudoSetVerifyTimeStep_C", 615 "TSPseudoSetVerifyTimeStep_Pseudo", 616 TSPseudoSetVerifyTimeStep_Pseudo);CHKERRQ(ierr); 617 ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSPseudoSetTimeStepIncrement_C", 618 "TSPseudoSetTimeStepIncrement_Pseudo", 619 TSPseudoSetTimeStepIncrement_Pseudo);CHKERRQ(ierr); 620 ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSPseudoIncrementDtFromInitialDt_C", 621 "TSPseudoIncrementDtFromInitialDt_Pseudo", 622 TSPseudoIncrementDtFromInitialDt_Pseudo);CHKERRQ(ierr); 623 ierr = PetscObjectComposeFunctionDynamic((PetscObject)ts,"TSPseudoSetTimeStep_C", 624 "TSPseudoSetTimeStep_Pseudo", 625 TSPseudoSetTimeStep_Pseudo);CHKERRQ(ierr); 626 PetscFunctionReturn(0); 627 } 628 EXTERN_C_END 629 630 #undef __FUNC__ 631 #define __FUNC__ /*<a name=""></a>*/"TSPseudoDefaultTimeStep" 632 /*@C 633 TSPseudoDefaultTimeStep - Default code to compute pseudo-timestepping. 634 Use with TSPseudoSetTimeStep(). 635 636 Collective on TS 637 638 Input Parameters: 639 . ts - the timestep context 640 . dtctx - unused timestep context 641 642 Output Parameter: 643 . newdt - the timestep to use for the next step 644 645 Level: advanced 646 647 .keywords: timestep, pseudo, default 648 649 .seealso: TSPseudoSetTimeStep(), TSPseudoComputeTimeStep() 650 @*/ 651 int TSPseudoDefaultTimeStep(TS ts,double* newdt,void* dtctx) 652 { 653 TS_Pseudo *pseudo = (TS_Pseudo*)ts->data; 654 double inc = pseudo->dt_increment,fnorm_previous = pseudo->fnorm_previous; 655 int ierr; 656 657 PetscFunctionBegin; 658 ierr = TSComputeRHSFunction(ts,ts->ptime,ts->vec_sol,pseudo->func);CHKERRQ(ierr); 659 ierr = VecNorm(pseudo->func,NORM_2,&pseudo->fnorm);CHKERRQ(ierr); 660 if (pseudo->initial_fnorm == 0.0) { 661 /* first time through so compute initial function norm */ 662 pseudo->initial_fnorm = pseudo->fnorm; 663 fnorm_previous = pseudo->fnorm; 664 } 665 if (pseudo->fnorm == 0.0) { 666 *newdt = 1.e12*inc*ts->time_step; 667 } else if (pseudo->increment_dt_from_initial_dt) { 668 *newdt = inc*ts->initial_time_step*pseudo->initial_fnorm/pseudo->fnorm; 669 } else { 670 *newdt = inc*ts->time_step*fnorm_previous/pseudo->fnorm; 671 } 672 pseudo->fnorm_previous = pseudo->fnorm; 673 PetscFunctionReturn(0); 674 } 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692