Actual source code: posindep.c
petsc-3.11.4 2019-09-28
1: /*
2: Code for Timestepping with implicit backwards Euler.
3: */
4: #include <petsc/private/tsimpl.h>
6: typedef struct {
7: Vec update; /* work vector where new solution is formed */
8: Vec func; /* work vector where F(t[i],u[i]) is stored */
9: Vec xdot; /* work vector for time derivative of state */
11: /* information used for Pseudo-timestepping */
13: PetscErrorCode (*dt)(TS,PetscReal*,void*); /* compute next timestep, and related context */
14: void *dtctx;
15: PetscErrorCode (*verify)(TS,Vec,void*,PetscReal*,PetscBool*); /* verify previous timestep and related context */
16: void *verifyctx;
18: PetscReal fnorm_initial,fnorm; /* original and current norm of F(u) */
19: PetscReal fnorm_previous;
21: PetscReal dt_initial; /* initial time-step */
22: PetscReal dt_increment; /* scaling that dt is incremented each time-step */
23: PetscReal dt_max; /* maximum time step */
24: PetscBool increment_dt_from_initial_dt;
25: PetscReal fatol,frtol;
26: } TS_Pseudo;
28: /* ------------------------------------------------------------------------------*/
30: /*@C
31: TSPseudoComputeTimeStep - Computes the next timestep for a currently running
32: pseudo-timestepping process.
34: Collective on TS
36: Input Parameter:
37: . ts - timestep context
39: Output Parameter:
40: . dt - newly computed timestep
42: Level: developer
44: Notes:
45: The routine to be called here to compute the timestep should be
46: set by calling TSPseudoSetTimeStep().
48: .keywords: timestep, pseudo, compute
50: .seealso: TSPseudoTimeStepDefault(), TSPseudoSetTimeStep()
51: @*/
52: PetscErrorCode TSPseudoComputeTimeStep(TS ts,PetscReal *dt)
53: {
54: TS_Pseudo *pseudo = (TS_Pseudo*)ts->data;
58: PetscLogEventBegin(TS_PseudoComputeTimeStep,ts,0,0,0);
59: (*pseudo->dt)(ts,dt,pseudo->dtctx);
60: PetscLogEventEnd(TS_PseudoComputeTimeStep,ts,0,0,0);
61: return(0);
62: }
65: /* ------------------------------------------------------------------------------*/
66: /*@C
67: TSPseudoVerifyTimeStepDefault - Default code to verify the quality of the last timestep.
69: Collective on TS
71: Input Parameters:
72: + ts - the timestep context
73: . dtctx - unused timestep context
74: - update - latest solution vector
76: Output Parameters:
77: + newdt - the timestep to use for the next step
78: - flag - flag indicating whether the last time step was acceptable
80: Level: advanced
82: Note:
83: This routine always returns a flag of 1, indicating an acceptable
84: timestep.
86: .keywords: timestep, pseudo, default, verify
88: .seealso: TSPseudoSetVerifyTimeStep(), TSPseudoVerifyTimeStep()
89: @*/
90: PetscErrorCode TSPseudoVerifyTimeStepDefault(TS ts,Vec update,void *dtctx,PetscReal *newdt,PetscBool *flag)
91: {
93: *flag = PETSC_TRUE;
94: return(0);
95: }
98: /*@
99: TSPseudoVerifyTimeStep - Verifies whether the last timestep was acceptable.
101: Collective on TS
103: Input Parameters:
104: + ts - timestep context
105: - update - latest solution vector
107: Output Parameters:
108: + dt - newly computed timestep (if it had to shrink)
109: - flag - indicates if current timestep was ok
111: Level: advanced
113: Notes:
114: The routine to be called here to compute the timestep should be
115: set by calling TSPseudoSetVerifyTimeStep().
117: .keywords: timestep, pseudo, verify
119: .seealso: TSPseudoSetVerifyTimeStep(), TSPseudoVerifyTimeStepDefault()
120: @*/
121: PetscErrorCode TSPseudoVerifyTimeStep(TS ts,Vec update,PetscReal *dt,PetscBool *flag)
122: {
123: TS_Pseudo *pseudo = (TS_Pseudo*)ts->data;
127: *flag = PETSC_TRUE;
128: if(pseudo->verify) {
129: (*pseudo->verify)(ts,update,pseudo->verifyctx,dt,flag);
130: }
131: return(0);
132: }
134: /* --------------------------------------------------------------------------------*/
136: static PetscErrorCode TSStep_Pseudo(TS ts)
137: {
138: TS_Pseudo *pseudo = (TS_Pseudo*)ts->data;
139: PetscInt nits,lits,reject;
140: PetscBool stepok;
141: PetscReal next_time_step = ts->time_step;
142: PetscErrorCode ierr;
145: if (ts->steps == 0) pseudo->dt_initial = ts->time_step;
146: VecCopy(ts->vec_sol,pseudo->update);
147: TSPseudoComputeTimeStep(ts,&next_time_step);
148: for (reject=0; reject<ts->max_reject; reject++,ts->reject++) {
149: ts->time_step = next_time_step;
150: TSPreStage(ts,ts->ptime+ts->time_step);
151: SNESSolve(ts->snes,NULL,pseudo->update);
152: SNESGetIterationNumber(ts->snes,&nits);
153: SNESGetLinearSolveIterations(ts->snes,&lits);
154: ts->snes_its += nits; ts->ksp_its += lits;
155: TSPostStage(ts,ts->ptime+ts->time_step,0,&(pseudo->update));
156: TSAdaptCheckStage(ts->adapt,ts,ts->ptime+ts->time_step,pseudo->update,&stepok);
157: if (!stepok) {next_time_step = ts->time_step; continue;}
158: pseudo->fnorm = -1; /* The current norm is no longer valid, monitor must recompute it. */
159: TSPseudoVerifyTimeStep(ts,pseudo->update,&next_time_step,&stepok);
160: if (stepok) break;
161: }
162: if (reject >= ts->max_reject) {
163: ts->reason = TS_DIVERGED_STEP_REJECTED;
164: PetscInfo2(ts,"Step=%D, step rejections %D greater than current TS allowed, stopping solve\n",ts->steps,reject);
165: return(0);
166: }
168: VecCopy(pseudo->update,ts->vec_sol);
169: ts->ptime += ts->time_step;
170: ts->time_step = next_time_step;
172: if (pseudo->fnorm < 0) {
173: VecZeroEntries(pseudo->xdot);
174: TSComputeIFunction(ts,ts->ptime,ts->vec_sol,pseudo->xdot,pseudo->func,PETSC_FALSE);
175: VecNorm(pseudo->func,NORM_2,&pseudo->fnorm);
176: }
177: if (pseudo->fnorm < pseudo->fatol) {
178: ts->reason = TS_CONVERGED_PSEUDO_FATOL;
179: PetscInfo3(ts,"Step=%D, converged since fnorm %g < fatol %g\n",ts->steps,pseudo->fnorm,pseudo->frtol);
180: return(0);
181: }
182: if (pseudo->fnorm/pseudo->fnorm_initial < pseudo->frtol) {
183: ts->reason = TS_CONVERGED_PSEUDO_FRTOL;
184: PetscInfo4(ts,"Step=%D, converged since fnorm %g / fnorm_initial %g < frtol %g\n",ts->steps,pseudo->fnorm,pseudo->fnorm_initial,pseudo->fatol);
185: return(0);
186: }
187: return(0);
188: }
190: /*------------------------------------------------------------*/
191: static PetscErrorCode TSReset_Pseudo(TS ts)
192: {
193: TS_Pseudo *pseudo = (TS_Pseudo*)ts->data;
197: VecDestroy(&pseudo->update);
198: VecDestroy(&pseudo->func);
199: VecDestroy(&pseudo->xdot);
200: return(0);
201: }
203: static PetscErrorCode TSDestroy_Pseudo(TS ts)
204: {
208: TSReset_Pseudo(ts);
209: PetscFree(ts->data);
210: PetscObjectComposeFunction((PetscObject)ts,"TSPseudoSetVerifyTimeStep_C",NULL);
211: PetscObjectComposeFunction((PetscObject)ts,"TSPseudoSetTimeStepIncrement_C",NULL);
212: PetscObjectComposeFunction((PetscObject)ts,"TSPseudoSetMaxTimeStep_C",NULL);
213: PetscObjectComposeFunction((PetscObject)ts,"TSPseudoIncrementDtFromInitialDt_C",NULL);
214: PetscObjectComposeFunction((PetscObject)ts,"TSPseudoSetTimeStep_C",NULL);
215: return(0);
216: }
218: /*------------------------------------------------------------*/
220: /*
221: Compute Xdot = (X^{n+1}-X^n)/dt) = 0
222: */
223: static PetscErrorCode TSPseudoGetXdot(TS ts,Vec X,Vec *Xdot)
224: {
225: TS_Pseudo *pseudo = (TS_Pseudo*)ts->data;
226: const PetscScalar mdt = 1.0/ts->time_step,*xnp1,*xn;
227: PetscScalar *xdot;
228: PetscErrorCode ierr;
229: PetscInt i,n;
232: *Xdot = NULL;
233: VecGetArrayRead(ts->vec_sol,&xn);
234: VecGetArrayRead(X,&xnp1);
235: VecGetArray(pseudo->xdot,&xdot);
236: VecGetLocalSize(X,&n);
237: for (i=0; i<n; i++) xdot[i] = mdt*(xnp1[i] - xn[i]);
238: VecRestoreArrayRead(ts->vec_sol,&xn);
239: VecRestoreArrayRead(X,&xnp1);
240: VecRestoreArray(pseudo->xdot,&xdot);
241: *Xdot = pseudo->xdot;
242: return(0);
243: }
245: /*
246: The transient residual is
248: F(U^{n+1},(U^{n+1}-U^n)/dt) = 0
250: or for ODE,
252: (U^{n+1} - U^{n})/dt - F(U^{n+1}) = 0
254: This is the function that must be evaluated for transient simulation and for
255: finite difference Jacobians. On the first Newton step, this algorithm uses
256: a guess of U^{n+1} = U^n in which case the transient term vanishes and the
257: residual is actually the steady state residual. Pseudotransient
258: continuation as described in the literature is a linearly implicit
259: algorithm, it only takes this one Newton step with the steady state
260: residual, and then advances to the next time step.
261: */
262: static PetscErrorCode SNESTSFormFunction_Pseudo(SNES snes,Vec X,Vec Y,TS ts)
263: {
264: Vec Xdot;
268: TSPseudoGetXdot(ts,X,&Xdot);
269: TSComputeIFunction(ts,ts->ptime+ts->time_step,X,Xdot,Y,PETSC_FALSE);
270: return(0);
271: }
273: /*
274: This constructs the Jacobian needed for SNES. For DAE, this is
276: dF(X,Xdot)/dX + shift*dF(X,Xdot)/dXdot
278: and for ODE:
280: J = I/dt - J_{Frhs} where J_{Frhs} is the given Jacobian of Frhs.
281: */
282: static PetscErrorCode SNESTSFormJacobian_Pseudo(SNES snes,Vec X,Mat AA,Mat BB,TS ts)
283: {
284: Vec Xdot;
288: TSPseudoGetXdot(ts,X,&Xdot);
289: TSComputeIJacobian(ts,ts->ptime+ts->time_step,X,Xdot,1./ts->time_step,AA,BB,PETSC_FALSE);
290: return(0);
291: }
294: static PetscErrorCode TSSetUp_Pseudo(TS ts)
295: {
296: TS_Pseudo *pseudo = (TS_Pseudo*)ts->data;
300: VecDuplicate(ts->vec_sol,&pseudo->update);
301: VecDuplicate(ts->vec_sol,&pseudo->func);
302: VecDuplicate(ts->vec_sol,&pseudo->xdot);
303: return(0);
304: }
305: /*------------------------------------------------------------*/
307: static PetscErrorCode TSPseudoMonitorDefault(TS ts,PetscInt step,PetscReal ptime,Vec v,void *dummy)
308: {
309: TS_Pseudo *pseudo = (TS_Pseudo*)ts->data;
311: PetscViewer viewer = (PetscViewer) dummy;
314: if (pseudo->fnorm < 0) { /* The last computed norm is stale, recompute */
315: VecZeroEntries(pseudo->xdot);
316: TSComputeIFunction(ts,ts->ptime,ts->vec_sol,pseudo->xdot,pseudo->func,PETSC_FALSE);
317: VecNorm(pseudo->func,NORM_2,&pseudo->fnorm);
318: }
319: PetscViewerASCIIAddTab(viewer,((PetscObject)ts)->tablevel);
320: PetscViewerASCIIPrintf(viewer,"TS %D dt %g time %g fnorm %g\n",step,(double)ts->time_step,(double)ptime,(double)pseudo->fnorm);
321: PetscViewerASCIISubtractTab(viewer,((PetscObject)ts)->tablevel);
322: return(0);
323: }
325: static PetscErrorCode TSSetFromOptions_Pseudo(PetscOptionItems *PetscOptionsObject,TS ts)
326: {
327: TS_Pseudo *pseudo = (TS_Pseudo*)ts->data;
329: PetscBool flg = PETSC_FALSE;
330: PetscViewer viewer;
333: PetscOptionsHead(PetscOptionsObject,"Pseudo-timestepping options");
334: PetscOptionsBool("-ts_monitor_pseudo","Monitor convergence","",flg,&flg,NULL);
335: if (flg) {
336: PetscViewerASCIIOpen(PetscObjectComm((PetscObject)ts),"stdout",&viewer);
337: TSMonitorSet(ts,TSPseudoMonitorDefault,viewer,(PetscErrorCode (*)(void**))PetscViewerDestroy);
338: }
339: flg = pseudo->increment_dt_from_initial_dt;
340: PetscOptionsBool("-ts_pseudo_increment_dt_from_initial_dt","Increase dt as a ratio from original dt","TSPseudoIncrementDtFromInitialDt",flg,&flg,NULL);
341: pseudo->increment_dt_from_initial_dt = flg;
342: PetscOptionsReal("-ts_pseudo_increment","Ratio to increase dt","TSPseudoSetTimeStepIncrement",pseudo->dt_increment,&pseudo->dt_increment,NULL);
343: PetscOptionsReal("-ts_pseudo_max_dt","Maximum value for dt","TSPseudoSetMaxTimeStep",pseudo->dt_max,&pseudo->dt_max,NULL);
344: PetscOptionsReal("-ts_pseudo_fatol","Tolerance for norm of function","",pseudo->fatol,&pseudo->fatol,NULL);
345: PetscOptionsReal("-ts_pseudo_frtol","Relative tolerance for norm of function","",pseudo->frtol,&pseudo->frtol,NULL);
346: PetscOptionsTail();
347: return(0);
348: }
350: static PetscErrorCode TSView_Pseudo(TS ts,PetscViewer viewer)
351: {
353: PetscBool isascii;
356: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);
357: if (isascii) {
358: TS_Pseudo *pseudo = (TS_Pseudo*) ts->data;
359: PetscViewerASCIIPrintf(viewer," frtol - relative tolerance in function value %g\n",(double)pseudo->frtol);
360: PetscViewerASCIIPrintf(viewer," fatol - absolute tolerance in function value %g\n",(double)pseudo->fatol);
361: PetscViewerASCIIPrintf(viewer," dt_initial - initial timestep %g\n",(double)pseudo->dt_initial);
362: PetscViewerASCIIPrintf(viewer," dt_increment - increase in timestep on successful step %g\n",(double)pseudo->dt_increment);
363: PetscViewerASCIIPrintf(viewer," dt_max - maximum time %g\n",(double)pseudo->dt_max);
364: }
365: return(0);
366: }
368: /* ----------------------------------------------------------------------------- */
369: /*@C
370: TSPseudoSetVerifyTimeStep - Sets a user-defined routine to verify the quality of the
371: last timestep.
373: Logically Collective on TS
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 NULL)
381: Level: advanced
383: Calling sequence of func:
384: . func (TS ts,Vec update,void *ctx,PetscReal *newdt,PetscBool *flag);
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
391: Notes:
392: The routine set here will be called by TSPseudoVerifyTimeStep()
393: during the timestepping process.
395: .keywords: timestep, pseudo, set, verify
397: .seealso: TSPseudoVerifyTimeStepDefault(), TSPseudoVerifyTimeStep()
398: @*/
399: PetscErrorCode TSPseudoSetVerifyTimeStep(TS ts,PetscErrorCode (*dt)(TS,Vec,void*,PetscReal*,PetscBool*),void *ctx)
400: {
405: PetscTryMethod(ts,"TSPseudoSetVerifyTimeStep_C",(TS,PetscErrorCode (*)(TS,Vec,void*,PetscReal*,PetscBool*),void*),(ts,dt,ctx));
406: return(0);
407: }
409: /*@
410: TSPseudoSetTimeStepIncrement - Sets the scaling increment applied to
411: dt when using the TSPseudoTimeStepDefault() routine.
413: Logically Collective on TS
415: Input Parameters:
416: + ts - the timestep context
417: - inc - the scaling factor >= 1.0
419: Options Database Key:
420: . -ts_pseudo_increment <increment>
422: Level: advanced
424: .keywords: timestep, pseudo, set, increment
426: .seealso: TSPseudoSetTimeStep(), TSPseudoTimeStepDefault()
427: @*/
428: PetscErrorCode TSPseudoSetTimeStepIncrement(TS ts,PetscReal inc)
429: {
435: PetscTryMethod(ts,"TSPseudoSetTimeStepIncrement_C",(TS,PetscReal),(ts,inc));
436: return(0);
437: }
439: /*@
440: TSPseudoSetMaxTimeStep - Sets the maximum time step
441: when using the TSPseudoTimeStepDefault() routine.
443: Logically Collective on TS
445: Input Parameters:
446: + ts - the timestep context
447: - maxdt - the maximum time step, use a non-positive value to deactivate
449: Options Database Key:
450: . -ts_pseudo_max_dt <increment>
452: Level: advanced
454: .keywords: timestep, pseudo, set
456: .seealso: TSPseudoSetTimeStep(), TSPseudoTimeStepDefault()
457: @*/
458: PetscErrorCode TSPseudoSetMaxTimeStep(TS ts,PetscReal maxdt)
459: {
465: PetscTryMethod(ts,"TSPseudoSetMaxTimeStep_C",(TS,PetscReal),(ts,maxdt));
466: return(0);
467: }
469: /*@
470: TSPseudoIncrementDtFromInitialDt - Indicates that a new timestep
471: is computed via the formula
472: $ dt = initial_dt*initial_fnorm/current_fnorm
473: rather than the default update,
474: $ dt = current_dt*previous_fnorm/current_fnorm.
476: Logically Collective on TS
478: Input Parameter:
479: . ts - the timestep context
481: Options Database Key:
482: . -ts_pseudo_increment_dt_from_initial_dt
484: Level: advanced
486: .keywords: timestep, pseudo, set, increment
488: .seealso: TSPseudoSetTimeStep(), TSPseudoTimeStepDefault()
489: @*/
490: PetscErrorCode TSPseudoIncrementDtFromInitialDt(TS ts)
491: {
496: PetscTryMethod(ts,"TSPseudoIncrementDtFromInitialDt_C",(TS),(ts));
497: return(0);
498: }
501: /*@C
502: TSPseudoSetTimeStep - Sets the user-defined routine to be
503: called at each pseudo-timestep to update the timestep.
505: Logically Collective on TS
507: Input Parameters:
508: + ts - timestep context
509: . dt - function to compute timestep
510: - ctx - [optional] user-defined context for private data
511: required by the function (may be NULL)
513: Level: intermediate
515: Calling sequence of func:
516: . func (TS ts,PetscReal *newdt,void *ctx);
518: . newdt - the newly computed timestep
519: . ctx - [optional] timestep context
521: Notes:
522: The routine set here will be called by TSPseudoComputeTimeStep()
523: during the timestepping process.
524: If not set then TSPseudoTimeStepDefault() is automatically used
526: .keywords: timestep, pseudo, set
528: .seealso: TSPseudoTimeStepDefault(), TSPseudoComputeTimeStep()
529: @*/
530: PetscErrorCode TSPseudoSetTimeStep(TS ts,PetscErrorCode (*dt)(TS,PetscReal*,void*),void *ctx)
531: {
536: PetscTryMethod(ts,"TSPseudoSetTimeStep_C",(TS,PetscErrorCode (*)(TS,PetscReal*,void*),void*),(ts,dt,ctx));
537: return(0);
538: }
540: /* ----------------------------------------------------------------------------- */
542: typedef PetscErrorCode (*FCN1)(TS,Vec,void*,PetscReal*,PetscBool*); /* force argument to next function to not be extern C*/
543: static PetscErrorCode TSPseudoSetVerifyTimeStep_Pseudo(TS ts,FCN1 dt,void *ctx)
544: {
545: TS_Pseudo *pseudo = (TS_Pseudo*)ts->data;
548: pseudo->verify = dt;
549: pseudo->verifyctx = ctx;
550: return(0);
551: }
553: static PetscErrorCode TSPseudoSetTimeStepIncrement_Pseudo(TS ts,PetscReal inc)
554: {
555: TS_Pseudo *pseudo = (TS_Pseudo*)ts->data;
558: pseudo->dt_increment = inc;
559: return(0);
560: }
562: static PetscErrorCode TSPseudoSetMaxTimeStep_Pseudo(TS ts,PetscReal maxdt)
563: {
564: TS_Pseudo *pseudo = (TS_Pseudo*)ts->data;
567: pseudo->dt_max = maxdt;
568: return(0);
569: }
571: static PetscErrorCode TSPseudoIncrementDtFromInitialDt_Pseudo(TS ts)
572: {
573: TS_Pseudo *pseudo = (TS_Pseudo*)ts->data;
576: pseudo->increment_dt_from_initial_dt = PETSC_TRUE;
577: return(0);
578: }
580: typedef PetscErrorCode (*FCN2)(TS,PetscReal*,void*); /* force argument to next function to not be extern C*/
581: static PetscErrorCode TSPseudoSetTimeStep_Pseudo(TS ts,FCN2 dt,void *ctx)
582: {
583: TS_Pseudo *pseudo = (TS_Pseudo*)ts->data;
586: pseudo->dt = dt;
587: pseudo->dtctx = ctx;
588: return(0);
589: }
591: /* ----------------------------------------------------------------------------- */
592: /*MC
593: TSPSEUDO - Solve steady state ODE and DAE problems with pseudo time stepping
595: This method solves equations of the form
597: $ F(X,Xdot) = 0
599: for steady state using the iteration
601: $ [G'] S = -F(X,0)
602: $ X += S
604: where
606: $ G(Y) = F(Y,(Y-X)/dt)
608: This is linearly-implicit Euler with the residual always evaluated "at steady
609: state". See note below.
611: Options database keys:
612: + -ts_pseudo_increment <real> - ratio of increase dt
613: . -ts_pseudo_increment_dt_from_initial_dt <truth> - Increase dt as a ratio from original dt
614: . -ts_pseudo_fatol <atol> - stop iterating when the function norm is less than atol
615: - -ts_pseudo_frtol <rtol> - stop iterating when the function norm divided by the initial function norm is less than rtol
617: Level: beginner
619: References:
620: + 1. - Todd S. Coffey and C. T. Kelley and David E. Keyes, Pseudotransient Continuation and Differential Algebraic Equations, 2003.
621: - 2. - C. T. Kelley and David E. Keyes, Convergence analysis of Pseudotransient Continuation, 1998.
623: Notes:
624: The residual computed by this method includes the transient term (Xdot is computed instead of
625: always being zero), but since the prediction from the last step is always the solution from the
626: last step, on the first Newton iteration we have
628: $ Xdot = (Xpredicted - Xold)/dt = (Xold-Xold)/dt = 0
630: Therefore, the linear system solved by the first Newton iteration is equivalent to the one
631: described above and in the papers. If the user chooses to perform multiple Newton iterations, the
632: algorithm is no longer the one described in the referenced papers.
634: .seealso: TSCreate(), TS, TSSetType()
636: M*/
637: PETSC_EXTERN PetscErrorCode TSCreate_Pseudo(TS ts)
638: {
639: TS_Pseudo *pseudo;
641: SNES snes;
642: SNESType stype;
645: ts->ops->reset = TSReset_Pseudo;
646: ts->ops->destroy = TSDestroy_Pseudo;
647: ts->ops->view = TSView_Pseudo;
648: ts->ops->setup = TSSetUp_Pseudo;
649: ts->ops->step = TSStep_Pseudo;
650: ts->ops->setfromoptions = TSSetFromOptions_Pseudo;
651: ts->ops->snesfunction = SNESTSFormFunction_Pseudo;
652: ts->ops->snesjacobian = SNESTSFormJacobian_Pseudo;
653: ts->default_adapt_type = TSADAPTNONE;
654: ts->usessnes = PETSC_TRUE;
656: TSGetSNES(ts,&snes);
657: SNESGetType(snes,&stype);
658: if (!stype) {SNESSetType(snes,SNESKSPONLY);}
660: PetscNewLog(ts,&pseudo);
661: ts->data = (void*)pseudo;
663: pseudo->dt = TSPseudoTimeStepDefault;
664: pseudo->dtctx = NULL;
665: pseudo->dt_increment = 1.1;
666: pseudo->increment_dt_from_initial_dt = PETSC_FALSE;
667: pseudo->fnorm = -1;
668: pseudo->fnorm_initial = -1;
669: pseudo->fnorm_previous = -1;
670: #if defined(PETSC_USE_REAL_SINGLE)
671: pseudo->fatol = 1.e-25;
672: pseudo->frtol = 1.e-5;
673: #else
674: pseudo->fatol = 1.e-50;
675: pseudo->frtol = 1.e-12;
676: #endif
677: PetscObjectComposeFunction((PetscObject)ts,"TSPseudoSetVerifyTimeStep_C",TSPseudoSetVerifyTimeStep_Pseudo);
678: PetscObjectComposeFunction((PetscObject)ts,"TSPseudoSetTimeStepIncrement_C",TSPseudoSetTimeStepIncrement_Pseudo);
679: PetscObjectComposeFunction((PetscObject)ts,"TSPseudoSetMaxTimeStep_C",TSPseudoSetMaxTimeStep_Pseudo);
680: PetscObjectComposeFunction((PetscObject)ts,"TSPseudoIncrementDtFromInitialDt_C",TSPseudoIncrementDtFromInitialDt_Pseudo);
681: PetscObjectComposeFunction((PetscObject)ts,"TSPseudoSetTimeStep_C",TSPseudoSetTimeStep_Pseudo);
682: return(0);
683: }
685: /*@C
686: TSPseudoTimeStepDefault - Default code to compute pseudo-timestepping.
687: Use with TSPseudoSetTimeStep().
689: Collective on TS
691: Input Parameters:
692: . ts - the timestep context
693: . dtctx - unused timestep context
695: Output Parameter:
696: . newdt - the timestep to use for the next step
698: Level: advanced
700: .keywords: timestep, pseudo, default
702: .seealso: TSPseudoSetTimeStep(), TSPseudoComputeTimeStep()
703: @*/
704: PetscErrorCode TSPseudoTimeStepDefault(TS ts,PetscReal *newdt,void *dtctx)
705: {
706: TS_Pseudo *pseudo = (TS_Pseudo*)ts->data;
707: PetscReal inc = pseudo->dt_increment;
711: VecZeroEntries(pseudo->xdot);
712: TSComputeIFunction(ts,ts->ptime,ts->vec_sol,pseudo->xdot,pseudo->func,PETSC_FALSE);
713: VecNorm(pseudo->func,NORM_2,&pseudo->fnorm);
714: if (pseudo->fnorm_initial < 0) {
715: /* first time through so compute initial function norm */
716: pseudo->fnorm_initial = pseudo->fnorm;
717: pseudo->fnorm_previous = pseudo->fnorm;
718: }
719: if (pseudo->fnorm == 0.0) *newdt = 1.e12*inc*ts->time_step;
720: else if (pseudo->increment_dt_from_initial_dt) *newdt = inc*pseudo->dt_initial*pseudo->fnorm_initial/pseudo->fnorm;
721: else *newdt = inc*ts->time_step*pseudo->fnorm_previous/pseudo->fnorm;
722: if (pseudo->dt_max > 0) *newdt = PetscMin(*newdt,pseudo->dt_max);
723: pseudo->fnorm_previous = pseudo->fnorm;
724: return(0);
725: }