Actual source code: ts.c
2: #include <private/tsimpl.h> /*I "petscts.h" I*/
4: /* Logging support */
5: PetscClassId TS_CLASSID;
6: PetscLogEvent TS_Step, TS_PseudoComputeTimeStep, TS_FunctionEval, TS_JacobianEval;
10: /*
11: TSSetTypeFromOptions - Sets the type of ts from user options.
13: Collective on TS
15: Input Parameter:
16: . ts - The ts
18: Level: intermediate
20: .keywords: TS, set, options, database, type
21: .seealso: TSSetFromOptions(), TSSetType()
22: */
23: static PetscErrorCode TSSetTypeFromOptions(TS ts)
24: {
25: PetscBool opt;
26: const char *defaultType;
27: char typeName[256];
31: if (((PetscObject)ts)->type_name) {
32: defaultType = ((PetscObject)ts)->type_name;
33: } else {
34: defaultType = TSEULER;
35: }
37: if (!TSRegisterAllCalled) {TSRegisterAll(PETSC_NULL);}
38: PetscOptionsList("-ts_type", "TS method"," TSSetType", TSList, defaultType, typeName, 256, &opt);
39: if (opt) {
40: TSSetType(ts, typeName);
41: } else {
42: TSSetType(ts, defaultType);
43: }
44: return(0);
45: }
49: /*@
50: TSSetFromOptions - Sets various TS parameters from user options.
52: Collective on TS
54: Input Parameter:
55: . ts - the TS context obtained from TSCreate()
57: Options Database Keys:
58: + -ts_type <type> - TSEULER, TSBEULER, TSSUNDIALS, TSPSEUDO, TSCN, TSRK, TSTHETA, TSGL, TSSSP
59: . -ts_max_steps maxsteps - maximum number of time-steps to take
60: . -ts_max_time time - maximum time to compute to
61: . -ts_dt dt - initial time step
62: . -ts_monitor - print information at each timestep
63: - -ts_monitor_draw - plot information at each timestep
65: Level: beginner
67: .keywords: TS, timestep, set, options, database
69: .seealso: TSGetType()
70: @*/
71: PetscErrorCode TSSetFromOptions(TS ts)
72: {
73: PetscBool opt,flg;
75: PetscViewer monviewer;
76: char monfilename[PETSC_MAX_PATH_LEN];
77: SNES snes;
81: PetscObjectOptionsBegin((PetscObject)ts);
82: /* Handle TS type options */
83: TSSetTypeFromOptions(ts);
85: /* Handle generic TS options */
86: PetscOptionsInt("-ts_max_steps","Maximum number of time steps","TSSetDuration",ts->max_steps,&ts->max_steps,PETSC_NULL);
87: PetscOptionsReal("-ts_max_time","Time to run to","TSSetDuration",ts->max_time,&ts->max_time,PETSC_NULL);
88: PetscOptionsReal("-ts_init_time","Initial time","TSSetTime",ts->ptime,&ts->ptime,PETSC_NULL);
89: PetscOptionsReal("-ts_dt","Initial time step","TSSetTimeStep",ts->time_step,&ts->time_step,PETSC_NULL);
90: opt = ts->exact_final_time == PETSC_DECIDE ? PETSC_FALSE : (PetscBool)ts->exact_final_time;
91: PetscOptionsBool("-ts_exact_final_time","Interpolate output to stop exactly at the final time","TSSetExactFinalTime",opt,&opt,&flg);
92: if (flg) {TSSetExactFinalTime(ts,opt);}
93: PetscOptionsInt("-ts_max_snes_failures","Maximum number of nonlinear solve failures","",ts->max_snes_failures,&ts->max_snes_failures,PETSC_NULL);
94: PetscOptionsInt("-ts_max_reject","Maximum number of step rejections","",ts->max_reject,&ts->max_reject,PETSC_NULL);
95: PetscOptionsBool("-ts_error_if_step_failed","Error if no step succeeds","",ts->errorifstepfailed,&ts->errorifstepfailed,PETSC_NULL);
97: /* Monitor options */
98: PetscOptionsString("-ts_monitor","Monitor timestep size","TSMonitorDefault","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);
99: if (flg) {
100: PetscViewerASCIIOpen(((PetscObject)ts)->comm,monfilename,&monviewer);
101: TSMonitorSet(ts,TSMonitorDefault,monviewer,(PetscErrorCode (*)(void**))PetscViewerDestroy);
102: }
103: PetscOptionsString("-ts_monitor_python","Use Python function","TSMonitorSet",0,monfilename,PETSC_MAX_PATH_LEN,&flg);
104: if (flg) {PetscPythonMonitorSet((PetscObject)ts,monfilename);}
106: opt = PETSC_FALSE;
107: PetscOptionsBool("-ts_monitor_draw","Monitor timestep size graphically","TSMonitorLG",opt,&opt,PETSC_NULL);
108: if (opt) {
109: TSMonitorSet(ts,TSMonitorLG,PETSC_NULL,PETSC_NULL);
110: }
111: opt = PETSC_FALSE;
112: PetscOptionsBool("-ts_monitor_solution","Monitor solution graphically","TSMonitorSolution",opt,&opt,PETSC_NULL);
113: if (opt) {
114: void *ctx;
115: TSMonitorSolutionCreate(ts,PETSC_NULL,&ctx);
116: TSMonitorSet(ts,TSMonitorSolution,ctx,TSMonitorSolutionDestroy);
117: }
119: TSGetSNES(ts,&snes);
120: if (ts->problem_type == TS_LINEAR) {SNESSetType(snes,SNESKSPONLY);}
122: /* Handle specific TS options */
123: if (ts->ops->setfromoptions) {
124: (*ts->ops->setfromoptions)(ts);
125: }
127: /* process any options handlers added with PetscObjectAddOptionsHandler() */
128: PetscObjectProcessOptionsHandlers((PetscObject)ts);
129: PetscOptionsEnd();
130: return(0);
131: }
136: /*@
137: TSComputeRHSJacobian - Computes the Jacobian matrix that has been
138: set with TSSetRHSJacobian().
140: Collective on TS and Vec
142: Input Parameters:
143: + ts - the TS context
144: . t - current timestep
145: - x - input vector
147: Output Parameters:
148: + A - Jacobian matrix
149: . B - optional preconditioning matrix
150: - flag - flag indicating matrix structure
152: Notes:
153: Most users should not need to explicitly call this routine, as it
154: is used internally within the nonlinear solvers.
156: See KSPSetOperators() for important information about setting the
157: flag parameter.
159: Level: developer
161: .keywords: SNES, compute, Jacobian, matrix
163: .seealso: TSSetRHSJacobian(), KSPSetOperators()
164: @*/
165: PetscErrorCode TSComputeRHSJacobian(TS ts,PetscReal t,Vec X,Mat *A,Mat *B,MatStructure *flg)
166: {
168: PetscInt Xstate;
174: PetscObjectStateQuery((PetscObject)X,&Xstate);
175: if (ts->rhsjacobian.time == t && (ts->problem_type == TS_LINEAR || (ts->rhsjacobian.X == X && ts->rhsjacobian.Xstate == Xstate))) {
176: *flg = ts->rhsjacobian.mstructure;
177: return(0);
178: }
180: if (!ts->userops->rhsjacobian && !ts->userops->ijacobian) SETERRQ(((PetscObject)ts)->comm,PETSC_ERR_USER,"Must call TSSetRHSJacobian() and / or TSSetIJacobian()");
182: if (ts->userops->rhsjacobian) {
183: PetscLogEventBegin(TS_JacobianEval,ts,X,*A,*B);
184: *flg = DIFFERENT_NONZERO_PATTERN;
185: PetscStackPush("TS user Jacobian function");
186: (*ts->userops->rhsjacobian)(ts,t,X,A,B,flg,ts->jacP);
187: PetscStackPop;
188: PetscLogEventEnd(TS_JacobianEval,ts,X,*A,*B);
189: /* make sure user returned a correct Jacobian and preconditioner */
192: } else {
193: MatZeroEntries(*A);
194: if (*A != *B) {MatZeroEntries(*B);}
195: *flg = SAME_NONZERO_PATTERN;
196: }
197: ts->rhsjacobian.time = t;
198: ts->rhsjacobian.X = X;
199: PetscObjectStateQuery((PetscObject)X,&ts->rhsjacobian.Xstate);
200: ts->rhsjacobian.mstructure = *flg;
201: return(0);
202: }
206: /*@
207: TSComputeRHSFunction - Evaluates the right-hand-side function.
209: Collective on TS and Vec
211: Input Parameters:
212: + ts - the TS context
213: . t - current time
214: - x - state vector
216: Output Parameter:
217: . y - right hand side
219: Note:
220: Most users should not need to explicitly call this routine, as it
221: is used internally within the nonlinear solvers.
223: Level: developer
225: .keywords: TS, compute
227: .seealso: TSSetRHSFunction(), TSComputeIFunction()
228: @*/
229: PetscErrorCode TSComputeRHSFunction(TS ts,PetscReal t,Vec x,Vec y)
230: {
238: if (!ts->userops->rhsfunction && !ts->userops->ifunction) SETERRQ(((PetscObject)ts)->comm,PETSC_ERR_USER,"Must call TSSetRHSFunction() and / or TSSetIFunction()");
240: PetscLogEventBegin(TS_FunctionEval,ts,x,y,0);
241: if (ts->userops->rhsfunction) {
242: PetscStackPush("TS user right-hand-side function");
243: (*ts->userops->rhsfunction)(ts,t,x,y,ts->funP);
244: PetscStackPop;
245: } else {
246: VecZeroEntries(y);
247: }
249: PetscLogEventEnd(TS_FunctionEval,ts,x,y,0);
250: return(0);
251: }
255: static PetscErrorCode TSGetRHSVec_Private(TS ts,Vec *Frhs)
256: {
257: Vec F;
261: *Frhs = PETSC_NULL;
262: TSGetIFunction(ts,&F,PETSC_NULL,PETSC_NULL);
263: if (!ts->Frhs) {
264: VecDuplicate(F,&ts->Frhs);
265: }
266: *Frhs = ts->Frhs;
267: return(0);
268: }
272: static PetscErrorCode TSGetRHSMats_Private(TS ts,Mat *Arhs,Mat *Brhs)
273: {
274: Mat A,B;
278: TSGetIJacobian(ts,&A,&B,PETSC_NULL,PETSC_NULL);
279: if (Arhs) {
280: if (!ts->Arhs) {
281: MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,&ts->Arhs);
282: }
283: *Arhs = ts->Arhs;
284: }
285: if (Brhs) {
286: if (!ts->Brhs) {
287: MatDuplicate(B,MAT_DO_NOT_COPY_VALUES,&ts->Brhs);
288: }
289: *Brhs = ts->Brhs;
290: }
291: return(0);
292: }
296: /*@
297: TSComputeIFunction - Evaluates the DAE residual written in implicit form F(t,X,Xdot)=0
299: Collective on TS and Vec
301: Input Parameters:
302: + ts - the TS context
303: . t - current time
304: . X - state vector
305: . Xdot - time derivative of state vector
306: - imex - flag indicates if the method is IMEX so that the RHSFunction should be kept separate
308: Output Parameter:
309: . Y - right hand side
311: Note:
312: Most users should not need to explicitly call this routine, as it
313: is used internally within the nonlinear solvers.
315: If the user did did not write their equations in implicit form, this
316: function recasts them in implicit form.
318: Level: developer
320: .keywords: TS, compute
322: .seealso: TSSetIFunction(), TSComputeRHSFunction()
323: @*/
324: PetscErrorCode TSComputeIFunction(TS ts,PetscReal t,Vec X,Vec Xdot,Vec Y,PetscBool imex)
325: {
334: if (!ts->userops->rhsfunction && !ts->userops->ifunction) SETERRQ(((PetscObject)ts)->comm,PETSC_ERR_USER,"Must call TSSetRHSFunction() and / or TSSetIFunction()");
336: PetscLogEventBegin(TS_FunctionEval,ts,X,Xdot,Y);
337: if (ts->userops->ifunction) {
338: PetscStackPush("TS user implicit function");
339: (*ts->userops->ifunction)(ts,t,X,Xdot,Y,ts->funP);
340: PetscStackPop;
341: }
342: if (imex) {
343: if (!ts->userops->ifunction) {
344: VecCopy(Xdot,Y);
345: }
346: } else if (ts->userops->rhsfunction) {
347: if (ts->userops->ifunction) {
348: Vec Frhs;
349: TSGetRHSVec_Private(ts,&Frhs);
350: TSComputeRHSFunction(ts,t,X,Frhs);
351: VecAXPY(Y,-1,Frhs);
352: } else {
353: TSComputeRHSFunction(ts,t,X,Y);
354: VecAYPX(Y,-1,Xdot);
355: }
356: }
357: PetscLogEventEnd(TS_FunctionEval,ts,X,Xdot,Y);
358: return(0);
359: }
363: /*@
364: TSComputeIJacobian - Evaluates the Jacobian of the DAE
366: Collective on TS and Vec
368: Input
369: Input Parameters:
370: + ts - the TS context
371: . t - current timestep
372: . X - state vector
373: . Xdot - time derivative of state vector
374: . shift - shift to apply, see note below
375: - imex - flag indicates if the method is IMEX so that the RHSJacobian should be kept separate
377: Output Parameters:
378: + A - Jacobian matrix
379: . B - optional preconditioning matrix
380: - flag - flag indicating matrix structure
382: Notes:
383: If F(t,X,Xdot)=0 is the DAE, the required Jacobian is
385: dF/dX + shift*dF/dXdot
387: Most users should not need to explicitly call this routine, as it
388: is used internally within the nonlinear solvers.
390: Level: developer
392: .keywords: TS, compute, Jacobian, matrix
394: .seealso: TSSetIJacobian()
395: @*/
396: PetscErrorCode TSComputeIJacobian(TS ts,PetscReal t,Vec X,Vec Xdot,PetscReal shift,Mat *A,Mat *B,MatStructure *flg,PetscBool imex)
397: {
398: PetscInt Xstate, Xdotstate;
410: PetscObjectStateQuery((PetscObject)X,&Xstate);
411: PetscObjectStateQuery((PetscObject)Xdot,&Xdotstate);
412: if (ts->ijacobian.time == t && (ts->problem_type == TS_LINEAR || (ts->ijacobian.X == X && ts->ijacobian.Xstate == Xstate && ts->ijacobian.Xdot == Xdot && ts->ijacobian.Xdotstate == Xdotstate && ts->ijacobian.imex == imex))) {
413: *flg = ts->ijacobian.mstructure;
414: MatScale(*A, shift / ts->ijacobian.shift);
415: return(0);
416: }
418: if (!ts->userops->rhsjacobian && !ts->userops->ijacobian) SETERRQ(((PetscObject)ts)->comm,PETSC_ERR_USER,"Must call TSSetRHSJacobian() and / or TSSetIJacobian()");
420: *flg = SAME_NONZERO_PATTERN; /* In case we're solving a linear problem in which case it wouldn't get initialized below. */
421: PetscLogEventBegin(TS_JacobianEval,ts,X,*A,*B);
422: if (ts->userops->ijacobian) {
423: *flg = DIFFERENT_NONZERO_PATTERN;
424: PetscStackPush("TS user implicit Jacobian");
425: (*ts->userops->ijacobian)(ts,t,X,Xdot,shift,A,B,flg,ts->jacP);
426: PetscStackPop;
427: /* make sure user returned a correct Jacobian and preconditioner */
430: }
431: if (imex) {
432: if (!ts->userops->ijacobian) { /* system was written as Xdot = F(t,X) */
433: MatZeroEntries(*A);
434: MatShift(*A,shift);
435: if (*A != *B) {
436: MatZeroEntries(*B);
437: MatShift(*B,shift);
438: }
439: *flg = SAME_PRECONDITIONER;
440: }
441: } else {
442: if (!ts->userops->ijacobian) {
443: TSComputeRHSJacobian(ts,t,X,A,B,flg);
444: MatScale(*A,-1);
445: MatShift(*A,shift);
446: if (*A != *B) {
447: MatScale(*B,-1);
448: MatShift(*B,shift);
449: }
450: } else if (ts->userops->rhsjacobian) {
451: Mat Arhs,Brhs;
452: MatStructure axpy,flg2 = DIFFERENT_NONZERO_PATTERN;
453: TSGetRHSMats_Private(ts,&Arhs,&Brhs);
454: TSComputeRHSJacobian(ts,t,X,&Arhs,&Brhs,&flg2);
455: axpy = (*flg == flg2) ? SAME_NONZERO_PATTERN : DIFFERENT_NONZERO_PATTERN;
456: MatAXPY(*A,-1,Arhs,axpy);
457: if (*A != *B) {
458: MatAXPY(*B,-1,Brhs,axpy);
459: }
460: *flg = PetscMin(*flg,flg2);
461: }
462: }
464: ts->ijacobian.time = t;
465: ts->ijacobian.X = X;
466: ts->ijacobian.Xdot = Xdot;
467: PetscObjectStateQuery((PetscObject)X,&ts->ijacobian.Xstate);
468: PetscObjectStateQuery((PetscObject)Xdot,&ts->ijacobian.Xdotstate);
469: ts->ijacobian.shift = shift;
470: ts->ijacobian.imex = imex;
471: ts->ijacobian.mstructure = *flg;
472: PetscLogEventEnd(TS_JacobianEval,ts,X,*A,*B);
473: return(0);
474: }
478: /*@C
479: TSSetRHSFunction - Sets the routine for evaluating the function,
480: F(t,u), where U_t = F(t,u).
482: Logically Collective on TS
484: Input Parameters:
485: + ts - the TS context obtained from TSCreate()
486: . r - vector to put the computed right hand side (or PETSC_NULL to have it created)
487: . f - routine for evaluating the right-hand-side function
488: - ctx - [optional] user-defined context for private data for the
489: function evaluation routine (may be PETSC_NULL)
491: Calling sequence of func:
492: $ func (TS ts,PetscReal t,Vec u,Vec F,void *ctx);
494: + t - current timestep
495: . u - input vector
496: . F - function vector
497: - ctx - [optional] user-defined function context
499: Important:
500: The user MUST call either this routine or TSSetMatrices().
502: Level: beginner
504: .keywords: TS, timestep, set, right-hand-side, function
506: .seealso: TSSetMatrices()
507: @*/
508: PetscErrorCode TSSetRHSFunction(TS ts,Vec r,PetscErrorCode (*f)(TS,PetscReal,Vec,Vec,void*),void *ctx)
509: {
511: SNES snes;
516: if (f) ts->userops->rhsfunction = f;
517: if (ctx) ts->funP = ctx;
518: TSGetSNES(ts,&snes);
519: SNESSetFunction(snes,r,SNESTSFormFunction,ts);
520: return(0);
521: }
525: /*@C
526: TSSetRHSJacobian - Sets the function to compute the Jacobian of F,
527: where U_t = F(U,t), as well as the location to store the matrix.
528: Use TSSetMatrices() for linear problems.
530: Logically Collective on TS
532: Input Parameters:
533: + ts - the TS context obtained from TSCreate()
534: . A - Jacobian matrix
535: . B - preconditioner matrix (usually same as A)
536: . f - the Jacobian evaluation routine
537: - ctx - [optional] user-defined context for private data for the
538: Jacobian evaluation routine (may be PETSC_NULL)
540: Calling sequence of func:
541: $ func (TS ts,PetscReal t,Vec u,Mat *A,Mat *B,MatStructure *flag,void *ctx);
543: + t - current timestep
544: . u - input vector
545: . A - matrix A, where U_t = A(t)u
546: . B - preconditioner matrix, usually the same as A
547: . flag - flag indicating information about the preconditioner matrix
548: structure (same as flag in KSPSetOperators())
549: - ctx - [optional] user-defined context for matrix evaluation routine
551: Notes:
552: See KSPSetOperators() for important information about setting the flag
553: output parameter in the routine func(). Be sure to read this information!
555: The routine func() takes Mat * as the matrix arguments rather than Mat.
556: This allows the matrix evaluation routine to replace A and/or B with a
557: completely new matrix structure (not just different matrix elements)
558: when appropriate, for instance, if the nonzero structure is changing
559: throughout the global iterations.
561: Level: beginner
562:
563: .keywords: TS, timestep, set, right-hand-side, Jacobian
565: .seealso: TSDefaultComputeJacobianColor(),
566: SNESDefaultComputeJacobianColor(), TSSetRHSFunction(), TSSetMatrices()
568: @*/
569: PetscErrorCode TSSetRHSJacobian(TS ts,Mat A,Mat B,TSRHSJacobian f,void *ctx)
570: {
572: SNES snes;
581: if (f) ts->userops->rhsjacobian = f;
582: if (ctx) ts->jacP = ctx;
583: TSGetSNES(ts,&snes);
584: if (!ts->userops->ijacobian) {
585: SNESSetJacobian(snes,A,B,SNESTSFormJacobian,ts);
586: }
587: if (A) {
588: PetscObjectReference((PetscObject)A);
589: MatDestroy(&ts->Arhs);
590: ts->Arhs = A;
591: }
592: if (B) {
593: PetscObjectReference((PetscObject)B);
594: MatDestroy(&ts->Brhs);
595: ts->Brhs = B;
596: }
597: return(0);
598: }
603: /*@C
604: TSSetIFunction - Set the function to compute F(t,U,U_t) where F = 0 is the DAE to be solved.
606: Logically Collective on TS
608: Input Parameters:
609: + ts - the TS context obtained from TSCreate()
610: . r - vector to hold the residual (or PETSC_NULL to have it created internally)
611: . f - the function evaluation routine
612: - ctx - user-defined context for private data for the function evaluation routine (may be PETSC_NULL)
614: Calling sequence of f:
615: $ f(TS ts,PetscReal t,Vec u,Vec u_t,Vec F,ctx);
617: + t - time at step/stage being solved
618: . u - state vector
619: . u_t - time derivative of state vector
620: . F - function vector
621: - ctx - [optional] user-defined context for matrix evaluation routine
623: Important:
624: The user MUST call either this routine, TSSetRHSFunction(), or TSSetMatrices(). This routine must be used when not solving an ODE.
626: Level: beginner
628: .keywords: TS, timestep, set, DAE, Jacobian
630: .seealso: TSSetMatrices(), TSSetRHSFunction(), TSSetIJacobian()
631: @*/
632: PetscErrorCode TSSetIFunction(TS ts,Vec res,TSIFunction f,void *ctx)
633: {
635: SNES snes;
640: if (f) ts->userops->ifunction = f;
641: if (ctx) ts->funP = ctx;
642: TSGetSNES(ts,&snes);
643: SNESSetFunction(snes,res,SNESTSFormFunction,ts);
644: return(0);
645: }
649: /*@C
650: TSGetIFunction - Returns the vector where the implicit residual is stored and the function/contex to compute it.
652: Not Collective
654: Input Parameter:
655: . ts - the TS context
657: Output Parameter:
658: + r - vector to hold residual (or PETSC_NULL)
659: . func - the function to compute residual (or PETSC_NULL)
660: - ctx - the function context (or PETSC_NULL)
662: Level: advanced
664: .keywords: TS, nonlinear, get, function
666: .seealso: TSSetIFunction(), SNESGetFunction()
667: @*/
668: PetscErrorCode TSGetIFunction(TS ts,Vec *r,TSIFunction *func,void **ctx)
669: {
671: SNES snes;
675: TSGetSNES(ts,&snes);
676: SNESGetFunction(snes,r,PETSC_NULL,PETSC_NULL);
677: if (func) *func = ts->userops->ifunction;
678: if (ctx) *ctx = ts->funP;
679: return(0);
680: }
684: /*@C
685: TSGetRHSFunction - Returns the vector where the right hand side is stored and the function/context to compute it.
687: Not Collective
689: Input Parameter:
690: . ts - the TS context
692: Output Parameter:
693: + r - vector to hold computed right hand side (or PETSC_NULL)
694: . func - the function to compute right hand side (or PETSC_NULL)
695: - ctx - the function context (or PETSC_NULL)
697: Level: advanced
699: .keywords: TS, nonlinear, get, function
701: .seealso: TSSetRhsfunction(), SNESGetFunction()
702: @*/
703: PetscErrorCode TSGetRHSFunction(TS ts,Vec *r,TSRHSFunction *func,void **ctx)
704: {
706: SNES snes;
710: TSGetSNES(ts,&snes);
711: SNESGetFunction(snes,r,PETSC_NULL,PETSC_NULL);
712: if (func) *func = ts->userops->rhsfunction;
713: if (ctx) *ctx = ts->funP;
714: return(0);
715: }
719: /*@C
720: TSSetIJacobian - Set the function to compute the matrix dF/dU + a*dF/dU_t where F(t,U,U_t) is the function
721: you provided with TSSetIFunction().
723: Logically Collective on TS
725: Input Parameters:
726: + ts - the TS context obtained from TSCreate()
727: . A - Jacobian matrix
728: . B - preconditioning matrix for A (may be same as A)
729: . f - the Jacobian evaluation routine
730: - ctx - user-defined context for private data for the Jacobian evaluation routine (may be PETSC_NULL)
732: Calling sequence of f:
733: $ f(TS ts,PetscReal t,Vec U,Vec U_t,PetscReal a,Mat *A,Mat *B,MatStructure *flag,void *ctx);
735: + t - time at step/stage being solved
736: . U - state vector
737: . U_t - time derivative of state vector
738: . a - shift
739: . A - Jacobian of G(U) = F(t,U,W+a*U), equivalent to dF/dU + a*dF/dU_t
740: . B - preconditioning matrix for A, may be same as A
741: . flag - flag indicating information about the preconditioner matrix
742: structure (same as flag in KSPSetOperators())
743: - ctx - [optional] user-defined context for matrix evaluation routine
745: Notes:
746: The matrices A and B are exactly the matrices that are used by SNES for the nonlinear solve.
748: The matrix dF/dU + a*dF/dU_t you provide turns out to be
749: the Jacobian of G(U) = F(t,U,W+a*U) where F(t,U,U_t) = 0 is the DAE to be solved.
750: The time integrator internally approximates U_t by W+a*U where the positive "shift"
751: a and vector W depend on the integration method, step size, and past states. For example with
752: the backward Euler method a = 1/dt and W = -a*U(previous timestep) so
753: W + a*U = a*(U - U(previous timestep)) = (U - U(previous timestep))/dt
755: Level: beginner
757: .keywords: TS, timestep, DAE, Jacobian
759: .seealso: TSSetIFunction(), TSSetRHSJacobian()
761: @*/
762: PetscErrorCode TSSetIJacobian(TS ts,Mat A,Mat B,TSIJacobian f,void *ctx)
763: {
765: SNES snes;
773: if (f) ts->userops->ijacobian = f;
774: if (ctx) ts->jacP = ctx;
775: TSGetSNES(ts,&snes);
776: SNESSetJacobian(snes,A,B,SNESTSFormJacobian,ts);
777: return(0);
778: }
782: /*@C
783: TSView - Prints the TS data structure.
785: Collective on TS
787: Input Parameters:
788: + ts - the TS context obtained from TSCreate()
789: - viewer - visualization context
791: Options Database Key:
792: . -ts_view - calls TSView() at end of TSStep()
794: Notes:
795: The available visualization contexts include
796: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
797: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
798: output where only the first processor opens
799: the file. All other processors send their
800: data to the first processor to print.
802: The user can open an alternative visualization context with
803: PetscViewerASCIIOpen() - output to a specified file.
805: Level: beginner
807: .keywords: TS, timestep, view
809: .seealso: PetscViewerASCIIOpen()
810: @*/
811: PetscErrorCode TSView(TS ts,PetscViewer viewer)
812: {
814: const TSType type;
815: PetscBool iascii,isstring,isundials;
819: if (!viewer) {
820: PetscViewerASCIIGetStdout(((PetscObject)ts)->comm,&viewer);
821: }
825: PetscTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
826: PetscTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);
827: if (iascii) {
828: PetscObjectPrintClassNamePrefixType((PetscObject)ts,viewer,"TS Object");
829: PetscViewerASCIIPrintf(viewer," maximum steps=%D\n",ts->max_steps);
830: PetscViewerASCIIPrintf(viewer," maximum time=%G\n",ts->max_time);
831: if (ts->problem_type == TS_NONLINEAR) {
832: PetscViewerASCIIPrintf(viewer," total number of nonlinear solver iterations=%D\n",ts->nonlinear_its);
833: PetscViewerASCIIPrintf(viewer," total number of nonlinear solve failures=%D\n",ts->num_snes_failures);
834: }
835: PetscViewerASCIIPrintf(viewer," total number of linear solver iterations=%D\n",ts->linear_its);
836: PetscViewerASCIIPrintf(viewer," total number of rejected steps=%D\n",ts->reject);
837: if (ts->ops->view) {
838: PetscViewerASCIIPushTab(viewer);
839: (*ts->ops->view)(ts,viewer);
840: PetscViewerASCIIPopTab(viewer);
841: }
842: } else if (isstring) {
843: TSGetType(ts,&type);
844: PetscViewerStringSPrintf(viewer," %-7.7s",type);
845: }
846: PetscViewerASCIIPushTab(viewer);
847: PetscTypeCompare((PetscObject)ts,TSSUNDIALS,&isundials);
848: PetscViewerASCIIPopTab(viewer);
849: return(0);
850: }
855: /*@
856: TSSetApplicationContext - Sets an optional user-defined context for
857: the timesteppers.
859: Logically Collective on TS
861: Input Parameters:
862: + ts - the TS context obtained from TSCreate()
863: - usrP - optional user context
865: Level: intermediate
867: .keywords: TS, timestep, set, application, context
869: .seealso: TSGetApplicationContext()
870: @*/
871: PetscErrorCode TSSetApplicationContext(TS ts,void *usrP)
872: {
875: ts->user = usrP;
876: return(0);
877: }
881: /*@
882: TSGetApplicationContext - Gets the user-defined context for the
883: timestepper.
885: Not Collective
887: Input Parameter:
888: . ts - the TS context obtained from TSCreate()
890: Output Parameter:
891: . usrP - user context
893: Level: intermediate
895: .keywords: TS, timestep, get, application, context
897: .seealso: TSSetApplicationContext()
898: @*/
899: PetscErrorCode TSGetApplicationContext(TS ts,void *usrP)
900: {
903: *(void**)usrP = ts->user;
904: return(0);
905: }
909: /*@
910: TSGetTimeStepNumber - Gets the current number of timesteps.
912: Not Collective
914: Input Parameter:
915: . ts - the TS context obtained from TSCreate()
917: Output Parameter:
918: . iter - number steps so far
920: Level: intermediate
922: .keywords: TS, timestep, get, iteration, number
923: @*/
924: PetscErrorCode TSGetTimeStepNumber(TS ts,PetscInt* iter)
925: {
929: *iter = ts->steps;
930: return(0);
931: }
935: /*@
936: TSSetInitialTimeStep - Sets the initial timestep to be used,
937: as well as the initial time.
939: Logically Collective on TS
941: Input Parameters:
942: + ts - the TS context obtained from TSCreate()
943: . initial_time - the initial time
944: - time_step - the size of the timestep
946: Level: intermediate
948: .seealso: TSSetTimeStep(), TSGetTimeStep()
950: .keywords: TS, set, initial, timestep
951: @*/
952: PetscErrorCode TSSetInitialTimeStep(TS ts,PetscReal initial_time,PetscReal time_step)
953: {
958: TSSetTimeStep(ts,time_step);
959: TSSetTime(ts,initial_time);
960: return(0);
961: }
965: /*@
966: TSSetTimeStep - Allows one to reset the timestep at any time,
967: useful for simple pseudo-timestepping codes.
969: Logically Collective on TS
971: Input Parameters:
972: + ts - the TS context obtained from TSCreate()
973: - time_step - the size of the timestep
975: Level: intermediate
977: .seealso: TSSetInitialTimeStep(), TSGetTimeStep()
979: .keywords: TS, set, timestep
980: @*/
981: PetscErrorCode TSSetTimeStep(TS ts,PetscReal time_step)
982: {
986: ts->time_step = time_step;
987: return(0);
988: }
992: /*@
993: TSSetExactFinalTime - Determines whether to interpolate solution to the
994: exact final time requested by the user or just returns it at the final time
995: it computed.
997: Logically Collective on TS
999: Input Parameter:
1000: + ts - the time-step context
1001: - ft - PETSC_TRUE if interpolates, else PETSC_FALSE
1003: Level: beginner
1005: .seealso: TSSetDuration()
1006: @*/
1007: PetscErrorCode TSSetExactFinalTime(TS ts,PetscBool flg)
1008: {
1013: ts->exact_final_time = flg;
1014: return(0);
1015: }
1019: /*@
1020: TSGetTimeStep - Gets the current timestep size.
1022: Not Collective
1024: Input Parameter:
1025: . ts - the TS context obtained from TSCreate()
1027: Output Parameter:
1028: . dt - the current timestep size
1030: Level: intermediate
1032: .seealso: TSSetInitialTimeStep(), TSGetTimeStep()
1034: .keywords: TS, get, timestep
1035: @*/
1036: PetscErrorCode TSGetTimeStep(TS ts,PetscReal* dt)
1037: {
1041: *dt = ts->time_step;
1042: return(0);
1043: }
1047: /*@
1048: TSGetSolution - Returns the solution at the present timestep. It
1049: is valid to call this routine inside the function that you are evaluating
1050: in order to move to the new timestep. This vector not changed until
1051: the solution at the next timestep has been calculated.
1053: Not Collective, but Vec returned is parallel if TS is parallel
1055: Input Parameter:
1056: . ts - the TS context obtained from TSCreate()
1058: Output Parameter:
1059: . v - the vector containing the solution
1061: Level: intermediate
1063: .seealso: TSGetTimeStep()
1065: .keywords: TS, timestep, get, solution
1066: @*/
1067: PetscErrorCode TSGetSolution(TS ts,Vec *v)
1068: {
1072: *v = ts->vec_sol;
1073: return(0);
1074: }
1076: /* ----- Routines to initialize and destroy a timestepper ---- */
1079: /*@
1080: TSSetProblemType - Sets the type of problem to be solved.
1082: Not collective
1084: Input Parameters:
1085: + ts - The TS
1086: - type - One of TS_LINEAR, TS_NONLINEAR where these types refer to problems of the forms
1087: .vb
1088: U_t = A U
1089: U_t = A(t) U
1090: U_t = F(t,U)
1091: .ve
1093: Level: beginner
1095: .keywords: TS, problem type
1096: .seealso: TSSetUp(), TSProblemType, TS
1097: @*/
1098: PetscErrorCode TSSetProblemType(TS ts, TSProblemType type)
1099: {
1104: ts->problem_type = type;
1105: if (type == TS_LINEAR) {
1106: SNES snes;
1107: TSGetSNES(ts,&snes);
1108: SNESSetType(snes,SNESKSPONLY);
1109: }
1110: return(0);
1111: }
1115: /*@C
1116: TSGetProblemType - Gets the type of problem to be solved.
1118: Not collective
1120: Input Parameter:
1121: . ts - The TS
1123: Output Parameter:
1124: . type - One of TS_LINEAR, TS_NONLINEAR where these types refer to problems of the forms
1125: .vb
1126: M U_t = A U
1127: M(t) U_t = A(t) U
1128: U_t = F(t,U)
1129: .ve
1131: Level: beginner
1133: .keywords: TS, problem type
1134: .seealso: TSSetUp(), TSProblemType, TS
1135: @*/
1136: PetscErrorCode TSGetProblemType(TS ts, TSProblemType *type)
1137: {
1141: *type = ts->problem_type;
1142: return(0);
1143: }
1147: /*@
1148: TSSetUp - Sets up the internal data structures for the later use
1149: of a timestepper.
1151: Collective on TS
1153: Input Parameter:
1154: . ts - the TS context obtained from TSCreate()
1156: Notes:
1157: For basic use of the TS solvers the user need not explicitly call
1158: TSSetUp(), since these actions will automatically occur during
1159: the call to TSStep(). However, if one wishes to control this
1160: phase separately, TSSetUp() should be called after TSCreate()
1161: and optional routines of the form TSSetXXX(), but before TSStep().
1163: Level: advanced
1165: .keywords: TS, timestep, setup
1167: .seealso: TSCreate(), TSStep(), TSDestroy()
1168: @*/
1169: PetscErrorCode TSSetUp(TS ts)
1170: {
1175: if (ts->setupcalled) return(0);
1177: if (!((PetscObject)ts)->type_name) {
1178: TSSetType(ts,TSEULER);
1179: }
1180: if (ts->exact_final_time == PETSC_DECIDE) ts->exact_final_time = PETSC_FALSE;
1182: if (!ts->vec_sol) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetSolution() first");
1184: if (ts->ops->setup) {
1185: (*ts->ops->setup)(ts);
1186: }
1188: ts->setupcalled = PETSC_TRUE;
1189: return(0);
1190: }
1194: /*@
1195: TSReset - Resets a TS context and removes any allocated Vecs and Mats.
1197: Collective on TS
1199: Input Parameter:
1200: . ts - the TS context obtained from TSCreate()
1202: Level: beginner
1204: .keywords: TS, timestep, reset
1206: .seealso: TSCreate(), TSSetup(), TSDestroy()
1207: @*/
1208: PetscErrorCode TSReset(TS ts)
1209: {
1214: if (ts->ops->reset) {
1215: (*ts->ops->reset)(ts);
1216: }
1217: if (ts->snes) {SNESReset(ts->snes);}
1218: MatDestroy(&ts->Arhs);
1219: MatDestroy(&ts->Brhs);
1220: VecDestroy(&ts->Frhs);
1221: VecDestroy(&ts->vec_sol);
1222: VecDestroyVecs(ts->nwork,&ts->work);
1223: ts->setupcalled = PETSC_FALSE;
1224: return(0);
1225: }
1229: /*@
1230: TSDestroy - Destroys the timestepper context that was created
1231: with TSCreate().
1233: Collective on TS
1235: Input Parameter:
1236: . ts - the TS context obtained from TSCreate()
1238: Level: beginner
1240: .keywords: TS, timestepper, destroy
1242: .seealso: TSCreate(), TSSetUp(), TSSolve()
1243: @*/
1244: PetscErrorCode TSDestroy(TS *ts)
1245: {
1249: if (!*ts) return(0);
1251: if (--((PetscObject)(*ts))->refct > 0) {*ts = 0; return(0);}
1253: TSReset((*ts));
1255: /* if memory was published with AMS then destroy it */
1256: PetscObjectDepublish((*ts));
1257: if ((*ts)->ops->destroy) {(*(*ts)->ops->destroy)((*ts));}
1259: SNESDestroy(&(*ts)->snes);
1260: DMDestroy(&(*ts)->dm);
1261: TSMonitorCancel((*ts));
1263: PetscFree((*ts)->userops);
1265: PetscHeaderDestroy(ts);
1266: return(0);
1267: }
1271: /*@
1272: TSGetSNES - Returns the SNES (nonlinear solver) associated with
1273: a TS (timestepper) context. Valid only for nonlinear problems.
1275: Not Collective, but SNES is parallel if TS is parallel
1277: Input Parameter:
1278: . ts - the TS context obtained from TSCreate()
1280: Output Parameter:
1281: . snes - the nonlinear solver context
1283: Notes:
1284: The user can then directly manipulate the SNES context to set various
1285: options, etc. Likewise, the user can then extract and manipulate the
1286: KSP, KSP, and PC contexts as well.
1288: TSGetSNES() does not work for integrators that do not use SNES; in
1289: this case TSGetSNES() returns PETSC_NULL in snes.
1291: Level: beginner
1293: .keywords: timestep, get, SNES
1294: @*/
1295: PetscErrorCode TSGetSNES(TS ts,SNES *snes)
1296: {
1302: if (!ts->snes) {
1303: SNESCreate(((PetscObject)ts)->comm,&ts->snes);
1304: PetscLogObjectParent(ts,ts->snes);
1305: PetscObjectIncrementTabLevel((PetscObject)ts->snes,(PetscObject)ts,1);
1306: if (ts->problem_type == TS_LINEAR) {
1307: SNESSetType(ts->snes,SNESKSPONLY);
1308: }
1309: }
1310: *snes = ts->snes;
1311: return(0);
1312: }
1316: /*@
1317: TSGetKSP - Returns the KSP (linear solver) associated with
1318: a TS (timestepper) context.
1320: Not Collective, but KSP is parallel if TS is parallel
1322: Input Parameter:
1323: . ts - the TS context obtained from TSCreate()
1325: Output Parameter:
1326: . ksp - the nonlinear solver context
1328: Notes:
1329: The user can then directly manipulate the KSP context to set various
1330: options, etc. Likewise, the user can then extract and manipulate the
1331: KSP and PC contexts as well.
1333: TSGetKSP() does not work for integrators that do not use KSP;
1334: in this case TSGetKSP() returns PETSC_NULL in ksp.
1336: Level: beginner
1338: .keywords: timestep, get, KSP
1339: @*/
1340: PetscErrorCode TSGetKSP(TS ts,KSP *ksp)
1341: {
1343: SNES snes;
1348: if (!((PetscObject)ts)->type_name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"KSP is not created yet. Call TSSetType() first");
1349: if (ts->problem_type != TS_LINEAR) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Linear only; use TSGetSNES()");
1350: TSGetSNES(ts,&snes);
1351: SNESGetKSP(snes,ksp);
1352: return(0);
1353: }
1355: /* ----------- Routines to set solver parameters ---------- */
1359: /*@
1360: TSGetDuration - Gets the maximum number of timesteps to use and
1361: maximum time for iteration.
1363: Not Collective
1365: Input Parameters:
1366: + ts - the TS context obtained from TSCreate()
1367: . maxsteps - maximum number of iterations to use, or PETSC_NULL
1368: - maxtime - final time to iterate to, or PETSC_NULL
1370: Level: intermediate
1372: .keywords: TS, timestep, get, maximum, iterations, time
1373: @*/
1374: PetscErrorCode TSGetDuration(TS ts, PetscInt *maxsteps, PetscReal *maxtime)
1375: {
1378: if (maxsteps) {
1380: *maxsteps = ts->max_steps;
1381: }
1382: if (maxtime) {
1384: *maxtime = ts->max_time;
1385: }
1386: return(0);
1387: }
1391: /*@
1392: TSSetDuration - Sets the maximum number of timesteps to use and
1393: maximum time for iteration.
1395: Logically Collective on TS
1397: Input Parameters:
1398: + ts - the TS context obtained from TSCreate()
1399: . maxsteps - maximum number of iterations to use
1400: - maxtime - final time to iterate to
1402: Options Database Keys:
1403: . -ts_max_steps <maxsteps> - Sets maxsteps
1404: . -ts_max_time <maxtime> - Sets maxtime
1406: Notes:
1407: The default maximum number of iterations is 5000. Default time is 5.0
1409: Level: intermediate
1411: .keywords: TS, timestep, set, maximum, iterations
1413: .seealso: TSSetExactFinalTime()
1414: @*/
1415: PetscErrorCode TSSetDuration(TS ts,PetscInt maxsteps,PetscReal maxtime)
1416: {
1421: if (maxsteps >= 0) ts->max_steps = maxsteps;
1422: if (maxtime != PETSC_DEFAULT) ts->max_time = maxtime;
1423: return(0);
1424: }
1428: /*@
1429: TSSetSolution - Sets the initial solution vector
1430: for use by the TS routines.
1432: Logically Collective on TS and Vec
1434: Input Parameters:
1435: + ts - the TS context obtained from TSCreate()
1436: - x - the solution vector
1438: Level: beginner
1440: .keywords: TS, timestep, set, solution, initial conditions
1441: @*/
1442: PetscErrorCode TSSetSolution(TS ts,Vec x)
1443: {
1449: PetscObjectReference((PetscObject)x);
1450: VecDestroy(&ts->vec_sol);
1451: ts->vec_sol = x;
1452: return(0);
1453: }
1457: /*@C
1458: TSSetPreStep - Sets the general-purpose function
1459: called once at the beginning of each time step.
1461: Logically Collective on TS
1463: Input Parameters:
1464: + ts - The TS context obtained from TSCreate()
1465: - func - The function
1467: Calling sequence of func:
1468: . func (TS ts);
1470: Level: intermediate
1472: .keywords: TS, timestep
1473: @*/
1474: PetscErrorCode TSSetPreStep(TS ts, PetscErrorCode (*func)(TS))
1475: {
1478: ts->ops->prestep = func;
1479: return(0);
1480: }
1484: /*@
1485: TSPreStep - Runs the user-defined pre-step function.
1487: Collective on TS
1489: Input Parameters:
1490: . ts - The TS context obtained from TSCreate()
1492: Notes:
1493: TSPreStep() is typically used within time stepping implementations,
1494: so most users would not generally call this routine themselves.
1496: Level: developer
1498: .keywords: TS, timestep
1499: @*/
1500: PetscErrorCode TSPreStep(TS ts)
1501: {
1506: if (ts->ops->prestep) {
1507: PetscStackPush("TS PreStep function");
1508: (*ts->ops->prestep)(ts);
1509: PetscStackPop;
1510: }
1511: return(0);
1512: }
1516: /*@C
1517: TSSetPostStep - Sets the general-purpose function
1518: called once at the end of each time step.
1520: Logically Collective on TS
1522: Input Parameters:
1523: + ts - The TS context obtained from TSCreate()
1524: - func - The function
1526: Calling sequence of func:
1527: . func (TS ts);
1529: Level: intermediate
1531: .keywords: TS, timestep
1532: @*/
1533: PetscErrorCode TSSetPostStep(TS ts, PetscErrorCode (*func)(TS))
1534: {
1537: ts->ops->poststep = func;
1538: return(0);
1539: }
1543: /*@
1544: TSPostStep - Runs the user-defined post-step function.
1546: Collective on TS
1548: Input Parameters:
1549: . ts - The TS context obtained from TSCreate()
1551: Notes:
1552: TSPostStep() is typically used within time stepping implementations,
1553: so most users would not generally call this routine themselves.
1555: Level: developer
1557: .keywords: TS, timestep
1558: @*/
1559: PetscErrorCode TSPostStep(TS ts)
1560: {
1565: if (ts->ops->poststep) {
1566: PetscStackPush("TS PostStep function");
1567: (*ts->ops->poststep)(ts);
1568: PetscStackPop;
1569: }
1570: return(0);
1571: }
1573: /* ------------ Routines to set performance monitoring options ----------- */
1577: /*@C
1578: TSMonitorSet - Sets an ADDITIONAL function that is to be used at every
1579: timestep to display the iteration's progress.
1581: Logically Collective on TS
1583: Input Parameters:
1584: + ts - the TS context obtained from TSCreate()
1585: . monitor - monitoring routine
1586: . mctx - [optional] user-defined context for private data for the
1587: monitor routine (use PETSC_NULL if no context is desired)
1588: - monitordestroy - [optional] routine that frees monitor context
1589: (may be PETSC_NULL)
1591: Calling sequence of monitor:
1592: $ int monitor(TS ts,PetscInt steps,PetscReal time,Vec x,void *mctx)
1594: + ts - the TS context
1595: . steps - iteration number
1596: . time - current time
1597: . x - current iterate
1598: - mctx - [optional] monitoring context
1600: Notes:
1601: This routine adds an additional monitor to the list of monitors that
1602: already has been loaded.
1604: Fortran notes: Only a single monitor function can be set for each TS object
1606: Level: intermediate
1608: .keywords: TS, timestep, set, monitor
1610: .seealso: TSMonitorDefault(), TSMonitorCancel()
1611: @*/
1612: PetscErrorCode TSMonitorSet(TS ts,PetscErrorCode (*monitor)(TS,PetscInt,PetscReal,Vec,void*),void *mctx,PetscErrorCode (*mdestroy)(void**))
1613: {
1616: if (ts->numbermonitors >= MAXTSMONITORS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many monitors set");
1617: ts->monitor[ts->numbermonitors] = monitor;
1618: ts->mdestroy[ts->numbermonitors] = mdestroy;
1619: ts->monitorcontext[ts->numbermonitors++] = (void*)mctx;
1620: return(0);
1621: }
1625: /*@C
1626: TSMonitorCancel - Clears all the monitors that have been set on a time-step object.
1628: Logically Collective on TS
1630: Input Parameters:
1631: . ts - the TS context obtained from TSCreate()
1633: Notes:
1634: There is no way to remove a single, specific monitor.
1636: Level: intermediate
1638: .keywords: TS, timestep, set, monitor
1640: .seealso: TSMonitorDefault(), TSMonitorSet()
1641: @*/
1642: PetscErrorCode TSMonitorCancel(TS ts)
1643: {
1645: PetscInt i;
1649: for (i=0; i<ts->numbermonitors; i++) {
1650: if (ts->mdestroy[i]) {
1651: (*ts->mdestroy[i])(&ts->monitorcontext[i]);
1652: }
1653: }
1654: ts->numbermonitors = 0;
1655: return(0);
1656: }
1660: /*@
1661: TSMonitorDefault - Sets the Default monitor
1663: Level: intermediate
1665: .keywords: TS, set, monitor
1667: .seealso: TSMonitorDefault(), TSMonitorSet()
1668: @*/
1669: PetscErrorCode TSMonitorDefault(TS ts,PetscInt step,PetscReal ptime,Vec v,void *dummy)
1670: {
1672: PetscViewer viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(((PetscObject)ts)->comm);
1675: PetscViewerASCIIAddTab(viewer,((PetscObject)ts)->tablevel);
1676: PetscViewerASCIIPrintf(viewer,"%D TS dt %g time %g\n",step,(double)ts->time_step,(double)ptime);
1677: PetscViewerASCIISubtractTab(viewer,((PetscObject)ts)->tablevel);
1678: return(0);
1679: }
1683: /*@
1684: TSSetRetainStages - Request that all stages in the upcoming step be stored so that interpolation will be available.
1686: Logically Collective on TS
1688: Input Argument:
1689: . ts - time stepping context
1691: Output Argument:
1692: . flg - PETSC_TRUE or PETSC_FALSE
1694: Level: intermediate
1696: .keywords: TS, set
1698: .seealso: TSInterpolate(), TSSetPostStep()
1699: @*/
1700: PetscErrorCode TSSetRetainStages(TS ts,PetscBool flg)
1701: {
1705: ts->retain_stages = flg;
1706: return(0);
1707: }
1711: /*@
1712: TSInterpolate - Interpolate the solution computed during the previous step to an arbitrary location in the interval
1714: Collective on TS
1716: Input Argument:
1717: + ts - time stepping context
1718: - t - time to interpolate to
1720: Output Argument:
1721: . X - state at given time
1723: Notes:
1724: The user should call TSSetRetainStages() before taking a step in which interpolation will be requested.
1726: Level: intermediate
1728: Developer Notes:
1729: TSInterpolate() and the storing of previous steps/stages should be generalized to support delay differential equations and continuous adjoints.
1731: .keywords: TS, set
1733: .seealso: TSSetRetainStages(), TSSetPostStep()
1734: @*/
1735: PetscErrorCode TSInterpolate(TS ts,PetscReal t,Vec X)
1736: {
1741: if (t < ts->ptime - ts->time_step_prev || t > ts->ptime) SETERRQ3(((PetscObject)ts)->comm,PETSC_ERR_ARG_OUTOFRANGE,"Requested time %G not in last time steps [%G,%G]",t,ts->ptime-ts->time_step_prev,ts->ptime);
1742: if (!ts->ops->interpolate) SETERRQ1(((PetscObject)ts)->comm,PETSC_ERR_SUP,"%s does not provide interpolation",((PetscObject)ts)->type_name);
1743: (*ts->ops->interpolate)(ts,t,X);
1744: return(0);
1745: }
1749: /*@
1750: TSStep - Steps one time step
1752: Collective on TS
1754: Input Parameter:
1755: . ts - the TS context obtained from TSCreate()
1757: Level: intermediate
1759: .keywords: TS, timestep, solve
1761: .seealso: TSCreate(), TSSetUp(), TSDestroy(), TSSolve()
1762: @*/
1763: PetscErrorCode TSStep(TS ts)
1764: {
1765: PetscReal ptime_prev;
1770: TSSetUp(ts);
1772: ts->reason = TS_CONVERGED_ITERATING;
1774: ptime_prev = ts->ptime;
1775: PetscLogEventBegin(TS_Step,ts,0,0,0);
1776: (*ts->ops->step)(ts);
1777: PetscLogEventEnd(TS_Step,ts,0,0,0);
1778: ts->time_step_prev = ts->ptime - ptime_prev;
1780: if (ts->reason < 0) {
1781: if (ts->errorifstepfailed) SETERRQ(((PetscObject)ts)->comm,PETSC_ERR_NOT_CONVERGED,"TSStep has failed");
1782: } else if (!ts->reason) {
1783: if (ts->steps >= ts->max_steps)
1784: ts->reason = TS_CONVERGED_ITS;
1785: else if (ts->ptime >= ts->max_time)
1786: ts->reason = TS_CONVERGED_TIME;
1787: }
1789: return(0);
1790: }
1794: /*@
1795: TSSolve - Steps the requested number of timesteps.
1797: Collective on TS
1799: Input Parameter:
1800: + ts - the TS context obtained from TSCreate()
1801: - x - the solution vector
1803: Output Parameter:
1804: . ftime - time of the state vector x upon completion
1806: Level: beginner
1808: Notes:
1809: The final time returned by this function may be different from the time of the internally
1810: held state accessible by TSGetSolution() and TSGetTime() because the method may have
1811: stepped over the final time.
1813: .keywords: TS, timestep, solve
1815: .seealso: TSCreate(), TSSetSolution(), TSStep()
1816: @*/
1817: PetscErrorCode TSSolve(TS ts,Vec x,PetscReal *ftime)
1818: {
1819: PetscBool flg;
1820: char filename[PETSC_MAX_PATH_LEN];
1821: PetscViewer viewer;
1827: if (ts->exact_final_time) { /* Need ts->vec_sol to be distinct so it is not overwritten when we interpolate at the end */
1828: if (!ts->vec_sol || x == ts->vec_sol) {
1829: Vec y;
1830: VecDuplicate(x,&y);
1831: TSSetSolution(ts,y);
1832: VecDestroy(&y); /* grant ownership */
1833: }
1834: VecCopy(x,ts->vec_sol);
1835: } else {
1836: TSSetSolution(ts,x);
1837: }
1838: TSSetUp(ts);
1839: /* reset time step and iteration counters */
1840: ts->steps = 0;
1841: ts->linear_its = 0;
1842: ts->nonlinear_its = 0;
1843: ts->num_snes_failures = 0;
1844: ts->reject = 0;
1845: ts->reason = TS_CONVERGED_ITERATING;
1847: if (ts->ops->solve) { /* This private interface is transitional and should be removed when all implementations are updated. */
1848: (*ts->ops->solve)(ts);
1849: VecCopy(ts->vec_sol,x);
1850: if (ftime) *ftime = ts->ptime;
1851: } else {
1852: /* steps the requested number of timesteps. */
1853: TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol);
1854: if (ts->steps >= ts->max_steps)
1855: ts->reason = TS_CONVERGED_ITS;
1856: else if (ts->ptime >= ts->max_time)
1857: ts->reason = TS_CONVERGED_TIME;
1858: while (!ts->reason) {
1859: TSPreStep(ts);
1860: TSStep(ts);
1861: TSPostStep(ts);
1862: TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol);
1863: }
1864: if (ts->exact_final_time && ts->ptime > ts->max_time) {
1865: TSInterpolate(ts,ts->max_time,x);
1866: if (ftime) *ftime = ts->max_time;
1867: } else {
1868: VecCopy(ts->vec_sol,x);
1869: if (ftime) *ftime = ts->ptime;
1870: }
1871: }
1872: PetscOptionsGetString(((PetscObject)ts)->prefix,"-ts_view",filename,PETSC_MAX_PATH_LEN,&flg);
1873: if (flg && !PetscPreLoadingOn) {
1874: PetscViewerASCIIOpen(((PetscObject)ts)->comm,filename,&viewer);
1875: TSView(ts,viewer);
1876: PetscViewerDestroy(&viewer);
1877: }
1878: return(0);
1879: }
1883: /*@
1884: TSMonitor - Runs all user-provided monitor routines set using TSMonitorSet()
1886: Collective on TS
1888: Input Parameters:
1889: + ts - time stepping context obtained from TSCreate()
1890: . step - step number that has just completed
1891: . ptime - model time of the state
1892: - x - state at the current model time
1894: Notes:
1895: TSMonitor() is typically used within the time stepping implementations.
1896: Users might call this function when using the TSStep() interface instead of TSSolve().
1898: Level: advanced
1900: .keywords: TS, timestep
1901: @*/
1902: PetscErrorCode TSMonitor(TS ts,PetscInt step,PetscReal ptime,Vec x)
1903: {
1905: PetscInt i,n = ts->numbermonitors;
1908: for (i=0; i<n; i++) {
1909: (*ts->monitor[i])(ts,step,ptime,x,ts->monitorcontext[i]);
1910: }
1911: return(0);
1912: }
1914: /* ------------------------------------------------------------------------*/
1918: /*@C
1919: TSMonitorLGCreate - Creates a line graph context for use with
1920: TS to monitor convergence of preconditioned residual norms.
1922: Collective on TS
1924: Input Parameters:
1925: + host - the X display to open, or null for the local machine
1926: . label - the title to put in the title bar
1927: . x, y - the screen coordinates of the upper left coordinate of the window
1928: - m, n - the screen width and height in pixels
1930: Output Parameter:
1931: . draw - the drawing context
1933: Options Database Key:
1934: . -ts_monitor_draw - automatically sets line graph monitor
1936: Notes:
1937: Use TSMonitorLGDestroy() to destroy this line graph, not PetscDrawLGDestroy().
1939: Level: intermediate
1941: .keywords: TS, monitor, line graph, residual, seealso
1943: .seealso: TSMonitorLGDestroy(), TSMonitorSet()
1945: @*/
1946: PetscErrorCode TSMonitorLGCreate(const char host[],const char label[],int x,int y,int m,int n,PetscDrawLG *draw)
1947: {
1948: PetscDraw win;
1952: PetscDrawCreate(PETSC_COMM_SELF,host,label,x,y,m,n,&win);
1953: PetscDrawSetType(win,PETSC_DRAW_X);
1954: PetscDrawLGCreate(win,1,draw);
1955: PetscDrawLGIndicateDataPoints(*draw);
1957: PetscLogObjectParent(*draw,win);
1958: return(0);
1959: }
1963: PetscErrorCode TSMonitorLG(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
1964: {
1965: PetscDrawLG lg = (PetscDrawLG) monctx;
1966: PetscReal x,y = ptime;
1970: if (!monctx) {
1971: MPI_Comm comm;
1972: PetscViewer viewer;
1974: PetscObjectGetComm((PetscObject)ts,&comm);
1975: viewer = PETSC_VIEWER_DRAW_(comm);
1976: PetscViewerDrawGetDrawLG(viewer,0,&lg);
1977: }
1979: if (!n) {PetscDrawLGReset(lg);}
1980: x = (PetscReal)n;
1981: PetscDrawLGAddPoint(lg,&x,&y);
1982: if (n < 20 || (n % 5)) {
1983: PetscDrawLGDraw(lg);
1984: }
1985: return(0);
1986: }
1990: /*@C
1991: TSMonitorLGDestroy - Destroys a line graph context that was created
1992: with TSMonitorLGCreate().
1994: Collective on PetscDrawLG
1996: Input Parameter:
1997: . draw - the drawing context
1999: Level: intermediate
2001: .keywords: TS, monitor, line graph, destroy
2003: .seealso: TSMonitorLGCreate(), TSMonitorSet(), TSMonitorLG();
2004: @*/
2005: PetscErrorCode TSMonitorLGDestroy(PetscDrawLG *drawlg)
2006: {
2007: PetscDraw draw;
2011: PetscDrawLGGetDraw(*drawlg,&draw);
2012: PetscDrawDestroy(&draw);
2013: PetscDrawLGDestroy(drawlg);
2014: return(0);
2015: }
2019: /*@
2020: TSGetTime - Gets the current time.
2022: Not Collective
2024: Input Parameter:
2025: . ts - the TS context obtained from TSCreate()
2027: Output Parameter:
2028: . t - the current time
2030: Level: beginner
2032: .seealso: TSSetInitialTimeStep(), TSGetTimeStep()
2034: .keywords: TS, get, time
2035: @*/
2036: PetscErrorCode TSGetTime(TS ts,PetscReal* t)
2037: {
2041: *t = ts->ptime;
2042: return(0);
2043: }
2047: /*@
2048: TSSetTime - Allows one to reset the time.
2050: Logically Collective on TS
2052: Input Parameters:
2053: + ts - the TS context obtained from TSCreate()
2054: - time - the time
2056: Level: intermediate
2058: .seealso: TSGetTime(), TSSetDuration()
2060: .keywords: TS, set, time
2061: @*/
2062: PetscErrorCode TSSetTime(TS ts, PetscReal t)
2063: {
2067: ts->ptime = t;
2068: return(0);
2069: }
2073: /*@C
2074: TSSetOptionsPrefix - Sets the prefix used for searching for all
2075: TS options in the database.
2077: Logically Collective on TS
2079: Input Parameter:
2080: + ts - The TS context
2081: - prefix - The prefix to prepend to all option names
2083: Notes:
2084: A hyphen (-) must NOT be given at the beginning of the prefix name.
2085: The first character of all runtime options is AUTOMATICALLY the
2086: hyphen.
2088: Level: advanced
2090: .keywords: TS, set, options, prefix, database
2092: .seealso: TSSetFromOptions()
2094: @*/
2095: PetscErrorCode TSSetOptionsPrefix(TS ts,const char prefix[])
2096: {
2098: SNES snes;
2102: PetscObjectSetOptionsPrefix((PetscObject)ts,prefix);
2103: TSGetSNES(ts,&snes);
2104: SNESSetOptionsPrefix(snes,prefix);
2105: return(0);
2106: }
2111: /*@C
2112: TSAppendOptionsPrefix - Appends to the prefix used for searching for all
2113: TS options in the database.
2115: Logically Collective on TS
2117: Input Parameter:
2118: + ts - The TS context
2119: - prefix - The prefix to prepend to all option names
2121: Notes:
2122: A hyphen (-) must NOT be given at the beginning of the prefix name.
2123: The first character of all runtime options is AUTOMATICALLY the
2124: hyphen.
2126: Level: advanced
2128: .keywords: TS, append, options, prefix, database
2130: .seealso: TSGetOptionsPrefix()
2132: @*/
2133: PetscErrorCode TSAppendOptionsPrefix(TS ts,const char prefix[])
2134: {
2136: SNES snes;
2140: PetscObjectAppendOptionsPrefix((PetscObject)ts,prefix);
2141: TSGetSNES(ts,&snes);
2142: SNESAppendOptionsPrefix(snes,prefix);
2143: return(0);
2144: }
2148: /*@C
2149: TSGetOptionsPrefix - Sets the prefix used for searching for all
2150: TS options in the database.
2152: Not Collective
2154: Input Parameter:
2155: . ts - The TS context
2157: Output Parameter:
2158: . prefix - A pointer to the prefix string used
2160: Notes: On the fortran side, the user should pass in a string 'prifix' of
2161: sufficient length to hold the prefix.
2163: Level: intermediate
2165: .keywords: TS, get, options, prefix, database
2167: .seealso: TSAppendOptionsPrefix()
2168: @*/
2169: PetscErrorCode TSGetOptionsPrefix(TS ts,const char *prefix[])
2170: {
2176: PetscObjectGetOptionsPrefix((PetscObject)ts,prefix);
2177: return(0);
2178: }
2182: /*@C
2183: TSGetRHSJacobian - Returns the Jacobian J at the present timestep.
2185: Not Collective, but parallel objects are returned if TS is parallel
2187: Input Parameter:
2188: . ts - The TS context obtained from TSCreate()
2190: Output Parameters:
2191: + J - The Jacobian J of F, where U_t = F(U,t)
2192: . M - The preconditioner matrix, usually the same as J
2193: . func - Function to compute the Jacobian of the RHS
2194: - ctx - User-defined context for Jacobian evaluation routine
2196: Notes: You can pass in PETSC_NULL for any return argument you do not need.
2198: Level: intermediate
2200: .seealso: TSGetTimeStep(), TSGetMatrices(), TSGetTime(), TSGetTimeStepNumber()
2202: .keywords: TS, timestep, get, matrix, Jacobian
2203: @*/
2204: PetscErrorCode TSGetRHSJacobian(TS ts,Mat *J,Mat *M,TSRHSJacobian *func,void **ctx)
2205: {
2207: SNES snes;
2210: TSGetSNES(ts,&snes);
2211: SNESGetJacobian(snes,J,M,PETSC_NULL,PETSC_NULL);
2212: if (func) *func = ts->userops->rhsjacobian;
2213: if (ctx) *ctx = ts->jacP;
2214: return(0);
2215: }
2219: /*@C
2220: TSGetIJacobian - Returns the implicit Jacobian at the present timestep.
2222: Not Collective, but parallel objects are returned if TS is parallel
2224: Input Parameter:
2225: . ts - The TS context obtained from TSCreate()
2227: Output Parameters:
2228: + A - The Jacobian of F(t,U,U_t)
2229: . B - The preconditioner matrix, often the same as A
2230: . f - The function to compute the matrices
2231: - ctx - User-defined context for Jacobian evaluation routine
2233: Notes: You can pass in PETSC_NULL for any return argument you do not need.
2235: Level: advanced
2237: .seealso: TSGetTimeStep(), TSGetRHSJacobian(), TSGetMatrices(), TSGetTime(), TSGetTimeStepNumber()
2239: .keywords: TS, timestep, get, matrix, Jacobian
2240: @*/
2241: PetscErrorCode TSGetIJacobian(TS ts,Mat *A,Mat *B,TSIJacobian *f,void **ctx)
2242: {
2244: SNES snes;
2247: TSGetSNES(ts,&snes);
2248: SNESGetJacobian(snes,A,B,PETSC_NULL,PETSC_NULL);
2249: if (f) *f = ts->userops->ijacobian;
2250: if (ctx) *ctx = ts->jacP;
2251: return(0);
2252: }
2254: typedef struct {
2255: PetscViewer viewer;
2256: Vec initialsolution;
2257: PetscBool showinitial;
2258: } TSMonitorSolutionCtx;
2262: /*@C
2263: TSMonitorSolution - Monitors progress of the TS solvers by calling
2264: VecView() for the solution at each timestep
2266: Collective on TS
2268: Input Parameters:
2269: + ts - the TS context
2270: . step - current time-step
2271: . ptime - current time
2272: - dummy - either a viewer or PETSC_NULL
2274: Level: intermediate
2276: .keywords: TS, vector, monitor, view
2278: .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
2279: @*/
2280: PetscErrorCode TSMonitorSolution(TS ts,PetscInt step,PetscReal ptime,Vec x,void *dummy)
2281: {
2282: PetscErrorCode ierr;
2283: TSMonitorSolutionCtx *ictx = (TSMonitorSolutionCtx*)dummy;
2286: if (!step && ictx->showinitial) {
2287: if (!ictx->initialsolution) {
2288: VecDuplicate(x,&ictx->initialsolution);
2289: }
2290: VecCopy(x,ictx->initialsolution);
2291: }
2292: if (ictx->showinitial) {
2293: PetscReal pause;
2294: PetscViewerDrawGetPause(ictx->viewer,&pause);
2295: PetscViewerDrawSetPause(ictx->viewer,0.0);
2296: VecView(ictx->initialsolution,ictx->viewer);
2297: PetscViewerDrawSetPause(ictx->viewer,pause);
2298: PetscViewerDrawSetHold(ictx->viewer,PETSC_TRUE);
2299: }
2300: VecView(x,ictx->viewer);
2301: if (ictx->showinitial) {
2302: PetscViewerDrawSetHold(ictx->viewer,PETSC_FALSE);
2303: }
2304: return(0);
2305: }
2310: /*@C
2311: TSMonitorSolutionDestroy - Destroys the monitor context for TSMonitorSolution
2313: Collective on TS
2315: Input Parameters:
2316: . ctx - the monitor context
2318: Level: intermediate
2320: .keywords: TS, vector, monitor, view
2322: .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorSolution()
2323: @*/
2324: PetscErrorCode TSMonitorSolutionDestroy(void **ctx)
2325: {
2326: PetscErrorCode ierr;
2327: TSMonitorSolutionCtx *ictx = *(TSMonitorSolutionCtx**)ctx;
2328:
2330: PetscViewerDestroy(&ictx->viewer);
2331: VecDestroy(&ictx->initialsolution);
2332: PetscFree(ictx);
2333: return(0);
2334: }
2338: /*@C
2339: TSMonitorSolutionCreate - Creates the monitor context for TSMonitorSolution
2341: Collective on TS
2343: Input Parameter:
2344: . ts - time-step context
2346: Output Patameter:
2347: . ctx - the monitor context
2349: Level: intermediate
2351: .keywords: TS, vector, monitor, view
2353: .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorSolution()
2354: @*/
2355: PetscErrorCode TSMonitorSolutionCreate(TS ts,PetscViewer viewer,void **ctx)
2356: {
2357: PetscErrorCode ierr;
2358: TSMonitorSolutionCtx *ictx;
2359:
2361: PetscNew(TSMonitorSolutionCtx,&ictx);
2362: *ctx = (void*)ictx;
2363: if (!viewer) {
2364: viewer = PETSC_VIEWER_DRAW_(((PetscObject)ts)->comm);
2365: }
2366: PetscObjectReference((PetscObject)viewer);
2367: ictx->viewer = viewer;
2368: ictx->showinitial = PETSC_FALSE;
2369: PetscOptionsGetBool(((PetscObject)ts)->prefix,"-ts_monitor_solution_initial",&ictx->showinitial,PETSC_NULL);
2370: return(0);
2371: }
2375: /*@
2376: TSSetDM - Sets the DM that may be used by some preconditioners
2378: Logically Collective on TS and DM
2380: Input Parameters:
2381: + ts - the preconditioner context
2382: - dm - the dm
2384: Level: intermediate
2387: .seealso: TSGetDM(), SNESSetDM(), SNESGetDM()
2388: @*/
2389: PetscErrorCode TSSetDM(TS ts,DM dm)
2390: {
2392: SNES snes;
2396: PetscObjectReference((PetscObject)dm);
2397: DMDestroy(&ts->dm);
2398: ts->dm = dm;
2399: TSGetSNES(ts,&snes);
2400: SNESSetDM(snes,dm);
2401: return(0);
2402: }
2406: /*@
2407: TSGetDM - Gets the DM that may be used by some preconditioners
2409: Not Collective
2411: Input Parameter:
2412: . ts - the preconditioner context
2414: Output Parameter:
2415: . dm - the dm
2417: Level: intermediate
2420: .seealso: TSSetDM(), SNESSetDM(), SNESGetDM()
2421: @*/
2422: PetscErrorCode TSGetDM(TS ts,DM *dm)
2423: {
2426: *dm = ts->dm;
2427: return(0);
2428: }
2432: /*@
2433: SNESTSFormFunction - Function to evaluate nonlinear residual
2435: Logically Collective on SNES
2437: Input Parameter:
2438: + snes - nonlinear solver
2439: . X - the current state at which to evaluate the residual
2440: - ctx - user context, must be a TS
2442: Output Parameter:
2443: . F - the nonlinear residual
2445: Notes:
2446: This function is not normally called by users and is automatically registered with the SNES used by TS.
2447: It is most frequently passed to MatFDColoringSetFunction().
2449: Level: advanced
2451: .seealso: SNESSetFunction(), MatFDColoringSetFunction()
2452: @*/
2453: PetscErrorCode SNESTSFormFunction(SNES snes,Vec X,Vec F,void *ctx)
2454: {
2455: TS ts = (TS)ctx;
2463: (ts->ops->snesfunction)(snes,X,F,ts);
2464: return(0);
2465: }
2469: /*@
2470: SNESTSFormJacobian - Function to evaluate the Jacobian
2472: Collective on SNES
2474: Input Parameter:
2475: + snes - nonlinear solver
2476: . X - the current state at which to evaluate the residual
2477: - ctx - user context, must be a TS
2479: Output Parameter:
2480: + A - the Jacobian
2481: . B - the preconditioning matrix (may be the same as A)
2482: - flag - indicates any structure change in the matrix
2484: Notes:
2485: This function is not normally called by users and is automatically registered with the SNES used by TS.
2487: Level: developer
2489: .seealso: SNESSetJacobian()
2490: @*/
2491: PetscErrorCode SNESTSFormJacobian(SNES snes,Vec X,Mat *A,Mat *B,MatStructure *flag,void *ctx)
2492: {
2493: TS ts = (TS)ctx;
2505: (ts->ops->snesjacobian)(snes,X,A,B,flag,ts);
2506: return(0);
2507: }
2511: /*@C
2512: TSComputeRHSFunctionLinear - Evaluate the right hand side via the user-provided Jacobian, for linear problems only
2514: Collective on TS
2516: Input Arguments:
2517: + ts - time stepping context
2518: . t - time at which to evaluate
2519: . X - state at which to evaluate
2520: - ctx - context
2522: Output Arguments:
2523: . F - right hand side
2525: Level: intermediate
2527: Notes:
2528: This function is intended to be passed to TSSetRHSFunction() to evaluate the right hand side for linear problems.
2529: The matrix (and optionally the evaluation context) should be passed to TSSetRHSJacobian().
2531: .seealso: TSSetRHSFunction(), TSSetRHSJacobian(), TSComputeRHSJacobianConstant()
2532: @*/
2533: PetscErrorCode TSComputeRHSFunctionLinear(TS ts,PetscReal t,Vec X,Vec F,void *ctx)
2534: {
2536: Mat Arhs,Brhs;
2537: MatStructure flg2;
2540: TSGetRHSMats_Private(ts,&Arhs,&Brhs);
2541: TSComputeRHSJacobian(ts,t,X,&Arhs,&Brhs,&flg2);
2542: MatMult(Arhs,X,F);
2543: return(0);
2544: }
2548: /*@C
2549: TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent.
2551: Collective on TS
2553: Input Arguments:
2554: + ts - time stepping context
2555: . t - time at which to evaluate
2556: . X - state at which to evaluate
2557: - ctx - context
2559: Output Arguments:
2560: + A - pointer to operator
2561: . B - pointer to preconditioning matrix
2562: - flg - matrix structure flag
2564: Level: intermediate
2566: Notes:
2567: This function is intended to be passed to TSSetRHSJacobian() to evaluate the Jacobian for linear time-independent problems.
2569: .seealso: TSSetRHSFunction(), TSSetRHSJacobian(), TSComputeRHSFunctionLinear()
2570: @*/
2571: PetscErrorCode TSComputeRHSJacobianConstant(TS ts,PetscReal t,Vec X,Mat *A,Mat *B,MatStructure *flg,void *ctx)
2572: {
2575: *flg = SAME_PRECONDITIONER;
2576: return(0);
2577: }
2581: /*@C
2582: TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only
2584: Collective on TS
2586: Input Arguments:
2587: + ts - time stepping context
2588: . t - time at which to evaluate
2589: . X - state at which to evaluate
2590: . Xdot - time derivative of state vector
2591: - ctx - context
2593: Output Arguments:
2594: . F - left hand side
2596: Level: intermediate
2598: Notes:
2599: The assumption here is that the left hand side is of the form A*Xdot (and not A*Xdot + B*X). For other cases, the
2600: user is required to write their own TSComputeIFunction.
2601: This function is intended to be passed to TSSetIFunction() to evaluate the left hand side for linear problems.
2602: The matrix (and optionally the evaluation context) should be passed to TSSetIJacobian().
2604: .seealso: TSSetIFunction(), TSSetIJacobian(), TSComputeIJacobianConstant()
2605: @*/
2606: PetscErrorCode TSComputeIFunctionLinear(TS ts,PetscReal t,Vec X,Vec Xdot,Vec F,void *ctx)
2607: {
2609: Mat A,B;
2610: MatStructure flg2;
2613: TSGetIJacobian(ts,&A,&B,PETSC_NULL,PETSC_NULL);
2614: TSComputeIJacobian(ts,t,X,Xdot,1.0,&A,&B,&flg2,PETSC_TRUE);
2615: MatMult(A,Xdot,F);
2616: return(0);
2617: }
2621: /*@C
2622: TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent.
2624: Collective on TS
2626: Input Arguments:
2627: + ts - time stepping context
2628: . t - time at which to evaluate
2629: . X - state at which to evaluate
2630: . Xdot - time derivative of state vector
2631: . shift - shift to apply
2632: - ctx - context
2634: Output Arguments:
2635: + A - pointer to operator
2636: . B - pointer to preconditioning matrix
2637: - flg - matrix structure flag
2639: Level: intermediate
2641: Notes:
2642: This function is intended to be passed to TSSetIJacobian() to evaluate the Jacobian for linear time-independent problems.
2644: .seealso: TSSetIFunction(), TSSetIJacobian(), TSComputeIFunctionLinear()
2645: @*/
2646: PetscErrorCode TSComputeIJacobianConstant(TS ts,PetscReal t,Vec X,Vec Xdot,PetscReal shift,Mat *A,Mat *B,MatStructure *flg,void *ctx)
2647: {
2650: *flg = SAME_PRECONDITIONER;
2651: return(0);
2652: }
2657: /*@
2658: TSGetConvergedReason - Gets the reason the TS iteration was stopped.
2660: Not Collective
2662: Input Parameter:
2663: . ts - the TS context
2665: Output Parameter:
2666: . reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the
2667: manual pages for the individual convergence tests for complete lists
2669: Level: intermediate
2671: Notes:
2672: Can only be called after the call to TSSolve() is complete.
2674: .keywords: TS, nonlinear, set, convergence, test
2676: .seealso: TSSetConvergenceTest(), TSConvergedReason
2677: @*/
2678: PetscErrorCode TSGetConvergedReason(TS ts,TSConvergedReason *reason)
2679: {
2683: *reason = ts->reason;
2684: return(0);
2685: }
2690: /*@
2691: TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu
2693: Input Parameters:
2694: . ts - the TS context.
2695: . xl - lower bound.
2696: . xu - upper bound.
2698: Notes:
2699: If this routine is not called then the lower and upper bounds are set to
2700: SNES_VI_INF and SNES_VI_NINF respectively during SNESSetUp().
2702: Level: advanced
2704: @*/
2705: PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu)
2706: {
2708: SNES snes;
2711: TSGetSNES(ts,&snes);
2712: SNESVISetVariableBounds(snes,xl,xu);
2713: return(0);
2714: }
2716: #if defined(PETSC_HAVE_MATLAB_ENGINE)
2717: #include <mex.h>
2719: typedef struct {char *funcname; mxArray *ctx;} TSMatlabContext;
2723: /*
2724: TSComputeFunction_Matlab - Calls the function that has been set with
2725: TSSetFunctionMatlab().
2727: Collective on TS
2729: Input Parameters:
2730: + snes - the TS context
2731: - x - input vector
2733: Output Parameter:
2734: . y - function vector, as set by TSSetFunction()
2736: Notes:
2737: TSComputeFunction() is typically used within nonlinear solvers
2738: implementations, so most users would not generally call this routine
2739: themselves.
2741: Level: developer
2743: .keywords: TS, nonlinear, compute, function
2745: .seealso: TSSetFunction(), TSGetFunction()
2746: */
2747: PetscErrorCode TSComputeFunction_Matlab(TS snes,PetscReal time,Vec x,Vec xdot,Vec y, void *ctx)
2748: {
2749: PetscErrorCode ierr;
2750: TSMatlabContext *sctx = (TSMatlabContext *)ctx;
2751: int nlhs = 1,nrhs = 7;
2752: mxArray *plhs[1],*prhs[7];
2753: long long int lx = 0,lxdot = 0,ly = 0,ls = 0;
2763: PetscMemcpy(&ls,&snes,sizeof(snes));
2764: PetscMemcpy(&lx,&x,sizeof(x));
2765: PetscMemcpy(&lxdot,&xdot,sizeof(xdot));
2766: PetscMemcpy(&ly,&y,sizeof(x));
2767: prhs[0] = mxCreateDoubleScalar((double)ls);
2768: prhs[1] = mxCreateDoubleScalar(time);
2769: prhs[2] = mxCreateDoubleScalar((double)lx);
2770: prhs[3] = mxCreateDoubleScalar((double)lxdot);
2771: prhs[4] = mxCreateDoubleScalar((double)ly);
2772: prhs[5] = mxCreateString(sctx->funcname);
2773: prhs[6] = sctx->ctx;
2774: mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSComputeFunctionInternal");
2775: mxGetScalar(plhs[0]);
2776: mxDestroyArray(prhs[0]);
2777: mxDestroyArray(prhs[1]);
2778: mxDestroyArray(prhs[2]);
2779: mxDestroyArray(prhs[3]);
2780: mxDestroyArray(prhs[4]);
2781: mxDestroyArray(prhs[5]);
2782: mxDestroyArray(plhs[0]);
2783: return(0);
2784: }
2789: /*
2790: TSSetFunctionMatlab - Sets the function evaluation routine and function
2791: vector for use by the TS routines in solving ODEs
2792: equations from MATLAB. Here the function is a string containing the name of a MATLAB function
2794: Logically Collective on TS
2796: Input Parameters:
2797: + ts - the TS context
2798: - func - function evaluation routine
2800: Calling sequence of func:
2801: $ func (TS ts,PetscReal time,Vec x,Vec xdot,Vec f,void *ctx);
2803: Level: beginner
2805: .keywords: TS, nonlinear, set, function
2807: .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
2808: */
2809: PetscErrorCode TSSetFunctionMatlab(TS ts,const char *func,mxArray *ctx)
2810: {
2811: PetscErrorCode ierr;
2812: TSMatlabContext *sctx;
2815: /* currently sctx is memory bleed */
2816: PetscMalloc(sizeof(TSMatlabContext),&sctx);
2817: PetscStrallocpy(func,&sctx->funcname);
2818: /*
2819: This should work, but it doesn't
2820: sctx->ctx = ctx;
2821: mexMakeArrayPersistent(sctx->ctx);
2822: */
2823: sctx->ctx = mxDuplicateArray(ctx);
2824: TSSetIFunction(ts,PETSC_NULL,TSComputeFunction_Matlab,sctx);
2825: return(0);
2826: }
2830: /*
2831: TSComputeJacobian_Matlab - Calls the function that has been set with
2832: TSSetJacobianMatlab().
2834: Collective on TS
2836: Input Parameters:
2837: + ts - the TS context
2838: . x - input vector
2839: . A, B - the matrices
2840: - ctx - user context
2842: Output Parameter:
2843: . flag - structure of the matrix
2845: Level: developer
2847: .keywords: TS, nonlinear, compute, function
2849: .seealso: TSSetFunction(), TSGetFunction()
2850: @*/
2851: PetscErrorCode TSComputeJacobian_Matlab(TS ts,PetscReal time,Vec x,Vec xdot,PetscReal shift,Mat *A,Mat *B,MatStructure *flag, void *ctx)
2852: {
2853: PetscErrorCode ierr;
2854: TSMatlabContext *sctx = (TSMatlabContext *)ctx;
2855: int nlhs = 2,nrhs = 9;
2856: mxArray *plhs[2],*prhs[9];
2857: long long int lx = 0,lxdot = 0,lA = 0,ls = 0, lB = 0;
2863: /* call Matlab function in ctx with arguments x and y */
2865: PetscMemcpy(&ls,&ts,sizeof(ts));
2866: PetscMemcpy(&lx,&x,sizeof(x));
2867: PetscMemcpy(&lxdot,&xdot,sizeof(x));
2868: PetscMemcpy(&lA,A,sizeof(x));
2869: PetscMemcpy(&lB,B,sizeof(x));
2870: prhs[0] = mxCreateDoubleScalar((double)ls);
2871: prhs[1] = mxCreateDoubleScalar((double)time);
2872: prhs[2] = mxCreateDoubleScalar((double)lx);
2873: prhs[3] = mxCreateDoubleScalar((double)lxdot);
2874: prhs[4] = mxCreateDoubleScalar((double)shift);
2875: prhs[5] = mxCreateDoubleScalar((double)lA);
2876: prhs[6] = mxCreateDoubleScalar((double)lB);
2877: prhs[7] = mxCreateString(sctx->funcname);
2878: prhs[8] = sctx->ctx;
2879: mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSComputeJacobianInternal");
2880: mxGetScalar(plhs[0]);
2881: *flag = (MatStructure) mxGetScalar(plhs[1]);
2882: mxDestroyArray(prhs[0]);
2883: mxDestroyArray(prhs[1]);
2884: mxDestroyArray(prhs[2]);
2885: mxDestroyArray(prhs[3]);
2886: mxDestroyArray(prhs[4]);
2887: mxDestroyArray(prhs[5]);
2888: mxDestroyArray(prhs[6]);
2889: mxDestroyArray(prhs[7]);
2890: mxDestroyArray(plhs[0]);
2891: mxDestroyArray(plhs[1]);
2892: return(0);
2893: }
2898: /*
2899: TSSetJacobianMatlab - Sets the Jacobian function evaluation routine and two empty Jacobian matrices
2900: vector for use by the TS routines in solving ODEs from MATLAB. Here the function is a string containing the name of a MATLAB function
2902: Logically Collective on TS
2904: Input Parameters:
2905: + ts - the TS context
2906: . A,B - Jacobian matrices
2907: . func - function evaluation routine
2908: - ctx - user context
2910: Calling sequence of func:
2911: $ flag = func (TS ts,PetscReal time,Vec x,Vec xdot,Mat A,Mat B,void *ctx);
2914: Level: developer
2916: .keywords: TS, nonlinear, set, function
2918: .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
2919: */
2920: PetscErrorCode TSSetJacobianMatlab(TS ts,Mat A,Mat B,const char *func,mxArray *ctx)
2921: {
2922: PetscErrorCode ierr;
2923: TSMatlabContext *sctx;
2926: /* currently sctx is memory bleed */
2927: PetscMalloc(sizeof(TSMatlabContext),&sctx);
2928: PetscStrallocpy(func,&sctx->funcname);
2929: /*
2930: This should work, but it doesn't
2931: sctx->ctx = ctx;
2932: mexMakeArrayPersistent(sctx->ctx);
2933: */
2934: sctx->ctx = mxDuplicateArray(ctx);
2935: TSSetIJacobian(ts,A,B,TSComputeJacobian_Matlab,sctx);
2936: return(0);
2937: }
2941: /*
2942: TSMonitor_Matlab - Calls the function that has been set with TSMonitorSetMatlab().
2944: Collective on TS
2946: .seealso: TSSetFunction(), TSGetFunction()
2947: @*/
2948: PetscErrorCode TSMonitor_Matlab(TS ts,PetscInt it, PetscReal time,Vec x, void *ctx)
2949: {
2950: PetscErrorCode ierr;
2951: TSMatlabContext *sctx = (TSMatlabContext *)ctx;
2952: int nlhs = 1,nrhs = 6;
2953: mxArray *plhs[1],*prhs[6];
2954: long long int lx = 0,ls = 0;
2960: PetscMemcpy(&ls,&ts,sizeof(ts));
2961: PetscMemcpy(&lx,&x,sizeof(x));
2962: prhs[0] = mxCreateDoubleScalar((double)ls);
2963: prhs[1] = mxCreateDoubleScalar((double)it);
2964: prhs[2] = mxCreateDoubleScalar((double)time);
2965: prhs[3] = mxCreateDoubleScalar((double)lx);
2966: prhs[4] = mxCreateString(sctx->funcname);
2967: prhs[5] = sctx->ctx;
2968: mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSMonitorInternal");
2969: mxGetScalar(plhs[0]);
2970: mxDestroyArray(prhs[0]);
2971: mxDestroyArray(prhs[1]);
2972: mxDestroyArray(prhs[2]);
2973: mxDestroyArray(prhs[3]);
2974: mxDestroyArray(prhs[4]);
2975: mxDestroyArray(plhs[0]);
2976: return(0);
2977: }
2982: /*
2983: TSMonitorSetMatlab - Sets the monitor function from Matlab
2985: Level: developer
2987: .keywords: TS, nonlinear, set, function
2989: .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
2990: */
2991: PetscErrorCode TSMonitorSetMatlab(TS ts,const char *func,mxArray *ctx)
2992: {
2993: PetscErrorCode ierr;
2994: TSMatlabContext *sctx;
2997: /* currently sctx is memory bleed */
2998: PetscMalloc(sizeof(TSMatlabContext),&sctx);
2999: PetscStrallocpy(func,&sctx->funcname);
3000: /*
3001: This should work, but it doesn't
3002: sctx->ctx = ctx;
3003: mexMakeArrayPersistent(sctx->ctx);
3004: */
3005: sctx->ctx = mxDuplicateArray(ctx);
3006: TSMonitorSet(ts,TSMonitor_Matlab,sctx,PETSC_NULL);
3007: return(0);
3008: }
3009: #endif