Actual source code: ts.c
petsc-3.5.2 2014-09-08
2: #include <petsc-private/tsimpl.h> /*I "petscts.h" I*/
3: #include <petscdmshell.h>
4: #include <petscdmda.h>
5: #include <petscviewer.h>
6: #include <petscdraw.h>
8: /* Logging support */
9: PetscClassId TS_CLASSID, DMTS_CLASSID;
10: PetscLogEvent TS_Step, TS_PseudoComputeTimeStep, TS_FunctionEval, TS_JacobianEval;
12: const char *const TSExactFinalTimeOptions[] = {"STEPOVER","INTERPOLATE","MATCHSTEP","TSExactFinalTimeOption","TS_EXACTFINALTIME_",0};
16: /*
17: TSSetTypeFromOptions - Sets the type of ts from user options.
19: Collective on TS
21: Input Parameter:
22: . ts - The ts
24: Level: intermediate
26: .keywords: TS, set, options, database, type
27: .seealso: TSSetFromOptions(), TSSetType()
28: */
29: static PetscErrorCode TSSetTypeFromOptions(TS ts)
30: {
31: PetscBool opt;
32: const char *defaultType;
33: char typeName[256];
37: if (((PetscObject)ts)->type_name) defaultType = ((PetscObject)ts)->type_name;
38: else defaultType = TSEULER;
40: if (!TSRegisterAllCalled) {TSRegisterAll();}
41: PetscOptionsFList("-ts_type", "TS method"," TSSetType", TSList, defaultType, typeName, 256, &opt);
42: if (opt) {
43: TSSetType(ts, typeName);
44: } else {
45: TSSetType(ts, defaultType);
46: }
47: return(0);
48: }
50: struct _n_TSMonitorDrawCtx {
51: PetscViewer viewer;
52: PetscDrawAxis axis;
53: Vec initialsolution;
54: PetscBool showinitial;
55: PetscInt howoften; /* when > 0 uses step % howoften, when negative only final solution plotted */
56: PetscBool showtimestepandtime;
57: int color;
58: };
62: /*@
63: TSSetFromOptions - Sets various TS parameters from user options.
65: Collective on TS
67: Input Parameter:
68: . ts - the TS context obtained from TSCreate()
70: Options Database Keys:
71: + -ts_type <type> - TSEULER, TSBEULER, TSSUNDIALS, TSPSEUDO, TSCN, TSRK, TSTHETA, TSGL, TSSSP
72: . -ts_max_steps maxsteps - maximum number of time-steps to take
73: . -ts_final_time time - maximum time to compute to
74: . -ts_dt dt - initial time step
75: . -ts_monitor - print information at each timestep
76: . -ts_monitor_lg_timestep - Monitor timestep size graphically
77: . -ts_monitor_lg_solution - Monitor solution graphically
78: . -ts_monitor_lg_error - Monitor error graphically
79: . -ts_monitor_lg_snes_iterations - Monitor number nonlinear iterations for each timestep graphically
80: . -ts_monitor_lg_ksp_iterations - Monitor number nonlinear iterations for each timestep graphically
81: . -ts_monitor_sp_eig - Monitor eigenvalues of linearized operator graphically
82: . -ts_monitor_draw_solution - Monitor solution graphically
83: . -ts_monitor_draw_solution_phase - Monitor solution graphically with phase diagram
84: . -ts_monitor_draw_error - Monitor error graphically
85: . -ts_monitor_solution_binary <filename> - Save each solution to a binary file
86: - -ts_monitor_solution_vtk <filename.vts> - Save each time step to a binary file, use filename-%%03D.vts
88: Developer Note: We should unify all the -ts_monitor options in the way that -xxx_view has been unified
90: Level: beginner
92: .keywords: TS, timestep, set, options, database
94: .seealso: TSGetType()
95: @*/
96: PetscErrorCode TSSetFromOptions(TS ts)
97: {
98: PetscBool opt,flg;
99: PetscErrorCode ierr;
100: PetscViewer monviewer;
101: char monfilename[PETSC_MAX_PATH_LEN];
102: SNES snes;
103: TSAdapt adapt;
104: PetscReal time_step;
105: TSExactFinalTimeOption eftopt;
106: char dir[16];
110: PetscObjectOptionsBegin((PetscObject)ts);
111: /* Handle TS type options */
112: TSSetTypeFromOptions(ts);
114: /* Handle generic TS options */
115: PetscOptionsInt("-ts_max_steps","Maximum number of time steps","TSSetDuration",ts->max_steps,&ts->max_steps,NULL);
116: PetscOptionsReal("-ts_final_time","Time to run to","TSSetDuration",ts->max_time,&ts->max_time,NULL);
117: PetscOptionsReal("-ts_init_time","Initial time","TSSetTime",ts->ptime,&ts->ptime,NULL);
118: PetscOptionsReal("-ts_dt","Initial time step","TSSetTimeStep",ts->time_step,&time_step,&flg);
119: if (flg) {
120: TSSetTimeStep(ts,time_step);
121: }
122: PetscOptionsEnum("-ts_exact_final_time","Option for handling of final time step","TSSetExactFinalTime",TSExactFinalTimeOptions,(PetscEnum)ts->exact_final_time,(PetscEnum*)&eftopt,&flg);
123: if (flg) {TSSetExactFinalTime(ts,eftopt);}
124: PetscOptionsInt("-ts_max_snes_failures","Maximum number of nonlinear solve failures","TSSetMaxSNESFailures",ts->max_snes_failures,&ts->max_snes_failures,NULL);
125: PetscOptionsInt("-ts_max_reject","Maximum number of step rejections before step fails","TSSetMaxStepRejections",ts->max_reject,&ts->max_reject,NULL);
126: PetscOptionsBool("-ts_error_if_step_fails","Error if no step succeeds","TSSetErrorIfStepFails",ts->errorifstepfailed,&ts->errorifstepfailed,NULL);
127: PetscOptionsReal("-ts_rtol","Relative tolerance for local truncation error","TSSetTolerances",ts->rtol,&ts->rtol,NULL);
128: PetscOptionsReal("-ts_atol","Absolute tolerance for local truncation error","TSSetTolerances",ts->atol,&ts->atol,NULL);
130: #if defined(PETSC_HAVE_SAWS)
131: {
132: PetscBool set;
133: flg = PETSC_FALSE;
134: PetscOptionsBool("-ts_saws_block","Block for SAWs memory snooper at end of TSSolve","PetscObjectSAWsBlock",((PetscObject)ts)->amspublishblock,&flg,&set);
135: if (set) {
136: PetscObjectSAWsSetBlock((PetscObject)ts,flg);
137: }
138: }
139: #endif
141: /* Monitor options */
142: PetscOptionsString("-ts_monitor","Monitor timestep size","TSMonitorDefault","stdout",monfilename,PETSC_MAX_PATH_LEN,&flg);
143: if (flg) {
144: PetscViewerASCIIOpen(PetscObjectComm((PetscObject)ts),monfilename,&monviewer);
145: TSMonitorSet(ts,TSMonitorDefault,monviewer,(PetscErrorCode (*)(void**))PetscViewerDestroy);
146: }
147: PetscOptionsString("-ts_monitor_python","Use Python function","TSMonitorSet",0,monfilename,PETSC_MAX_PATH_LEN,&flg);
148: if (flg) {PetscPythonMonitorSet((PetscObject)ts,monfilename);}
150: PetscOptionsName("-ts_monitor_lg_timestep","Monitor timestep size graphically","TSMonitorLGTimeStep",&opt);
151: if (opt) {
152: TSMonitorLGCtx ctx;
153: PetscInt howoften = 1;
155: PetscOptionsInt("-ts_monitor_lg_timestep","Monitor timestep size graphically","TSMonitorLGTimeStep",howoften,&howoften,NULL);
156: TSMonitorLGCtxCreate(PetscObjectComm((PetscObject)ts),0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx);
157: TSMonitorSet(ts,TSMonitorLGTimeStep,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy);
158: }
159: PetscOptionsName("-ts_monitor_lg_solution","Monitor solution graphically","TSMonitorLGSolution",&opt);
160: if (opt) {
161: TSMonitorLGCtx ctx;
162: PetscInt howoften = 1;
164: PetscOptionsInt("-ts_monitor_lg_solution","Monitor solution graphically","TSMonitorLGSolution",howoften,&howoften,NULL);
165: TSMonitorLGCtxCreate(PETSC_COMM_SELF,0,0,PETSC_DECIDE,PETSC_DECIDE,600,400,howoften,&ctx);
166: TSMonitorSet(ts,TSMonitorLGSolution,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy);
167: }
168: PetscOptionsName("-ts_monitor_lg_error","Monitor error graphically","TSMonitorLGError",&opt);
169: if (opt) {
170: TSMonitorLGCtx ctx;
171: PetscInt howoften = 1;
173: PetscOptionsInt("-ts_monitor_lg_error","Monitor error graphically","TSMonitorLGError",howoften,&howoften,NULL);
174: TSMonitorLGCtxCreate(PETSC_COMM_SELF,0,0,PETSC_DECIDE,PETSC_DECIDE,600,400,howoften,&ctx);
175: TSMonitorSet(ts,TSMonitorLGError,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy);
176: }
177: PetscOptionsName("-ts_monitor_lg_snes_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGSNESIterations",&opt);
178: if (opt) {
179: TSMonitorLGCtx ctx;
180: PetscInt howoften = 1;
182: PetscOptionsInt("-ts_monitor_lg_snes_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGSNESIterations",howoften,&howoften,NULL);
183: TSMonitorLGCtxCreate(PETSC_COMM_SELF,0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx);
184: TSMonitorSet(ts,TSMonitorLGSNESIterations,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy);
185: }
186: PetscOptionsName("-ts_monitor_lg_ksp_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGKSPIterations",&opt);
187: if (opt) {
188: TSMonitorLGCtx ctx;
189: PetscInt howoften = 1;
191: PetscOptionsInt("-ts_monitor_lg_ksp_iterations","Monitor number nonlinear iterations for each timestep graphically","TSMonitorLGKSPIterations",howoften,&howoften,NULL);
192: TSMonitorLGCtxCreate(PETSC_COMM_SELF,0,0,PETSC_DECIDE,PETSC_DECIDE,300,300,howoften,&ctx);
193: TSMonitorSet(ts,TSMonitorLGKSPIterations,ctx,(PetscErrorCode (*)(void**))TSMonitorLGCtxDestroy);
194: }
195: PetscOptionsName("-ts_monitor_sp_eig","Monitor eigenvalues of linearized operator graphically","TSMonitorSPEig",&opt);
196: if (opt) {
197: TSMonitorSPEigCtx ctx;
198: PetscInt howoften = 1;
200: PetscOptionsInt("-ts_monitor_sp_eig","Monitor eigenvalues of linearized operator graphically","TSMonitorSPEig",howoften,&howoften,NULL);
201: TSMonitorSPEigCtxCreate(PETSC_COMM_SELF,0,0,PETSC_DECIDE,PETSC_DECIDE,600,400,howoften,&ctx);
202: TSMonitorSet(ts,TSMonitorSPEig,ctx,(PetscErrorCode (*)(void**))TSMonitorSPEigCtxDestroy);
203: }
204: opt = PETSC_FALSE;
205: PetscOptionsName("-ts_monitor_draw_solution","Monitor solution graphically","TSMonitorDrawSolution",&opt);
206: if (opt) {
207: TSMonitorDrawCtx ctx;
208: PetscInt howoften = 1;
210: PetscOptionsInt("-ts_monitor_draw_solution","Monitor solution graphically","TSMonitorDrawSolution",howoften,&howoften,NULL);
211: TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),0,0,PETSC_DECIDE,PETSC_DECIDE,600,400,howoften,&ctx);
212: TSMonitorSet(ts,TSMonitorDrawSolution,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy);
213: }
214: opt = PETSC_FALSE;
215: PetscOptionsName("-ts_monitor_draw_solution_phase","Monitor solution graphically","TSMonitorDrawSolutionPhase",&opt);
216: if (opt) {
217: TSMonitorDrawCtx ctx;
218: PetscReal bounds[4];
219: PetscInt n = 4;
220: PetscDraw draw;
222: PetscOptionsRealArray("-ts_monitor_draw_solution_phase","Monitor solution graphically","TSMonitorDrawSolutionPhase",bounds,&n,NULL);
223: if (n != 4) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Must provide bounding box of phase field");
224: TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),0,0,PETSC_DECIDE,PETSC_DECIDE,600,400,1,&ctx);
225: PetscViewerDrawGetDraw(ctx->viewer,0,&draw);
226: PetscDrawClear(draw);
227: PetscDrawAxisCreate(draw,&ctx->axis);
228: PetscDrawAxisSetLimits(ctx->axis,bounds[0],bounds[2],bounds[1],bounds[3]);
229: PetscDrawAxisSetLabels(ctx->axis,"Phase Diagram","Variable 1","Variable 2");
230: PetscDrawAxisDraw(ctx->axis);
231: /* PetscDrawSetCoordinates(draw,bounds[0],bounds[1],bounds[2],bounds[3]); */
232: TSMonitorSet(ts,TSMonitorDrawSolutionPhase,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy);
233: }
234: opt = PETSC_FALSE;
235: PetscOptionsName("-ts_monitor_draw_error","Monitor error graphically","TSMonitorDrawError",&opt);
236: if (opt) {
237: TSMonitorDrawCtx ctx;
238: PetscInt howoften = 1;
240: PetscOptionsInt("-ts_monitor_draw_error","Monitor error graphically","TSMonitorDrawError",howoften,&howoften,NULL);
241: TSMonitorDrawCtxCreate(PetscObjectComm((PetscObject)ts),0,0,PETSC_DECIDE,PETSC_DECIDE,600,400,howoften,&ctx);
242: TSMonitorSet(ts,TSMonitorDrawError,ctx,(PetscErrorCode (*)(void**))TSMonitorDrawCtxDestroy);
243: }
244: opt = PETSC_FALSE;
245: PetscOptionsString("-ts_monitor_solution_binary","Save each solution to a binary file","TSMonitorSolutionBinary",0,monfilename,PETSC_MAX_PATH_LEN,&flg);
246: if (flg) {
247: PetscViewer ctx;
248: if (monfilename[0]) {
249: PetscViewerBinaryOpen(PetscObjectComm((PetscObject)ts),monfilename,FILE_MODE_WRITE,&ctx);
250: TSMonitorSet(ts,TSMonitorSolutionBinary,ctx,(PetscErrorCode (*)(void**))PetscViewerDestroy);
251: } else {
252: ctx = PETSC_VIEWER_BINARY_(PetscObjectComm((PetscObject)ts));
253: TSMonitorSet(ts,TSMonitorSolutionBinary,ctx,(PetscErrorCode (*)(void**))NULL);
254: }
255: }
256: opt = PETSC_FALSE;
257: PetscOptionsString("-ts_monitor_solution_vtk","Save each time step to a binary file, use filename-%%03D.vts","TSMonitorSolutionVTK",0,monfilename,PETSC_MAX_PATH_LEN,&flg);
258: if (flg) {
259: const char *ptr,*ptr2;
260: char *filetemplate;
261: if (!monfilename[0]) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"-ts_monitor_solution_vtk requires a file template, e.g. filename-%%03D.vts");
262: /* Do some cursory validation of the input. */
263: PetscStrstr(monfilename,"%",(char**)&ptr);
264: if (!ptr) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"-ts_monitor_solution_vtk requires a file template, e.g. filename-%%03D.vts");
265: for (ptr++; ptr && *ptr; ptr++) {
266: PetscStrchr("DdiouxX",*ptr,(char**)&ptr2);
267: if (!ptr2 && (*ptr < '0' || '9' < *ptr)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Invalid file template argument to -ts_monitor_solution_vtk, should look like filename-%%03D.vts");
268: if (ptr2) break;
269: }
270: PetscStrallocpy(monfilename,&filetemplate);
271: TSMonitorSet(ts,TSMonitorSolutionVTK,filetemplate,(PetscErrorCode (*)(void**))TSMonitorSolutionVTKDestroy);
272: }
274: PetscOptionsString("-ts_monitor_dmda_ray","Display a ray of the solution","None","y=0",dir,16,&flg);
275: if (flg) {
276: TSMonitorDMDARayCtx *rayctx;
277: int ray = 0;
278: DMDADirection ddir;
279: DM da;
280: PetscMPIInt rank;
282: if (dir[1] != '=') SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Unknown ray %s",dir);
283: if (dir[0] == 'x') ddir = DMDA_X;
284: else if (dir[0] == 'y') ddir = DMDA_Y;
285: else SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Unknown ray %s",dir);
286: sscanf(dir+2,"%d",&ray);
288: PetscInfo2(((PetscObject)ts),"Displaying DMDA ray %c = %D\n",dir[0],ray);
289: PetscNew(&rayctx);
290: TSGetDM(ts,&da);
291: DMDAGetRay(da,ddir,ray,&rayctx->ray,&rayctx->scatter);
292: MPI_Comm_rank(PetscObjectComm((PetscObject)ts),&rank);
293: if (!rank) {
294: PetscViewerDrawOpen(PETSC_COMM_SELF,0,0,0,0,600,300,&rayctx->viewer);
295: }
296: rayctx->lgctx = NULL;
297: TSMonitorSet(ts,TSMonitorDMDARay,rayctx,TSMonitorDMDARayDestroy);
298: }
299: PetscOptionsString("-ts_monitor_lg_dmda_ray","Display a ray of the solution","None","x=0",dir,16,&flg);
300: if (flg) {
301: TSMonitorDMDARayCtx *rayctx;
302: int ray = 0;
303: DMDADirection ddir;
304: DM da;
305: PetscInt howoften = 1;
307: if (dir[1] != '=') SETERRQ1(PetscObjectComm((PetscObject) ts), PETSC_ERR_ARG_WRONG, "Malformed ray %s", dir);
308: if (dir[0] == 'x') ddir = DMDA_X;
309: else if (dir[0] == 'y') ddir = DMDA_Y;
310: else SETERRQ1(PetscObjectComm((PetscObject) ts), PETSC_ERR_ARG_WRONG, "Unknown ray direction %s", dir);
311: sscanf(dir+2, "%d", &ray);
313: PetscInfo2(((PetscObject) ts),"Displaying LG DMDA ray %c = %D\n", dir[0], ray);
314: PetscNew(&rayctx);
315: TSGetDM(ts, &da);
316: DMDAGetRay(da, ddir, ray, &rayctx->ray, &rayctx->scatter);
317: TSMonitorLGCtxCreate(PETSC_COMM_SELF,0,0,PETSC_DECIDE,PETSC_DECIDE,600,400,howoften,&rayctx->lgctx);
318: TSMonitorSet(ts, TSMonitorLGDMDARay, rayctx, TSMonitorDMDARayDestroy);
319: }
321: /*
322: This code is all wrong. One is creating objects inside the TSSetFromOptions() so if run with the options gui
323: will bleed memory. Also one is using a PetscOptionsBegin() inside a PetscOptionsBegin()
324: */
325: TSGetAdapt(ts,&adapt);
326: TSAdaptSetFromOptions(adapt);
328: TSGetSNES(ts,&snes);
329: if (ts->problem_type == TS_LINEAR) {SNESSetType(snes,SNESKSPONLY);}
331: /* Handle specific TS options */
332: if (ts->ops->setfromoptions) {
333: (*ts->ops->setfromoptions)(ts);
334: }
336: /* process any options handlers added with PetscObjectAddOptionsHandler() */
337: PetscObjectProcessOptionsHandlers((PetscObject)ts);
338: PetscOptionsEnd();
339: return(0);
340: }
345: /*@
346: TSComputeRHSJacobian - Computes the Jacobian matrix that has been
347: set with TSSetRHSJacobian().
349: Collective on TS and Vec
351: Input Parameters:
352: + ts - the TS context
353: . t - current timestep
354: - U - input vector
356: Output Parameters:
357: + A - Jacobian matrix
358: . B - optional preconditioning matrix
359: - flag - flag indicating matrix structure
361: Notes:
362: Most users should not need to explicitly call this routine, as it
363: is used internally within the nonlinear solvers.
365: See KSPSetOperators() for important information about setting the
366: flag parameter.
368: Level: developer
370: .keywords: SNES, compute, Jacobian, matrix
372: .seealso: TSSetRHSJacobian(), KSPSetOperators()
373: @*/
374: PetscErrorCode TSComputeRHSJacobian(TS ts,PetscReal t,Vec U,Mat A,Mat B)
375: {
377: PetscObjectState Ustate;
378: DM dm;
379: DMTS tsdm;
380: TSRHSJacobian rhsjacobianfunc;
381: void *ctx;
382: TSIJacobian ijacobianfunc;
388: TSGetDM(ts,&dm);
389: DMGetDMTS(dm,&tsdm);
390: DMTSGetRHSJacobian(dm,&rhsjacobianfunc,&ctx);
391: DMTSGetIJacobian(dm,&ijacobianfunc,NULL);
392: PetscObjectStateGet((PetscObject)U,&Ustate);
393: if (ts->rhsjacobian.time == t && (ts->problem_type == TS_LINEAR || (ts->rhsjacobian.X == U && ts->rhsjacobian.Xstate == Ustate))) {
394: return(0);
395: }
397: if (!rhsjacobianfunc && !ijacobianfunc) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must call TSSetRHSJacobian() and / or TSSetIJacobian()");
399: if (ts->rhsjacobian.reuse) {
400: MatShift(A,-ts->rhsjacobian.shift);
401: MatScale(A,1./ts->rhsjacobian.scale);
402: if (A != B) {
403: MatShift(B,-ts->rhsjacobian.shift);
404: MatScale(B,1./ts->rhsjacobian.scale);
405: }
406: ts->rhsjacobian.shift = 0;
407: ts->rhsjacobian.scale = 1.;
408: }
410: if (rhsjacobianfunc) {
411: PetscLogEventBegin(TS_JacobianEval,ts,U,A,B);
412: PetscStackPush("TS user Jacobian function");
413: (*rhsjacobianfunc)(ts,t,U,A,B,ctx);
414: PetscStackPop;
415: PetscLogEventEnd(TS_JacobianEval,ts,U,A,B);
416: /* make sure user returned a correct Jacobian and preconditioner */
419: } else {
420: MatZeroEntries(A);
421: if (A != B) {MatZeroEntries(B);}
422: }
423: ts->rhsjacobian.time = t;
424: ts->rhsjacobian.X = U;
425: PetscObjectStateGet((PetscObject)U,&ts->rhsjacobian.Xstate);
426: return(0);
427: }
431: /*@
432: TSComputeRHSFunction - Evaluates the right-hand-side function.
434: Collective on TS and Vec
436: Input Parameters:
437: + ts - the TS context
438: . t - current time
439: - U - state vector
441: Output Parameter:
442: . y - right hand side
444: Note:
445: Most users should not need to explicitly call this routine, as it
446: is used internally within the nonlinear solvers.
448: Level: developer
450: .keywords: TS, compute
452: .seealso: TSSetRHSFunction(), TSComputeIFunction()
453: @*/
454: PetscErrorCode TSComputeRHSFunction(TS ts,PetscReal t,Vec U,Vec y)
455: {
457: TSRHSFunction rhsfunction;
458: TSIFunction ifunction;
459: void *ctx;
460: DM dm;
466: TSGetDM(ts,&dm);
467: DMTSGetRHSFunction(dm,&rhsfunction,&ctx);
468: DMTSGetIFunction(dm,&ifunction,NULL);
470: if (!rhsfunction && !ifunction) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must call TSSetRHSFunction() and / or TSSetIFunction()");
472: PetscLogEventBegin(TS_FunctionEval,ts,U,y,0);
473: if (rhsfunction) {
474: PetscStackPush("TS user right-hand-side function");
475: (*rhsfunction)(ts,t,U,y,ctx);
476: PetscStackPop;
477: } else {
478: VecZeroEntries(y);
479: }
481: PetscLogEventEnd(TS_FunctionEval,ts,U,y,0);
482: return(0);
483: }
487: /*@
488: TSComputeSolutionFunction - Evaluates the solution function.
490: Collective on TS and Vec
492: Input Parameters:
493: + ts - the TS context
494: - t - current time
496: Output Parameter:
497: . U - the solution
499: Note:
500: Most users should not need to explicitly call this routine, as it
501: is used internally within the nonlinear solvers.
503: Level: developer
505: .keywords: TS, compute
507: .seealso: TSSetSolutionFunction(), TSSetRHSFunction(), TSComputeIFunction()
508: @*/
509: PetscErrorCode TSComputeSolutionFunction(TS ts,PetscReal t,Vec U)
510: {
511: PetscErrorCode ierr;
512: TSSolutionFunction solutionfunction;
513: void *ctx;
514: DM dm;
519: TSGetDM(ts,&dm);
520: DMTSGetSolutionFunction(dm,&solutionfunction,&ctx);
522: if (solutionfunction) {
523: PetscStackPush("TS user solution function");
524: (*solutionfunction)(ts,t,U,ctx);
525: PetscStackPop;
526: }
527: return(0);
528: }
531: /*@
532: TSComputeForcingFunction - Evaluates the forcing function.
534: Collective on TS and Vec
536: Input Parameters:
537: + ts - the TS context
538: - t - current time
540: Output Parameter:
541: . U - the function value
543: Note:
544: Most users should not need to explicitly call this routine, as it
545: is used internally within the nonlinear solvers.
547: Level: developer
549: .keywords: TS, compute
551: .seealso: TSSetSolutionFunction(), TSSetRHSFunction(), TSComputeIFunction()
552: @*/
553: PetscErrorCode TSComputeForcingFunction(TS ts,PetscReal t,Vec U)
554: {
555: PetscErrorCode ierr, (*forcing)(TS,PetscReal,Vec,void*);
556: void *ctx;
557: DM dm;
562: TSGetDM(ts,&dm);
563: DMTSGetForcingFunction(dm,&forcing,&ctx);
565: if (forcing) {
566: PetscStackPush("TS user forcing function");
567: (*forcing)(ts,t,U,ctx);
568: PetscStackPop;
569: }
570: return(0);
571: }
575: static PetscErrorCode TSGetRHSVec_Private(TS ts,Vec *Frhs)
576: {
577: Vec F;
581: *Frhs = NULL;
582: TSGetIFunction(ts,&F,NULL,NULL);
583: if (!ts->Frhs) {
584: VecDuplicate(F,&ts->Frhs);
585: }
586: *Frhs = ts->Frhs;
587: return(0);
588: }
592: static PetscErrorCode TSGetRHSMats_Private(TS ts,Mat *Arhs,Mat *Brhs)
593: {
594: Mat A,B;
598: if (Arhs) *Arhs = NULL;
599: if (Brhs) *Brhs = NULL;
600: TSGetIJacobian(ts,&A,&B,NULL,NULL);
601: if (Arhs) {
602: if (!ts->Arhs) {
603: MatDuplicate(A,MAT_DO_NOT_COPY_VALUES,&ts->Arhs);
604: }
605: *Arhs = ts->Arhs;
606: }
607: if (Brhs) {
608: if (!ts->Brhs) {
609: if (A != B) {
610: MatDuplicate(B,MAT_DO_NOT_COPY_VALUES,&ts->Brhs);
611: } else {
612: ts->Brhs = ts->Arhs;
613: PetscObjectReference((PetscObject)ts->Arhs);
614: }
615: }
616: *Brhs = ts->Brhs;
617: }
618: return(0);
619: }
623: /*@
624: TSComputeIFunction - Evaluates the DAE residual written in implicit form F(t,U,Udot)=0
626: Collective on TS and Vec
628: Input Parameters:
629: + ts - the TS context
630: . t - current time
631: . U - state vector
632: . Udot - time derivative of state vector
633: - imex - flag indicates if the method is IMEX so that the RHSFunction should be kept separate
635: Output Parameter:
636: . Y - right hand side
638: Note:
639: Most users should not need to explicitly call this routine, as it
640: is used internally within the nonlinear solvers.
642: If the user did did not write their equations in implicit form, this
643: function recasts them in implicit form.
645: Level: developer
647: .keywords: TS, compute
649: .seealso: TSSetIFunction(), TSComputeRHSFunction()
650: @*/
651: PetscErrorCode TSComputeIFunction(TS ts,PetscReal t,Vec U,Vec Udot,Vec Y,PetscBool imex)
652: {
654: TSIFunction ifunction;
655: TSRHSFunction rhsfunction;
656: void *ctx;
657: DM dm;
665: TSGetDM(ts,&dm);
666: DMTSGetIFunction(dm,&ifunction,&ctx);
667: DMTSGetRHSFunction(dm,&rhsfunction,NULL);
669: if (!rhsfunction && !ifunction) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must call TSSetRHSFunction() and / or TSSetIFunction()");
671: PetscLogEventBegin(TS_FunctionEval,ts,U,Udot,Y);
672: if (ifunction) {
673: PetscStackPush("TS user implicit function");
674: (*ifunction)(ts,t,U,Udot,Y,ctx);
675: PetscStackPop;
676: }
677: if (imex) {
678: if (!ifunction) {
679: VecCopy(Udot,Y);
680: }
681: } else if (rhsfunction) {
682: if (ifunction) {
683: Vec Frhs;
684: TSGetRHSVec_Private(ts,&Frhs);
685: TSComputeRHSFunction(ts,t,U,Frhs);
686: VecAXPY(Y,-1,Frhs);
687: } else {
688: TSComputeRHSFunction(ts,t,U,Y);
689: VecAYPX(Y,-1,Udot);
690: }
691: }
692: PetscLogEventEnd(TS_FunctionEval,ts,U,Udot,Y);
693: return(0);
694: }
698: /*@
699: TSComputeIJacobian - Evaluates the Jacobian of the DAE
701: Collective on TS and Vec
703: Input
704: Input Parameters:
705: + ts - the TS context
706: . t - current timestep
707: . U - state vector
708: . Udot - time derivative of state vector
709: . shift - shift to apply, see note below
710: - imex - flag indicates if the method is IMEX so that the RHSJacobian should be kept separate
712: Output Parameters:
713: + A - Jacobian matrix
714: . B - optional preconditioning matrix
715: - flag - flag indicating matrix structure
717: Notes:
718: If F(t,U,Udot)=0 is the DAE, the required Jacobian is
720: dF/dU + shift*dF/dUdot
722: Most users should not need to explicitly call this routine, as it
723: is used internally within the nonlinear solvers.
725: Level: developer
727: .keywords: TS, compute, Jacobian, matrix
729: .seealso: TSSetIJacobian()
730: @*/
731: PetscErrorCode TSComputeIJacobian(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat A,Mat B,PetscBool imex)
732: {
734: TSIJacobian ijacobian;
735: TSRHSJacobian rhsjacobian;
736: DM dm;
737: void *ctx;
748: TSGetDM(ts,&dm);
749: DMTSGetIJacobian(dm,&ijacobian,&ctx);
750: DMTSGetRHSJacobian(dm,&rhsjacobian,NULL);
752: if (!rhsjacobian && !ijacobian) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_USER,"Must call TSSetRHSJacobian() and / or TSSetIJacobian()");
754: PetscLogEventBegin(TS_JacobianEval,ts,U,A,B);
755: if (ijacobian) {
756: PetscStackPush("TS user implicit Jacobian");
757: (*ijacobian)(ts,t,U,Udot,shift,A,B,ctx);
758: PetscStackPop;
759: /* make sure user returned a correct Jacobian and preconditioner */
762: }
763: if (imex) {
764: if (!ijacobian) { /* system was written as Udot = G(t,U) */
765: MatZeroEntries(A);
766: MatShift(A,shift);
767: if (A != B) {
768: MatZeroEntries(B);
769: MatShift(B,shift);
770: }
771: }
772: } else {
773: Mat Arhs = NULL,Brhs = NULL;
774: if (rhsjacobian) {
775: if (ijacobian) {
776: TSGetRHSMats_Private(ts,&Arhs,&Brhs);
777: } else {
778: TSGetIJacobian(ts,&Arhs,&Brhs,NULL,NULL);
779: }
780: TSComputeRHSJacobian(ts,t,U,Arhs,Brhs);
781: }
782: if (Arhs == A) { /* No IJacobian, so we only have the RHS matrix */
783: ts->rhsjacobian.scale = -1;
784: ts->rhsjacobian.shift = shift;
785: MatScale(A,-1);
786: MatShift(A,shift);
787: if (A != B) {
788: MatScale(B,-1);
789: MatShift(B,shift);
790: }
791: } else if (Arhs) { /* Both IJacobian and RHSJacobian */
792: MatStructure axpy = DIFFERENT_NONZERO_PATTERN;
793: if (!ijacobian) { /* No IJacobian provided, but we have a separate RHS matrix */
794: MatZeroEntries(A);
795: MatShift(A,shift);
796: if (A != B) {
797: MatZeroEntries(B);
798: MatShift(B,shift);
799: }
800: }
801: MatAXPY(A,-1,Arhs,axpy);
802: if (A != B) {
803: MatAXPY(B,-1,Brhs,axpy);
804: }
805: }
806: }
807: PetscLogEventEnd(TS_JacobianEval,ts,U,A,B);
808: return(0);
809: }
813: /*@C
814: TSSetRHSFunction - Sets the routine for evaluating the function,
815: where U_t = G(t,u).
817: Logically Collective on TS
819: Input Parameters:
820: + ts - the TS context obtained from TSCreate()
821: . r - vector to put the computed right hand side (or NULL to have it created)
822: . f - routine for evaluating the right-hand-side function
823: - ctx - [optional] user-defined context for private data for the
824: function evaluation routine (may be NULL)
826: Calling sequence of func:
827: $ func (TS ts,PetscReal t,Vec u,Vec F,void *ctx);
829: + t - current timestep
830: . u - input vector
831: . F - function vector
832: - ctx - [optional] user-defined function context
834: Level: beginner
836: .keywords: TS, timestep, set, right-hand-side, function
838: .seealso: TSSetRHSJacobian(), TSSetIJacobian()
839: @*/
840: PetscErrorCode TSSetRHSFunction(TS ts,Vec r,PetscErrorCode (*f)(TS,PetscReal,Vec,Vec,void*),void *ctx)
841: {
843: SNES snes;
844: Vec ralloc = NULL;
845: DM dm;
851: TSGetDM(ts,&dm);
852: DMTSSetRHSFunction(dm,f,ctx);
853: TSGetSNES(ts,&snes);
854: if (!r && !ts->dm && ts->vec_sol) {
855: VecDuplicate(ts->vec_sol,&ralloc);
856: r = ralloc;
857: }
858: SNESSetFunction(snes,r,SNESTSFormFunction,ts);
859: VecDestroy(&ralloc);
860: return(0);
861: }
865: /*@C
866: TSSetSolutionFunction - Provide a function that computes the solution of the ODE or DAE
868: Logically Collective on TS
870: Input Parameters:
871: + ts - the TS context obtained from TSCreate()
872: . f - routine for evaluating the solution
873: - ctx - [optional] user-defined context for private data for the
874: function evaluation routine (may be NULL)
876: Calling sequence of func:
877: $ func (TS ts,PetscReal t,Vec u,void *ctx);
879: + t - current timestep
880: . u - output vector
881: - ctx - [optional] user-defined function context
883: Notes:
884: This routine is used for testing accuracy of time integration schemes when you already know the solution.
885: If analytic solutions are not known for your system, consider using the Method of Manufactured Solutions to
886: create closed-form solutions with non-physical forcing terms.
888: For low-dimensional problems solved in serial, such as small discrete systems, TSMonitorLGError() can be used to monitor the error history.
890: Level: beginner
892: .keywords: TS, timestep, set, right-hand-side, function
894: .seealso: TSSetRHSJacobian(), TSSetIJacobian(), TSComputeSolutionFunction(), TSSetForcingFunction()
895: @*/
896: PetscErrorCode TSSetSolutionFunction(TS ts,PetscErrorCode (*f)(TS,PetscReal,Vec,void*),void *ctx)
897: {
899: DM dm;
903: TSGetDM(ts,&dm);
904: DMTSSetSolutionFunction(dm,f,ctx);
905: return(0);
906: }
910: /*@C
911: TSSetForcingFunction - Provide a function that computes a forcing term for a ODE or PDE
913: Logically Collective on TS
915: Input Parameters:
916: + ts - the TS context obtained from TSCreate()
917: . f - routine for evaluating the forcing function
918: - ctx - [optional] user-defined context for private data for the
919: function evaluation routine (may be NULL)
921: Calling sequence of func:
922: $ func (TS ts,PetscReal t,Vec u,void *ctx);
924: + t - current timestep
925: . u - output vector
926: - ctx - [optional] user-defined function context
928: Notes:
929: This routine is useful for testing accuracy of time integration schemes when using the Method of Manufactured Solutions to
930: create closed-form solutions with a non-physical forcing term.
932: For low-dimensional problems solved in serial, such as small discrete systems, TSMonitorLGError() can be used to monitor the error history.
934: Level: beginner
936: .keywords: TS, timestep, set, right-hand-side, function
938: .seealso: TSSetRHSJacobian(), TSSetIJacobian(), TSComputeSolutionFunction(), TSSetSolutionFunction()
939: @*/
940: PetscErrorCode TSSetForcingFunction(TS ts,PetscErrorCode (*f)(TS,PetscReal,Vec,void*),void *ctx)
941: {
943: DM dm;
947: TSGetDM(ts,&dm);
948: DMTSSetForcingFunction(dm,f,ctx);
949: return(0);
950: }
954: /*@C
955: TSSetRHSJacobian - Sets the function to compute the Jacobian of F,
956: where U_t = G(U,t), as well as the location to store the matrix.
958: Logically Collective on TS
960: Input Parameters:
961: + ts - the TS context obtained from TSCreate()
962: . Amat - (approximate) Jacobian matrix
963: . Pmat - matrix from which preconditioner is to be constructed (usually the same as Amat)
964: . f - the Jacobian evaluation routine
965: - ctx - [optional] user-defined context for private data for the
966: Jacobian evaluation routine (may be NULL)
968: Calling sequence of func:
969: $ func (TS ts,PetscReal t,Vec u,Mat *A,Mat *B,MatStructure *flag,void *ctx);
971: + t - current timestep
972: . u - input vector
973: . Amat - (approximate) Jacobian matrix
974: . Pmat - matrix from which preconditioner is to be constructed (usually the same as Amat)
975: . flag - flag indicating information about the preconditioner matrix
976: structure (same as flag in KSPSetOperators())
977: - ctx - [optional] user-defined context for matrix evaluation routine
979: Notes:
980: See KSPSetOperators() for important information about setting the flag
981: output parameter in the routine func(). Be sure to read this information!
983: The routine func() takes Mat * as the matrix arguments rather than Mat.
984: This allows the matrix evaluation routine to replace A and/or B with a
985: completely new matrix structure (not just different matrix elements)
986: when appropriate, for instance, if the nonzero structure is changing
987: throughout the global iterations.
989: Level: beginner
991: .keywords: TS, timestep, set, right-hand-side, Jacobian
993: .seealso: SNESComputeJacobianDefaultColor(), TSSetRHSFunction(), TSRHSJacobianSetReuse()
995: @*/
996: PetscErrorCode TSSetRHSJacobian(TS ts,Mat Amat,Mat Pmat,TSRHSJacobian f,void *ctx)
997: {
999: SNES snes;
1000: DM dm;
1001: TSIJacobian ijacobian;
1010: TSGetDM(ts,&dm);
1011: DMTSSetRHSJacobian(dm,f,ctx);
1012: if (f == TSComputeRHSJacobianConstant) {
1013: /* Handle this case automatically for the user; otherwise user should call themselves. */
1014: TSRHSJacobianSetReuse(ts,PETSC_TRUE);
1015: }
1016: DMTSGetIJacobian(dm,&ijacobian,NULL);
1017: TSGetSNES(ts,&snes);
1018: if (!ijacobian) {
1019: SNESSetJacobian(snes,Amat,Pmat,SNESTSFormJacobian,ts);
1020: }
1021: if (Amat) {
1022: PetscObjectReference((PetscObject)Amat);
1023: MatDestroy(&ts->Arhs);
1025: ts->Arhs = Amat;
1026: }
1027: if (Pmat) {
1028: PetscObjectReference((PetscObject)Pmat);
1029: MatDestroy(&ts->Brhs);
1031: ts->Brhs = Pmat;
1032: }
1033: return(0);
1034: }
1039: /*@C
1040: TSSetIFunction - Set the function to compute F(t,U,U_t) where F() = 0 is the DAE to be solved.
1042: Logically Collective on TS
1044: Input Parameters:
1045: + ts - the TS context obtained from TSCreate()
1046: . r - vector to hold the residual (or NULL to have it created internally)
1047: . f - the function evaluation routine
1048: - ctx - user-defined context for private data for the function evaluation routine (may be NULL)
1050: Calling sequence of f:
1051: $ f(TS ts,PetscReal t,Vec u,Vec u_t,Vec F,ctx);
1053: + t - time at step/stage being solved
1054: . u - state vector
1055: . u_t - time derivative of state vector
1056: . F - function vector
1057: - ctx - [optional] user-defined context for matrix evaluation routine
1059: Important:
1060: The user MUST call either this routine, TSSetRHSFunction(). This routine must be used when not solving an ODE, for example a DAE.
1062: Level: beginner
1064: .keywords: TS, timestep, set, DAE, Jacobian
1066: .seealso: TSSetRHSJacobian(), TSSetRHSFunction(), TSSetIJacobian()
1067: @*/
1068: PetscErrorCode TSSetIFunction(TS ts,Vec res,TSIFunction f,void *ctx)
1069: {
1071: SNES snes;
1072: Vec resalloc = NULL;
1073: DM dm;
1079: TSGetDM(ts,&dm);
1080: DMTSSetIFunction(dm,f,ctx);
1082: TSGetSNES(ts,&snes);
1083: if (!res && !ts->dm && ts->vec_sol) {
1084: VecDuplicate(ts->vec_sol,&resalloc);
1085: res = resalloc;
1086: }
1087: SNESSetFunction(snes,res,SNESTSFormFunction,ts);
1088: VecDestroy(&resalloc);
1089: return(0);
1090: }
1094: /*@C
1095: TSGetIFunction - Returns the vector where the implicit residual is stored and the function/contex to compute it.
1097: Not Collective
1099: Input Parameter:
1100: . ts - the TS context
1102: Output Parameter:
1103: + r - vector to hold residual (or NULL)
1104: . func - the function to compute residual (or NULL)
1105: - ctx - the function context (or NULL)
1107: Level: advanced
1109: .keywords: TS, nonlinear, get, function
1111: .seealso: TSSetIFunction(), SNESGetFunction()
1112: @*/
1113: PetscErrorCode TSGetIFunction(TS ts,Vec *r,TSIFunction *func,void **ctx)
1114: {
1116: SNES snes;
1117: DM dm;
1121: TSGetSNES(ts,&snes);
1122: SNESGetFunction(snes,r,NULL,NULL);
1123: TSGetDM(ts,&dm);
1124: DMTSGetIFunction(dm,func,ctx);
1125: return(0);
1126: }
1130: /*@C
1131: TSGetRHSFunction - Returns the vector where the right hand side is stored and the function/context to compute it.
1133: Not Collective
1135: Input Parameter:
1136: . ts - the TS context
1138: Output Parameter:
1139: + r - vector to hold computed right hand side (or NULL)
1140: . func - the function to compute right hand side (or NULL)
1141: - ctx - the function context (or NULL)
1143: Level: advanced
1145: .keywords: TS, nonlinear, get, function
1147: .seealso: TSSetRhsfunction(), SNESGetFunction()
1148: @*/
1149: PetscErrorCode TSGetRHSFunction(TS ts,Vec *r,TSRHSFunction *func,void **ctx)
1150: {
1152: SNES snes;
1153: DM dm;
1157: TSGetSNES(ts,&snes);
1158: SNESGetFunction(snes,r,NULL,NULL);
1159: TSGetDM(ts,&dm);
1160: DMTSGetRHSFunction(dm,func,ctx);
1161: return(0);
1162: }
1166: /*@C
1167: TSSetIJacobian - Set the function to compute the matrix dF/dU + a*dF/dU_t where F(t,U,U_t) is the function
1168: you provided with TSSetIFunction().
1170: Logically Collective on TS
1172: Input Parameters:
1173: + ts - the TS context obtained from TSCreate()
1174: . Amat - (approximate) Jacobian matrix
1175: . Pmat - matrix used to compute preconditioner (usually the same as Amat)
1176: . f - the Jacobian evaluation routine
1177: - ctx - user-defined context for private data for the Jacobian evaluation routine (may be NULL)
1179: Calling sequence of f:
1180: $ f(TS ts,PetscReal t,Vec U,Vec U_t,PetscReal a,Mat *Amat,Mat *Pmat,MatStructure *flag,void *ctx);
1182: + t - time at step/stage being solved
1183: . U - state vector
1184: . U_t - time derivative of state vector
1185: . a - shift
1186: . Amat - (approximate) Jacobian of F(t,U,W+a*U), equivalent to dF/dU + a*dF/dU_t
1187: . Pmat - matrix used for constructing preconditioner, usually the same as Amat
1188: . flag - flag indicating information about the preconditioner matrix
1189: structure (same as flag in KSPSetOperators())
1190: - ctx - [optional] user-defined context for matrix evaluation routine
1192: Notes:
1193: The matrices Amat and Pmat are exactly the matrices that are used by SNES for the nonlinear solve.
1195: The matrix dF/dU + a*dF/dU_t you provide turns out to be
1196: the Jacobian of F(t,U,W+a*U) where F(t,U,U_t) = 0 is the DAE to be solved.
1197: The time integrator internally approximates U_t by W+a*U where the positive "shift"
1198: a and vector W depend on the integration method, step size, and past states. For example with
1199: the backward Euler method a = 1/dt and W = -a*U(previous timestep) so
1200: W + a*U = a*(U - U(previous timestep)) = (U - U(previous timestep))/dt
1202: Level: beginner
1204: .keywords: TS, timestep, DAE, Jacobian
1206: .seealso: TSSetIFunction(), TSSetRHSJacobian(), SNESComputeJacobianDefaultColor(), SNESComputeJacobianDefault()
1208: @*/
1209: PetscErrorCode TSSetIJacobian(TS ts,Mat Amat,Mat Pmat,TSIJacobian f,void *ctx)
1210: {
1212: SNES snes;
1213: DM dm;
1222: TSGetDM(ts,&dm);
1223: DMTSSetIJacobian(dm,f,ctx);
1225: TSGetSNES(ts,&snes);
1226: SNESSetJacobian(snes,Amat,Pmat,SNESTSFormJacobian,ts);
1227: return(0);
1228: }
1232: /*@
1233: TSRHSJacobianSetReuse - restore RHS Jacobian before re-evaluating. Without this flag, TS will change the sign and
1234: shift the RHS Jacobian for a finite-time-step implicit solve, in which case the user function will need to recompute
1235: the entire Jacobian. The reuse flag must be set if the evaluation function will assume that the matrix entries have
1236: not been changed by the TS.
1238: Logically Collective
1240: Input Arguments:
1241: + ts - TS context obtained from TSCreate()
1242: - reuse - PETSC_TRUE if the RHS Jacobian
1244: Level: intermediate
1246: .seealso: TSSetRHSJacobian(), TSComputeRHSJacobianConstant()
1247: @*/
1248: PetscErrorCode TSRHSJacobianSetReuse(TS ts,PetscBool reuse)
1249: {
1251: ts->rhsjacobian.reuse = reuse;
1252: return(0);
1253: }
1257: /*@C
1258: TSLoad - Loads a KSP that has been stored in binary with KSPView().
1260: Collective on PetscViewer
1262: Input Parameters:
1263: + newdm - the newly loaded TS, this needs to have been created with TSCreate() or
1264: some related function before a call to TSLoad().
1265: - viewer - binary file viewer, obtained from PetscViewerBinaryOpen()
1267: Level: intermediate
1269: Notes:
1270: The type is determined by the data in the file, any type set into the TS before this call is ignored.
1272: Notes for advanced users:
1273: Most users should not need to know the details of the binary storage
1274: format, since TSLoad() and TSView() completely hide these details.
1275: But for anyone who's interested, the standard binary matrix storage
1276: format is
1277: .vb
1278: has not yet been determined
1279: .ve
1281: .seealso: PetscViewerBinaryOpen(), TSView(), MatLoad(), VecLoad()
1282: @*/
1283: PetscErrorCode TSLoad(TS ts, PetscViewer viewer)
1284: {
1286: PetscBool isbinary;
1287: PetscInt classid;
1288: char type[256];
1289: DMTS sdm;
1290: DM dm;
1295: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
1296: if (!isbinary) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen()");
1298: PetscViewerBinaryRead(viewer,&classid,1,PETSC_INT);
1299: if (classid != TS_FILE_CLASSID) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_WRONG,"Not TS next in file");
1300: PetscViewerBinaryRead(viewer,type,256,PETSC_CHAR);
1301: TSSetType(ts, type);
1302: if (ts->ops->load) {
1303: (*ts->ops->load)(ts,viewer);
1304: }
1305: DMCreate(PetscObjectComm((PetscObject)ts),&dm);
1306: DMLoad(dm,viewer);
1307: TSSetDM(ts,dm);
1308: DMCreateGlobalVector(ts->dm,&ts->vec_sol);
1309: VecLoad(ts->vec_sol,viewer);
1310: DMGetDMTS(ts->dm,&sdm);
1311: DMTSLoad(sdm,viewer);
1312: return(0);
1313: }
1315: #include <petscdraw.h>
1316: #if defined(PETSC_HAVE_SAWS)
1317: #include <petscviewersaws.h>
1318: #endif
1321: /*@C
1322: TSView - Prints the TS data structure.
1324: Collective on TS
1326: Input Parameters:
1327: + ts - the TS context obtained from TSCreate()
1328: - viewer - visualization context
1330: Options Database Key:
1331: . -ts_view - calls TSView() at end of TSStep()
1333: Notes:
1334: The available visualization contexts include
1335: + PETSC_VIEWER_STDOUT_SELF - standard output (default)
1336: - PETSC_VIEWER_STDOUT_WORLD - synchronized standard
1337: output where only the first processor opens
1338: the file. All other processors send their
1339: data to the first processor to print.
1341: The user can open an alternative visualization context with
1342: PetscViewerASCIIOpen() - output to a specified file.
1344: Level: beginner
1346: .keywords: TS, timestep, view
1348: .seealso: PetscViewerASCIIOpen()
1349: @*/
1350: PetscErrorCode TSView(TS ts,PetscViewer viewer)
1351: {
1353: TSType type;
1354: PetscBool iascii,isstring,isundials,isbinary,isdraw;
1355: DMTS sdm;
1356: #if defined(PETSC_HAVE_SAWS)
1357: PetscBool isams;
1358: #endif
1362: if (!viewer) {
1363: PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)ts),&viewer);
1364: }
1368: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);
1369: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);
1370: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);
1371: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);
1372: #if defined(PETSC_HAVE_SAWS)
1373: PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSAWS,&isams);
1374: #endif
1375: if (iascii) {
1376: PetscObjectPrintClassNamePrefixType((PetscObject)ts,viewer);
1377: PetscViewerASCIIPrintf(viewer," maximum steps=%D\n",ts->max_steps);
1378: PetscViewerASCIIPrintf(viewer," maximum time=%g\n",(double)ts->max_time);
1379: if (ts->problem_type == TS_NONLINEAR) {
1380: PetscViewerASCIIPrintf(viewer," total number of nonlinear solver iterations=%D\n",ts->snes_its);
1381: PetscViewerASCIIPrintf(viewer," total number of nonlinear solve failures=%D\n",ts->num_snes_failures);
1382: }
1383: PetscViewerASCIIPrintf(viewer," total number of linear solver iterations=%D\n",ts->ksp_its);
1384: PetscViewerASCIIPrintf(viewer," total number of rejected steps=%D\n",ts->reject);
1385: DMGetDMTS(ts->dm,&sdm);
1386: DMTSView(sdm,viewer);
1387: if (ts->ops->view) {
1388: PetscViewerASCIIPushTab(viewer);
1389: (*ts->ops->view)(ts,viewer);
1390: PetscViewerASCIIPopTab(viewer);
1391: }
1392: } else if (isstring) {
1393: TSGetType(ts,&type);
1394: PetscViewerStringSPrintf(viewer," %-7.7s",type);
1395: } else if (isbinary) {
1396: PetscInt classid = TS_FILE_CLASSID;
1397: MPI_Comm comm;
1398: PetscMPIInt rank;
1399: char type[256];
1401: PetscObjectGetComm((PetscObject)ts,&comm);
1402: MPI_Comm_rank(comm,&rank);
1403: if (!rank) {
1404: PetscViewerBinaryWrite(viewer,&classid,1,PETSC_INT,PETSC_FALSE);
1405: PetscStrncpy(type,((PetscObject)ts)->type_name,256);
1406: PetscViewerBinaryWrite(viewer,type,256,PETSC_CHAR,PETSC_FALSE);
1407: }
1408: if (ts->ops->view) {
1409: (*ts->ops->view)(ts,viewer);
1410: }
1411: DMView(ts->dm,viewer);
1412: VecView(ts->vec_sol,viewer);
1413: DMGetDMTS(ts->dm,&sdm);
1414: DMTSView(sdm,viewer);
1415: } else if (isdraw) {
1416: PetscDraw draw;
1417: char str[36];
1418: PetscReal x,y,bottom,h;
1420: PetscViewerDrawGetDraw(viewer,0,&draw);
1421: PetscDrawGetCurrentPoint(draw,&x,&y);
1422: PetscStrcpy(str,"TS: ");
1423: PetscStrcat(str,((PetscObject)ts)->type_name);
1424: PetscDrawBoxedString(draw,x,y,PETSC_DRAW_BLACK,PETSC_DRAW_BLACK,str,NULL,&h);
1425: bottom = y - h;
1426: PetscDrawPushCurrentPoint(draw,x,bottom);
1427: if (ts->ops->view) {
1428: (*ts->ops->view)(ts,viewer);
1429: }
1430: PetscDrawPopCurrentPoint(draw);
1431: #if defined(PETSC_HAVE_SAWS)
1432: } else if (isams) {
1433: PetscMPIInt rank;
1434: const char *name;
1436: PetscObjectGetName((PetscObject)ts,&name);
1437: MPI_Comm_rank(PETSC_COMM_WORLD,&rank);
1438: if (!((PetscObject)ts)->amsmem && !rank) {
1439: char dir[1024];
1441: PetscObjectViewSAWs((PetscObject)ts,viewer);
1442: PetscSNPrintf(dir,1024,"/PETSc/Objects/%s/time_step",name);
1443: PetscStackCallSAWs(SAWs_Register,(dir,&ts->steps,1,SAWs_READ,SAWs_INT));
1444: PetscSNPrintf(dir,1024,"/PETSc/Objects/%s/time",name);
1445: PetscStackCallSAWs(SAWs_Register,(dir,&ts->ptime,1,SAWs_READ,SAWs_DOUBLE));
1446: }
1447: if (ts->ops->view) {
1448: (*ts->ops->view)(ts,viewer);
1449: }
1450: #endif
1451: }
1453: PetscViewerASCIIPushTab(viewer);
1454: PetscObjectTypeCompare((PetscObject)ts,TSSUNDIALS,&isundials);
1455: PetscViewerASCIIPopTab(viewer);
1456: return(0);
1457: }
1462: /*@
1463: TSSetApplicationContext - Sets an optional user-defined context for
1464: the timesteppers.
1466: Logically Collective on TS
1468: Input Parameters:
1469: + ts - the TS context obtained from TSCreate()
1470: - usrP - optional user context
1472: Level: intermediate
1474: .keywords: TS, timestep, set, application, context
1476: .seealso: TSGetApplicationContext()
1477: @*/
1478: PetscErrorCode TSSetApplicationContext(TS ts,void *usrP)
1479: {
1482: ts->user = usrP;
1483: return(0);
1484: }
1488: /*@
1489: TSGetApplicationContext - Gets the user-defined context for the
1490: timestepper.
1492: Not Collective
1494: Input Parameter:
1495: . ts - the TS context obtained from TSCreate()
1497: Output Parameter:
1498: . usrP - user context
1500: Level: intermediate
1502: .keywords: TS, timestep, get, application, context
1504: .seealso: TSSetApplicationContext()
1505: @*/
1506: PetscErrorCode TSGetApplicationContext(TS ts,void *usrP)
1507: {
1510: *(void**)usrP = ts->user;
1511: return(0);
1512: }
1516: /*@
1517: TSGetTimeStepNumber - Gets the number of time steps completed.
1519: Not Collective
1521: Input Parameter:
1522: . ts - the TS context obtained from TSCreate()
1524: Output Parameter:
1525: . iter - number of steps completed so far
1527: Level: intermediate
1529: .keywords: TS, timestep, get, iteration, number
1530: .seealso: TSGetTime(), TSGetTimeStep(), TSSetPreStep(), TSSetPreStage(), TSSetPostStage(), TSSetPostStep()
1531: @*/
1532: PetscErrorCode TSGetTimeStepNumber(TS ts,PetscInt *iter)
1533: {
1537: *iter = ts->steps;
1538: return(0);
1539: }
1543: /*@
1544: TSSetInitialTimeStep - Sets the initial timestep to be used,
1545: as well as the initial time.
1547: Logically Collective on TS
1549: Input Parameters:
1550: + ts - the TS context obtained from TSCreate()
1551: . initial_time - the initial time
1552: - time_step - the size of the timestep
1554: Level: intermediate
1556: .seealso: TSSetTimeStep(), TSGetTimeStep()
1558: .keywords: TS, set, initial, timestep
1559: @*/
1560: PetscErrorCode TSSetInitialTimeStep(TS ts,PetscReal initial_time,PetscReal time_step)
1561: {
1566: TSSetTimeStep(ts,time_step);
1567: TSSetTime(ts,initial_time);
1568: return(0);
1569: }
1573: /*@
1574: TSSetTimeStep - Allows one to reset the timestep at any time,
1575: useful for simple pseudo-timestepping codes.
1577: Logically Collective on TS
1579: Input Parameters:
1580: + ts - the TS context obtained from TSCreate()
1581: - time_step - the size of the timestep
1583: Level: intermediate
1585: .seealso: TSSetInitialTimeStep(), TSGetTimeStep()
1587: .keywords: TS, set, timestep
1588: @*/
1589: PetscErrorCode TSSetTimeStep(TS ts,PetscReal time_step)
1590: {
1594: ts->time_step = time_step;
1595: ts->time_step_orig = time_step;
1596: return(0);
1597: }
1601: /*@
1602: TSSetExactFinalTime - Determines whether to adapt the final time step to
1603: match the exact final time, interpolate solution to the exact final time,
1604: or just return at the final time TS computed.
1606: Logically Collective on TS
1608: Input Parameter:
1609: + ts - the time-step context
1610: - eftopt - exact final time option
1612: Level: beginner
1614: .seealso: TSExactFinalTimeOption
1615: @*/
1616: PetscErrorCode TSSetExactFinalTime(TS ts,TSExactFinalTimeOption eftopt)
1617: {
1621: ts->exact_final_time = eftopt;
1622: return(0);
1623: }
1627: /*@
1628: TSGetTimeStep - Gets the current timestep size.
1630: Not Collective
1632: Input Parameter:
1633: . ts - the TS context obtained from TSCreate()
1635: Output Parameter:
1636: . dt - the current timestep size
1638: Level: intermediate
1640: .seealso: TSSetInitialTimeStep(), TSGetTimeStep()
1642: .keywords: TS, get, timestep
1643: @*/
1644: PetscErrorCode TSGetTimeStep(TS ts,PetscReal *dt)
1645: {
1649: *dt = ts->time_step;
1650: return(0);
1651: }
1655: /*@
1656: TSGetSolution - Returns the solution at the present timestep. It
1657: is valid to call this routine inside the function that you are evaluating
1658: in order to move to the new timestep. This vector not changed until
1659: the solution at the next timestep has been calculated.
1661: Not Collective, but Vec returned is parallel if TS is parallel
1663: Input Parameter:
1664: . ts - the TS context obtained from TSCreate()
1666: Output Parameter:
1667: . v - the vector containing the solution
1669: Level: intermediate
1671: .seealso: TSGetTimeStep()
1673: .keywords: TS, timestep, get, solution
1674: @*/
1675: PetscErrorCode TSGetSolution(TS ts,Vec *v)
1676: {
1680: *v = ts->vec_sol;
1681: return(0);
1682: }
1684: /* ----- Routines to initialize and destroy a timestepper ---- */
1687: /*@
1688: TSSetProblemType - Sets the type of problem to be solved.
1690: Not collective
1692: Input Parameters:
1693: + ts - The TS
1694: - type - One of TS_LINEAR, TS_NONLINEAR where these types refer to problems of the forms
1695: .vb
1696: U_t - A U = 0 (linear)
1697: U_t - A(t) U = 0 (linear)
1698: F(t,U,U_t) = 0 (nonlinear)
1699: .ve
1701: Level: beginner
1703: .keywords: TS, problem type
1704: .seealso: TSSetUp(), TSProblemType, TS
1705: @*/
1706: PetscErrorCode TSSetProblemType(TS ts, TSProblemType type)
1707: {
1712: ts->problem_type = type;
1713: if (type == TS_LINEAR) {
1714: SNES snes;
1715: TSGetSNES(ts,&snes);
1716: SNESSetType(snes,SNESKSPONLY);
1717: }
1718: return(0);
1719: }
1723: /*@C
1724: TSGetProblemType - Gets the type of problem to be solved.
1726: Not collective
1728: Input Parameter:
1729: . ts - The TS
1731: Output Parameter:
1732: . type - One of TS_LINEAR, TS_NONLINEAR where these types refer to problems of the forms
1733: .vb
1734: M U_t = A U
1735: M(t) U_t = A(t) U
1736: F(t,U,U_t)
1737: .ve
1739: Level: beginner
1741: .keywords: TS, problem type
1742: .seealso: TSSetUp(), TSProblemType, TS
1743: @*/
1744: PetscErrorCode TSGetProblemType(TS ts, TSProblemType *type)
1745: {
1749: *type = ts->problem_type;
1750: return(0);
1751: }
1755: /*@
1756: TSSetUp - Sets up the internal data structures for the later use
1757: of a timestepper.
1759: Collective on TS
1761: Input Parameter:
1762: . ts - the TS context obtained from TSCreate()
1764: Notes:
1765: For basic use of the TS solvers the user need not explicitly call
1766: TSSetUp(), since these actions will automatically occur during
1767: the call to TSStep(). However, if one wishes to control this
1768: phase separately, TSSetUp() should be called after TSCreate()
1769: and optional routines of the form TSSetXXX(), but before TSStep().
1771: Level: advanced
1773: .keywords: TS, timestep, setup
1775: .seealso: TSCreate(), TSStep(), TSDestroy()
1776: @*/
1777: PetscErrorCode TSSetUp(TS ts)
1778: {
1780: DM dm;
1781: PetscErrorCode (*func)(SNES,Vec,Vec,void*);
1782: PetscErrorCode (*jac)(SNES,Vec,Mat,Mat,void*);
1783: TSIJacobian ijac;
1784: TSRHSJacobian rhsjac;
1788: if (ts->setupcalled) return(0);
1790: if (!((PetscObject)ts)->type_name) {
1791: TSSetType(ts,TSEULER);
1792: }
1794: if (!ts->vec_sol) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Must call TSSetSolution() first");
1796: TSGetAdapt(ts,&ts->adapt);
1798: if (ts->rhsjacobian.reuse) {
1799: Mat Amat,Pmat;
1800: SNES snes;
1801: TSGetSNES(ts,&snes);
1802: SNESGetJacobian(snes,&Amat,&Pmat,NULL,NULL);
1803: /* Matching matrices implies that an IJacobian is NOT set, because if it had been set, the IJacobian's matrix would
1804: * have displaced the RHS matrix */
1805: if (Amat == ts->Arhs) {
1806: MatDuplicate(ts->Arhs,MAT_DO_NOT_COPY_VALUES,&Amat);
1807: SNESSetJacobian(snes,Amat,NULL,NULL,NULL);
1808: MatDestroy(&Amat);
1809: }
1810: if (Pmat == ts->Brhs) {
1811: MatDuplicate(ts->Brhs,MAT_DO_NOT_COPY_VALUES,&Pmat);
1812: SNESSetJacobian(snes,NULL,Pmat,NULL,NULL);
1813: MatDestroy(&Pmat);
1814: }
1815: }
1817: if (ts->ops->setup) {
1818: (*ts->ops->setup)(ts);
1819: }
1821: /* in the case where we've set a DMTSFunction or what have you, we need the default SNESFunction
1822: to be set right but can't do it elsewhere due to the overreliance on ctx=ts.
1823: */
1824: TSGetDM(ts,&dm);
1825: DMSNESGetFunction(dm,&func,NULL);
1826: if (!func) {
1827: ierr =DMSNESSetFunction(dm,SNESTSFormFunction,ts);
1828: }
1829: /* if the SNES doesn't have a jacobian set and the TS has an ijacobian or rhsjacobian set, set the SNES to use it.
1830: Otherwise, the SNES will use coloring internally to form the Jacobian.
1831: */
1832: DMSNESGetJacobian(dm,&jac,NULL);
1833: DMTSGetIJacobian(dm,&ijac,NULL);
1834: DMTSGetRHSJacobian(dm,&rhsjac,NULL);
1835: if (!jac && (ijac || rhsjac)) {
1836: DMSNESSetJacobian(dm,SNESTSFormJacobian,ts);
1837: }
1838: ts->setupcalled = PETSC_TRUE;
1839: return(0);
1840: }
1844: /*@
1845: TSReset - Resets a TS context and removes any allocated Vecs and Mats.
1847: Collective on TS
1849: Input Parameter:
1850: . ts - the TS context obtained from TSCreate()
1852: Level: beginner
1854: .keywords: TS, timestep, reset
1856: .seealso: TSCreate(), TSSetup(), TSDestroy()
1857: @*/
1858: PetscErrorCode TSReset(TS ts)
1859: {
1864: if (ts->ops->reset) {
1865: (*ts->ops->reset)(ts);
1866: }
1867: if (ts->snes) {SNESReset(ts->snes);}
1869: MatDestroy(&ts->Arhs);
1870: MatDestroy(&ts->Brhs);
1871: VecDestroy(&ts->Frhs);
1872: VecDestroy(&ts->vec_sol);
1873: VecDestroy(&ts->vatol);
1874: VecDestroy(&ts->vrtol);
1875: VecDestroyVecs(ts->nwork,&ts->work);
1877: ts->setupcalled = PETSC_FALSE;
1878: return(0);
1879: }
1883: /*@
1884: TSDestroy - Destroys the timestepper context that was created
1885: with TSCreate().
1887: Collective on TS
1889: Input Parameter:
1890: . ts - the TS context obtained from TSCreate()
1892: Level: beginner
1894: .keywords: TS, timestepper, destroy
1896: .seealso: TSCreate(), TSSetUp(), TSSolve()
1897: @*/
1898: PetscErrorCode TSDestroy(TS *ts)
1899: {
1903: if (!*ts) return(0);
1905: if (--((PetscObject)(*ts))->refct > 0) {*ts = 0; return(0);}
1907: TSReset((*ts));
1909: /* if memory was published with SAWs then destroy it */
1910: PetscObjectSAWsViewOff((PetscObject)*ts);
1911: if ((*ts)->ops->destroy) {(*(*ts)->ops->destroy)((*ts));}
1913: TSAdaptDestroy(&(*ts)->adapt);
1914: if ((*ts)->event) {
1915: TSEventMonitorDestroy(&(*ts)->event);
1916: }
1917: SNESDestroy(&(*ts)->snes);
1918: DMDestroy(&(*ts)->dm);
1919: TSMonitorCancel((*ts));
1921: PetscHeaderDestroy(ts);
1922: return(0);
1923: }
1927: /*@
1928: TSGetSNES - Returns the SNES (nonlinear solver) associated with
1929: a TS (timestepper) context. Valid only for nonlinear problems.
1931: Not Collective, but SNES is parallel if TS is parallel
1933: Input Parameter:
1934: . ts - the TS context obtained from TSCreate()
1936: Output Parameter:
1937: . snes - the nonlinear solver context
1939: Notes:
1940: The user can then directly manipulate the SNES context to set various
1941: options, etc. Likewise, the user can then extract and manipulate the
1942: KSP, KSP, and PC contexts as well.
1944: TSGetSNES() does not work for integrators that do not use SNES; in
1945: this case TSGetSNES() returns NULL in snes.
1947: Level: beginner
1949: .keywords: timestep, get, SNES
1950: @*/
1951: PetscErrorCode TSGetSNES(TS ts,SNES *snes)
1952: {
1958: if (!ts->snes) {
1959: SNESCreate(PetscObjectComm((PetscObject)ts),&ts->snes);
1960: SNESSetFunction(ts->snes,NULL,SNESTSFormFunction,ts);
1961: PetscLogObjectParent((PetscObject)ts,(PetscObject)ts->snes);
1962: PetscObjectIncrementTabLevel((PetscObject)ts->snes,(PetscObject)ts,1);
1963: if (ts->dm) {SNESSetDM(ts->snes,ts->dm);}
1964: if (ts->problem_type == TS_LINEAR) {
1965: SNESSetType(ts->snes,SNESKSPONLY);
1966: }
1967: }
1968: *snes = ts->snes;
1969: return(0);
1970: }
1974: /*@
1975: TSSetSNES - Set the SNES (nonlinear solver) to be used by the timestepping context
1977: Collective
1979: Input Parameter:
1980: + ts - the TS context obtained from TSCreate()
1981: - snes - the nonlinear solver context
1983: Notes:
1984: Most users should have the TS created by calling TSGetSNES()
1986: Level: developer
1988: .keywords: timestep, set, SNES
1989: @*/
1990: PetscErrorCode TSSetSNES(TS ts,SNES snes)
1991: {
1993: PetscErrorCode (*func)(SNES,Vec,Mat,Mat,void*);
1998: PetscObjectReference((PetscObject)snes);
1999: SNESDestroy(&ts->snes);
2001: ts->snes = snes;
2003: SNESSetFunction(ts->snes,NULL,SNESTSFormFunction,ts);
2004: SNESGetJacobian(ts->snes,NULL,NULL,&func,NULL);
2005: if (func == SNESTSFormJacobian) {
2006: SNESSetJacobian(ts->snes,NULL,NULL,SNESTSFormJacobian,ts);
2007: }
2008: return(0);
2009: }
2013: /*@
2014: TSGetKSP - Returns the KSP (linear solver) associated with
2015: a TS (timestepper) context.
2017: Not Collective, but KSP is parallel if TS is parallel
2019: Input Parameter:
2020: . ts - the TS context obtained from TSCreate()
2022: Output Parameter:
2023: . ksp - the nonlinear solver context
2025: Notes:
2026: The user can then directly manipulate the KSP context to set various
2027: options, etc. Likewise, the user can then extract and manipulate the
2028: KSP and PC contexts as well.
2030: TSGetKSP() does not work for integrators that do not use KSP;
2031: in this case TSGetKSP() returns NULL in ksp.
2033: Level: beginner
2035: .keywords: timestep, get, KSP
2036: @*/
2037: PetscErrorCode TSGetKSP(TS ts,KSP *ksp)
2038: {
2040: SNES snes;
2045: if (!((PetscObject)ts)->type_name) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NULL,"KSP is not created yet. Call TSSetType() first");
2046: if (ts->problem_type != TS_LINEAR) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Linear only; use TSGetSNES()");
2047: TSGetSNES(ts,&snes);
2048: SNESGetKSP(snes,ksp);
2049: return(0);
2050: }
2052: /* ----------- Routines to set solver parameters ---------- */
2056: /*@
2057: TSGetDuration - Gets the maximum number of timesteps to use and
2058: maximum time for iteration.
2060: Not Collective
2062: Input Parameters:
2063: + ts - the TS context obtained from TSCreate()
2064: . maxsteps - maximum number of iterations to use, or NULL
2065: - maxtime - final time to iterate to, or NULL
2067: Level: intermediate
2069: .keywords: TS, timestep, get, maximum, iterations, time
2070: @*/
2071: PetscErrorCode TSGetDuration(TS ts, PetscInt *maxsteps, PetscReal *maxtime)
2072: {
2075: if (maxsteps) {
2077: *maxsteps = ts->max_steps;
2078: }
2079: if (maxtime) {
2081: *maxtime = ts->max_time;
2082: }
2083: return(0);
2084: }
2088: /*@
2089: TSSetDuration - Sets the maximum number of timesteps to use and
2090: maximum time for iteration.
2092: Logically Collective on TS
2094: Input Parameters:
2095: + ts - the TS context obtained from TSCreate()
2096: . maxsteps - maximum number of iterations to use
2097: - maxtime - final time to iterate to
2099: Options Database Keys:
2100: . -ts_max_steps <maxsteps> - Sets maxsteps
2101: . -ts_final_time <maxtime> - Sets maxtime
2103: Notes:
2104: The default maximum number of iterations is 5000. Default time is 5.0
2106: Level: intermediate
2108: .keywords: TS, timestep, set, maximum, iterations
2110: .seealso: TSSetExactFinalTime()
2111: @*/
2112: PetscErrorCode TSSetDuration(TS ts,PetscInt maxsteps,PetscReal maxtime)
2113: {
2118: if (maxsteps >= 0) ts->max_steps = maxsteps;
2119: if (maxtime != PETSC_DEFAULT) ts->max_time = maxtime;
2120: return(0);
2121: }
2125: /*@
2126: TSSetSolution - Sets the initial solution vector
2127: for use by the TS routines.
2129: Logically Collective on TS and Vec
2131: Input Parameters:
2132: + ts - the TS context obtained from TSCreate()
2133: - u - the solution vector
2135: Level: beginner
2137: .keywords: TS, timestep, set, solution, initial conditions
2138: @*/
2139: PetscErrorCode TSSetSolution(TS ts,Vec u)
2140: {
2142: DM dm;
2147: PetscObjectReference((PetscObject)u);
2148: VecDestroy(&ts->vec_sol);
2150: ts->vec_sol = u;
2152: TSGetDM(ts,&dm);
2153: DMShellSetGlobalVector(dm,u);
2154: return(0);
2155: }
2159: /*@C
2160: TSSetPreStep - Sets the general-purpose function
2161: called once at the beginning of each time step.
2163: Logically Collective on TS
2165: Input Parameters:
2166: + ts - The TS context obtained from TSCreate()
2167: - func - The function
2169: Calling sequence of func:
2170: . func (TS ts);
2172: Level: intermediate
2174: Note:
2175: If a step is rejected, TSStep() will call this routine again before each attempt.
2176: The last completed time step number can be queried using TSGetTimeStepNumber(), the
2177: size of the step being attempted can be obtained using TSGetTimeStep().
2179: .keywords: TS, timestep
2180: .seealso: TSSetPreStage(), TSSetPostStage(), TSSetPostStep(), TSStep()
2181: @*/
2182: PetscErrorCode TSSetPreStep(TS ts, PetscErrorCode (*func)(TS))
2183: {
2186: ts->prestep = func;
2187: return(0);
2188: }
2192: /*@
2193: TSPreStep - Runs the user-defined pre-step function.
2195: Collective on TS
2197: Input Parameters:
2198: . ts - The TS context obtained from TSCreate()
2200: Notes:
2201: TSPreStep() is typically used within time stepping implementations,
2202: so most users would not generally call this routine themselves.
2204: Level: developer
2206: .keywords: TS, timestep
2207: .seealso: TSSetPreStep(), TSPreStage(), TSPostStage(), TSPostStep()
2208: @*/
2209: PetscErrorCode TSPreStep(TS ts)
2210: {
2215: if (ts->prestep) {
2216: PetscStackCallStandard((*ts->prestep),(ts));
2217: }
2218: return(0);
2219: }
2223: /*@C
2224: TSSetPreStage - Sets the general-purpose function
2225: called once at the beginning of each stage.
2227: Logically Collective on TS
2229: Input Parameters:
2230: + ts - The TS context obtained from TSCreate()
2231: - func - The function
2233: Calling sequence of func:
2234: . PetscErrorCode func(TS ts, PetscReal stagetime);
2236: Level: intermediate
2238: Note:
2239: There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried.
2240: The time step number being computed can be queried using TSGetTimeStepNumber() and the total size of the step being
2241: attempted can be obtained using TSGetTimeStep(). The time at the start of the step is available via TSGetTime().
2243: .keywords: TS, timestep
2244: .seealso: TSSetPostStage(), TSSetPreStep(), TSSetPostStep(), TSGetApplicationContext()
2245: @*/
2246: PetscErrorCode TSSetPreStage(TS ts, PetscErrorCode (*func)(TS,PetscReal))
2247: {
2250: ts->prestage = func;
2251: return(0);
2252: }
2256: /*@C
2257: TSSetPostStage - Sets the general-purpose function
2258: called once at the end of each stage.
2260: Logically Collective on TS
2262: Input Parameters:
2263: + ts - The TS context obtained from TSCreate()
2264: - func - The function
2266: Calling sequence of func:
2267: . PetscErrorCode func(TS ts, PetscReal stagetime, PetscInt stageindex, Vec* Y);
2269: Level: intermediate
2271: Note:
2272: There may be several stages per time step. If the solve for a given stage fails, the step may be rejected and retried.
2273: The time step number being computed can be queried using TSGetTimeStepNumber() and the total size of the step being
2274: attempted can be obtained using TSGetTimeStep(). The time at the start of the step is available via TSGetTime().
2276: .keywords: TS, timestep
2277: .seealso: TSSetPreStage(), TSSetPreStep(), TSSetPostStep(), TSGetApplicationContext()
2278: @*/
2279: PetscErrorCode TSSetPostStage(TS ts, PetscErrorCode (*func)(TS,PetscReal,PetscInt,Vec*))
2280: {
2283: ts->poststage = func;
2284: return(0);
2285: }
2289: /*@
2290: TSPreStage - Runs the user-defined pre-stage function set using TSSetPreStage()
2292: Collective on TS
2294: Input Parameters:
2295: . ts - The TS context obtained from TSCreate()
2296: stagetime - The absolute time of the current stage
2298: Notes:
2299: TSPreStage() is typically used within time stepping implementations,
2300: most users would not generally call this routine themselves.
2302: Level: developer
2304: .keywords: TS, timestep
2305: .seealso: TSPostStage(), TSSetPreStep(), TSPreStep(), TSPostStep()
2306: @*/
2307: PetscErrorCode TSPreStage(TS ts, PetscReal stagetime)
2308: {
2313: if (ts->prestage) {
2314: PetscStackCallStandard((*ts->prestage),(ts,stagetime));
2315: }
2316: return(0);
2317: }
2321: /*@
2322: TSPostStage - Runs the user-defined post-stage function set using TSSetPostStage()
2324: Collective on TS
2326: Input Parameters:
2327: . ts - The TS context obtained from TSCreate()
2328: stagetime - The absolute time of the current stage
2329: stageindex - Stage number
2330: Y - Array of vectors (of size = total number
2331: of stages) with the stage solutions
2333: Notes:
2334: TSPostStage() is typically used within time stepping implementations,
2335: most users would not generally call this routine themselves.
2337: Level: developer
2339: .keywords: TS, timestep
2340: .seealso: TSPreStage(), TSSetPreStep(), TSPreStep(), TSPostStep()
2341: @*/
2342: PetscErrorCode TSPostStage(TS ts, PetscReal stagetime, PetscInt stageindex, Vec *Y)
2343: {
2348: if (ts->prestage) {
2349: PetscStackCallStandard((*ts->poststage),(ts,stagetime,stageindex,Y));
2350: }
2351: return(0);
2352: }
2356: /*@C
2357: TSSetPostStep - Sets the general-purpose function
2358: called once at the end of each time step.
2360: Logically Collective on TS
2362: Input Parameters:
2363: + ts - The TS context obtained from TSCreate()
2364: - func - The function
2366: Calling sequence of func:
2367: $ func (TS ts);
2369: Level: intermediate
2371: .keywords: TS, timestep
2372: .seealso: TSSetPreStep(), TSSetPreStage(), TSGetTimeStep(), TSGetTimeStepNumber(), TSGetTime()
2373: @*/
2374: PetscErrorCode TSSetPostStep(TS ts, PetscErrorCode (*func)(TS))
2375: {
2378: ts->poststep = func;
2379: return(0);
2380: }
2384: /*@
2385: TSPostStep - Runs the user-defined post-step function.
2387: Collective on TS
2389: Input Parameters:
2390: . ts - The TS context obtained from TSCreate()
2392: Notes:
2393: TSPostStep() is typically used within time stepping implementations,
2394: so most users would not generally call this routine themselves.
2396: Level: developer
2398: .keywords: TS, timestep
2399: @*/
2400: PetscErrorCode TSPostStep(TS ts)
2401: {
2406: if (ts->poststep) {
2407: PetscStackCallStandard((*ts->poststep),(ts));
2408: }
2409: return(0);
2410: }
2412: /* ------------ Routines to set performance monitoring options ----------- */
2416: /*@C
2417: TSMonitorSet - Sets an ADDITIONAL function that is to be used at every
2418: timestep to display the iteration's progress.
2420: Logically Collective on TS
2422: Input Parameters:
2423: + ts - the TS context obtained from TSCreate()
2424: . monitor - monitoring routine
2425: . mctx - [optional] user-defined context for private data for the
2426: monitor routine (use NULL if no context is desired)
2427: - monitordestroy - [optional] routine that frees monitor context
2428: (may be NULL)
2430: Calling sequence of monitor:
2431: $ int monitor(TS ts,PetscInt steps,PetscReal time,Vec u,void *mctx)
2433: + ts - the TS context
2434: . steps - iteration number (after the final time step the monitor routine is called with a step of -1, this is at the final time which may have
2435: been interpolated to)
2436: . time - current time
2437: . u - current iterate
2438: - mctx - [optional] monitoring context
2440: Notes:
2441: This routine adds an additional monitor to the list of monitors that
2442: already has been loaded.
2444: Fortran notes: Only a single monitor function can be set for each TS object
2446: Level: intermediate
2448: .keywords: TS, timestep, set, monitor
2450: .seealso: TSMonitorDefault(), TSMonitorCancel()
2451: @*/
2452: PetscErrorCode TSMonitorSet(TS ts,PetscErrorCode (*monitor)(TS,PetscInt,PetscReal,Vec,void*),void *mctx,PetscErrorCode (*mdestroy)(void**))
2453: {
2456: if (ts->numbermonitors >= MAXTSMONITORS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many monitors set");
2457: ts->monitor[ts->numbermonitors] = monitor;
2458: ts->monitordestroy[ts->numbermonitors] = mdestroy;
2459: ts->monitorcontext[ts->numbermonitors++] = (void*)mctx;
2460: return(0);
2461: }
2465: /*@C
2466: TSMonitorCancel - Clears all the monitors that have been set on a time-step object.
2468: Logically Collective on TS
2470: Input Parameters:
2471: . ts - the TS context obtained from TSCreate()
2473: Notes:
2474: There is no way to remove a single, specific monitor.
2476: Level: intermediate
2478: .keywords: TS, timestep, set, monitor
2480: .seealso: TSMonitorDefault(), TSMonitorSet()
2481: @*/
2482: PetscErrorCode TSMonitorCancel(TS ts)
2483: {
2485: PetscInt i;
2489: for (i=0; i<ts->numbermonitors; i++) {
2490: if (ts->monitordestroy[i]) {
2491: (*ts->monitordestroy[i])(&ts->monitorcontext[i]);
2492: }
2493: }
2494: ts->numbermonitors = 0;
2495: return(0);
2496: }
2500: /*@
2501: TSMonitorDefault - Sets the Default monitor
2503: Level: intermediate
2505: .keywords: TS, set, monitor
2507: .seealso: TSMonitorDefault(), TSMonitorSet()
2508: @*/
2509: PetscErrorCode TSMonitorDefault(TS ts,PetscInt step,PetscReal ptime,Vec v,void *dummy)
2510: {
2512: PetscViewer viewer = dummy ? (PetscViewer) dummy : PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)ts));
2515: PetscViewerASCIIAddTab(viewer,((PetscObject)ts)->tablevel);
2516: PetscViewerASCIIPrintf(viewer,"%D TS dt %g time %g\n",step,(double)ts->time_step,(double)ptime);
2517: PetscViewerASCIISubtractTab(viewer,((PetscObject)ts)->tablevel);
2518: return(0);
2519: }
2523: /*@
2524: TSSetRetainStages - Request that all stages in the upcoming step be stored so that interpolation will be available.
2526: Logically Collective on TS
2528: Input Argument:
2529: . ts - time stepping context
2531: Output Argument:
2532: . flg - PETSC_TRUE or PETSC_FALSE
2534: Level: intermediate
2536: .keywords: TS, set
2538: .seealso: TSInterpolate(), TSSetPostStep()
2539: @*/
2540: PetscErrorCode TSSetRetainStages(TS ts,PetscBool flg)
2541: {
2544: ts->retain_stages = flg;
2545: return(0);
2546: }
2550: /*@
2551: TSInterpolate - Interpolate the solution computed during the previous step to an arbitrary location in the interval
2553: Collective on TS
2555: Input Argument:
2556: + ts - time stepping context
2557: - t - time to interpolate to
2559: Output Argument:
2560: . U - state at given time
2562: Notes:
2563: The user should call TSSetRetainStages() before taking a step in which interpolation will be requested.
2565: Level: intermediate
2567: Developer Notes:
2568: TSInterpolate() and the storing of previous steps/stages should be generalized to support delay differential equations and continuous adjoints.
2570: .keywords: TS, set
2572: .seealso: TSSetRetainStages(), TSSetPostStep()
2573: @*/
2574: PetscErrorCode TSInterpolate(TS ts,PetscReal t,Vec U)
2575: {
2581: if (t < ts->ptime - ts->time_step_prev || t > ts->ptime) SETERRQ3(PetscObjectComm((PetscObject)ts),PETSC_ERR_ARG_OUTOFRANGE,"Requested time %g not in last time steps [%g,%g]",t,(double)(ts->ptime-ts->time_step_prev),(double)ts->ptime);
2582: if (!ts->ops->interpolate) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"%s does not provide interpolation",((PetscObject)ts)->type_name);
2583: (*ts->ops->interpolate)(ts,t,U);
2584: return(0);
2585: }
2589: /*@
2590: TSStep - Steps one time step
2592: Collective on TS
2594: Input Parameter:
2595: . ts - the TS context obtained from TSCreate()
2597: Level: intermediate
2599: Notes:
2600: The hook set using TSSetPreStep() is called before each attempt to take the step. In general, the time step size may
2601: be changed due to adaptive error controller or solve failures. Note that steps may contain multiple stages.
2603: This may over-step the final time provided in TSSetDuration() depending on the time-step used. TSSolve() interpolates to exactly the
2604: time provided in TSSetDuration(). One can use TSInterpolate() to determine an interpolated solution within the final timestep.
2606: .keywords: TS, timestep, solve
2608: .seealso: TSCreate(), TSSetUp(), TSDestroy(), TSSolve(), TSSetPreStep(), TSSetPreStage(), TSSetPostStage(), TSInterpolate()
2609: @*/
2610: PetscErrorCode TSStep(TS ts)
2611: {
2612: DM dm;
2613: PetscErrorCode ierr;
2614: static PetscBool cite = PETSC_FALSE;
2618: PetscCitationsRegister("@techreport{tspaper,\n"
2619: " title = {{PETSc/TS}: A Modern Scalable {DAE/ODE} Solver Library},\n"
2620: " author = {Shrirang Abhyankar and Jed Brown and Emil Constantinescu and Debojyoti Ghosh and Barry F. Smith},\n"
2621: " type = {Preprint},\n"
2622: " number = {ANL/MCS-P5061-0114},\n"
2623: " institution = {Argonne National Laboratory},\n"
2624: " year = {2014}\n}\n",&cite);
2626: TSGetDM(ts, &dm);
2627: TSSetUp(ts);
2629: ts->reason = TS_CONVERGED_ITERATING;
2630: ts->ptime_prev = ts->ptime;
2631: DMSetOutputSequenceNumber(dm, ts->steps, ts->ptime);
2632: VecViewFromOptions(ts->vec_sol, ((PetscObject) ts)->prefix, "-ts_view_solution");
2634: PetscLogEventBegin(TS_Step,ts,0,0,0);
2635: (*ts->ops->step)(ts);
2636: PetscLogEventEnd(TS_Step,ts,0,0,0);
2638: ts->time_step_prev = ts->ptime - ts->ptime_prev;
2639: DMSetOutputSequenceNumber(dm, ts->steps, ts->ptime);
2641: if (ts->reason < 0) {
2642: if (ts->errorifstepfailed) {
2643: if (ts->reason == TS_DIVERGED_NONLINEAR_SOLVE) {
2644: SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSStep has failed due to %s, increase -ts_max_snes_failures or make negative to attempt recovery",TSConvergedReasons[ts->reason]);
2645: } else SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_NOT_CONVERGED,"TSStep has failed due to %s",TSConvergedReasons[ts->reason]);
2646: }
2647: } else if (!ts->reason) {
2648: if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS;
2649: else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
2650: }
2651: return(0);
2652: }
2656: /*@
2657: TSEvaluateStep - Evaluate the solution at the end of a time step with a given order of accuracy.
2659: Collective on TS
2661: Input Arguments:
2662: + ts - time stepping context
2663: . order - desired order of accuracy
2664: - done - whether the step was evaluated at this order (pass NULL to generate an error if not available)
2666: Output Arguments:
2667: . U - state at the end of the current step
2669: Level: advanced
2671: Notes:
2672: This function cannot be called until all stages have been evaluated.
2673: It is normally called by adaptive controllers before a step has been accepted and may also be called by the user after TSStep() has returned.
2675: .seealso: TSStep(), TSAdapt
2676: @*/
2677: PetscErrorCode TSEvaluateStep(TS ts,PetscInt order,Vec U,PetscBool *done)
2678: {
2685: if (!ts->ops->evaluatestep) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSEvaluateStep not implemented for type '%s'",((PetscObject)ts)->type_name);
2686: (*ts->ops->evaluatestep)(ts,order,U,done);
2687: return(0);
2688: }
2692: /*@
2693: TSSolve - Steps the requested number of timesteps.
2695: Collective on TS
2697: Input Parameter:
2698: + ts - the TS context obtained from TSCreate()
2699: - u - the solution vector (can be null if TSSetSolution() was used, otherwise must contain the initial conditions)
2701: Level: beginner
2703: Notes:
2704: The final time returned by this function may be different from the time of the internally
2705: held state accessible by TSGetSolution() and TSGetTime() because the method may have
2706: stepped over the final time.
2708: .keywords: TS, timestep, solve
2710: .seealso: TSCreate(), TSSetSolution(), TSStep()
2711: @*/
2712: PetscErrorCode TSSolve(TS ts,Vec u)
2713: {
2714: Vec solution;
2715: PetscErrorCode ierr;
2720: if (ts->exact_final_time == TS_EXACTFINALTIME_INTERPOLATE) { /* Need ts->vec_sol to be distinct so it is not overwritten when we interpolate at the end */
2722: if (!ts->vec_sol || u == ts->vec_sol) {
2723: VecDuplicate(u,&solution);
2724: TSSetSolution(ts,solution);
2725: VecDestroy(&solution); /* grant ownership */
2726: }
2727: VecCopy(u,ts->vec_sol);
2728: } else if (u) {
2729: TSSetSolution(ts,u);
2730: }
2731: TSSetUp(ts);
2732: /* reset time step and iteration counters */
2733: ts->steps = 0;
2734: ts->ksp_its = 0;
2735: ts->snes_its = 0;
2736: ts->num_snes_failures = 0;
2737: ts->reject = 0;
2738: ts->reason = TS_CONVERGED_ITERATING;
2740: TSViewFromOptions(ts,NULL,"-ts_view_pre");
2742: if (ts->ops->solve) { /* This private interface is transitional and should be removed when all implementations are updated. */
2743: (*ts->ops->solve)(ts);
2744: VecCopy(ts->vec_sol,u);
2745: ts->solvetime = ts->ptime;
2746: } else {
2747: /* steps the requested number of timesteps. */
2748: if (ts->steps >= ts->max_steps) ts->reason = TS_CONVERGED_ITS;
2749: else if (ts->ptime >= ts->max_time) ts->reason = TS_CONVERGED_TIME;
2750: while (!ts->reason) {
2751: TSMonitor(ts,ts->steps,ts->ptime,ts->vec_sol);
2752: TSStep(ts);
2753: if (ts->event) {
2754: TSEventMonitor(ts);
2755: if (ts->event->status != TSEVENT_PROCESSING) {
2756: TSPostStep(ts);
2757: }
2758: } else {
2759: TSPostStep(ts);
2760: }
2761: }
2762: if (ts->exact_final_time == TS_EXACTFINALTIME_INTERPOLATE && ts->ptime > ts->max_time) {
2763: TSInterpolate(ts,ts->max_time,u);
2764: ts->solvetime = ts->max_time;
2765: solution = u;
2766: } else {
2767: if (u) {VecCopy(ts->vec_sol,u);}
2768: ts->solvetime = ts->ptime;
2769: solution = ts->vec_sol;
2770: }
2771: TSMonitor(ts,ts->steps,ts->solvetime,solution);
2772: VecViewFromOptions(u, ((PetscObject) ts)->prefix, "-ts_view_solution");
2773: }
2774: TSViewFromOptions(ts,NULL,"-ts_view");
2775: PetscObjectSAWsBlock((PetscObject)ts);
2776: return(0);
2777: }
2781: /*@
2782: TSMonitor - Runs all user-provided monitor routines set using TSMonitorSet()
2784: Collective on TS
2786: Input Parameters:
2787: + ts - time stepping context obtained from TSCreate()
2788: . step - step number that has just completed
2789: . ptime - model time of the state
2790: - u - state at the current model time
2792: Notes:
2793: TSMonitor() is typically used within the time stepping implementations.
2794: Users might call this function when using the TSStep() interface instead of TSSolve().
2796: Level: advanced
2798: .keywords: TS, timestep
2799: @*/
2800: PetscErrorCode TSMonitor(TS ts,PetscInt step,PetscReal ptime,Vec u)
2801: {
2803: PetscInt i,n = ts->numbermonitors;
2808: for (i=0; i<n; i++) {
2809: (*ts->monitor[i])(ts,step,ptime,u,ts->monitorcontext[i]);
2810: }
2811: return(0);
2812: }
2814: /* ------------------------------------------------------------------------*/
2817: /*@C
2818: TSMonitorLGCtxCreate - Creates a line graph context for use with
2819: TS to monitor the solution process graphically in various ways
2821: Collective on TS
2823: Input Parameters:
2824: + host - the X display to open, or null for the local machine
2825: . label - the title to put in the title bar
2826: . x, y - the screen coordinates of the upper left coordinate of the window
2827: . m, n - the screen width and height in pixels
2828: - howoften - if positive then determines the frequency of the plotting, if -1 then only at the final time
2830: Output Parameter:
2831: . ctx - the context
2833: Options Database Key:
2834: + -ts_monitor_lg_timestep - automatically sets line graph monitor
2835: . -ts_monitor_lg_solution -
2836: . -ts_monitor_lg_error -
2837: . -ts_monitor_lg_ksp_iterations -
2838: . -ts_monitor_lg_snes_iterations -
2839: - -lg_indicate_data_points <true,false> - indicate the data points (at each time step) on the plot; default is true
2841: Notes:
2842: Use TSMonitorLGCtxDestroy() to destroy.
2844: Level: intermediate
2846: .keywords: TS, monitor, line graph, residual, seealso
2848: .seealso: TSMonitorLGTimeStep(), TSMonitorSet(), TSMonitorLGSolution(), TSMonitorLGError()
2850: @*/
2851: PetscErrorCode TSMonitorLGCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,TSMonitorLGCtx *ctx)
2852: {
2853: PetscDraw win;
2857: PetscNew(ctx);
2858: PetscDrawCreate(comm,host,label,x,y,m,n,&win);
2859: PetscDrawSetFromOptions(win);
2860: PetscDrawLGCreate(win,1,&(*ctx)->lg);
2861: PetscLogObjectParent((PetscObject)(*ctx)->lg,(PetscObject)win);
2862: PetscDrawLGIndicateDataPoints((*ctx)->lg,PETSC_TRUE);
2863: PetscDrawLGSetFromOptions((*ctx)->lg);
2864: (*ctx)->howoften = howoften;
2865: return(0);
2866: }
2870: PetscErrorCode TSMonitorLGTimeStep(TS ts,PetscInt step,PetscReal ptime,Vec v,void *monctx)
2871: {
2872: TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
2873: PetscReal x = ptime,y;
2877: if (!step) {
2878: PetscDrawAxis axis;
2879: PetscDrawLGGetAxis(ctx->lg,&axis);
2880: PetscDrawAxisSetLabels(axis,"Timestep as function of time","Time","Time step");
2881: PetscDrawLGReset(ctx->lg);
2882: PetscDrawLGIndicateDataPoints(ctx->lg,PETSC_TRUE);
2883: }
2884: TSGetTimeStep(ts,&y);
2885: PetscDrawLGAddPoint(ctx->lg,&x,&y);
2886: if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
2887: PetscDrawLGDraw(ctx->lg);
2888: }
2889: return(0);
2890: }
2894: /*@C
2895: TSMonitorLGCtxDestroy - Destroys a line graph context that was created
2896: with TSMonitorLGCtxCreate().
2898: Collective on TSMonitorLGCtx
2900: Input Parameter:
2901: . ctx - the monitor context
2903: Level: intermediate
2905: .keywords: TS, monitor, line graph, destroy
2907: .seealso: TSMonitorLGCtxCreate(), TSMonitorSet(), TSMonitorLGTimeStep();
2908: @*/
2909: PetscErrorCode TSMonitorLGCtxDestroy(TSMonitorLGCtx *ctx)
2910: {
2911: PetscDraw draw;
2915: PetscDrawLGGetDraw((*ctx)->lg,&draw);
2916: PetscDrawDestroy(&draw);
2917: PetscDrawLGDestroy(&(*ctx)->lg);
2918: PetscFree(*ctx);
2919: return(0);
2920: }
2924: /*@
2925: TSGetTime - Gets the time of the most recently completed step.
2927: Not Collective
2929: Input Parameter:
2930: . ts - the TS context obtained from TSCreate()
2932: Output Parameter:
2933: . t - the current time
2935: Level: beginner
2937: Note:
2938: When called during time step evaluation (e.g. during residual evaluation or via hooks set using TSSetPreStep(),
2939: TSSetPreStage(), TSSetPostStage(), or TSSetPostStep()), the time is the time at the start of the step being evaluated.
2941: .seealso: TSSetInitialTimeStep(), TSGetTimeStep()
2943: .keywords: TS, get, time
2944: @*/
2945: PetscErrorCode TSGetTime(TS ts,PetscReal *t)
2946: {
2950: *t = ts->ptime;
2951: return(0);
2952: }
2956: /*@
2957: TSSetTime - Allows one to reset the time.
2959: Logically Collective on TS
2961: Input Parameters:
2962: + ts - the TS context obtained from TSCreate()
2963: - time - the time
2965: Level: intermediate
2967: .seealso: TSGetTime(), TSSetDuration()
2969: .keywords: TS, set, time
2970: @*/
2971: PetscErrorCode TSSetTime(TS ts, PetscReal t)
2972: {
2976: ts->ptime = t;
2977: return(0);
2978: }
2982: /*@C
2983: TSSetOptionsPrefix - Sets the prefix used for searching for all
2984: TS options in the database.
2986: Logically Collective on TS
2988: Input Parameter:
2989: + ts - The TS context
2990: - prefix - The prefix to prepend to all option names
2992: Notes:
2993: A hyphen (-) must NOT be given at the beginning of the prefix name.
2994: The first character of all runtime options is AUTOMATICALLY the
2995: hyphen.
2997: Level: advanced
2999: .keywords: TS, set, options, prefix, database
3001: .seealso: TSSetFromOptions()
3003: @*/
3004: PetscErrorCode TSSetOptionsPrefix(TS ts,const char prefix[])
3005: {
3007: SNES snes;
3011: PetscObjectSetOptionsPrefix((PetscObject)ts,prefix);
3012: TSGetSNES(ts,&snes);
3013: SNESSetOptionsPrefix(snes,prefix);
3014: return(0);
3015: }
3020: /*@C
3021: TSAppendOptionsPrefix - Appends to the prefix used for searching for all
3022: TS options in the database.
3024: Logically Collective on TS
3026: Input Parameter:
3027: + ts - The TS context
3028: - prefix - The prefix to prepend to all option names
3030: Notes:
3031: A hyphen (-) must NOT be given at the beginning of the prefix name.
3032: The first character of all runtime options is AUTOMATICALLY the
3033: hyphen.
3035: Level: advanced
3037: .keywords: TS, append, options, prefix, database
3039: .seealso: TSGetOptionsPrefix()
3041: @*/
3042: PetscErrorCode TSAppendOptionsPrefix(TS ts,const char prefix[])
3043: {
3045: SNES snes;
3049: PetscObjectAppendOptionsPrefix((PetscObject)ts,prefix);
3050: TSGetSNES(ts,&snes);
3051: SNESAppendOptionsPrefix(snes,prefix);
3052: return(0);
3053: }
3057: /*@C
3058: TSGetOptionsPrefix - Sets the prefix used for searching for all
3059: TS options in the database.
3061: Not Collective
3063: Input Parameter:
3064: . ts - The TS context
3066: Output Parameter:
3067: . prefix - A pointer to the prefix string used
3069: Notes: On the fortran side, the user should pass in a string 'prifix' of
3070: sufficient length to hold the prefix.
3072: Level: intermediate
3074: .keywords: TS, get, options, prefix, database
3076: .seealso: TSAppendOptionsPrefix()
3077: @*/
3078: PetscErrorCode TSGetOptionsPrefix(TS ts,const char *prefix[])
3079: {
3085: PetscObjectGetOptionsPrefix((PetscObject)ts,prefix);
3086: return(0);
3087: }
3091: /*@C
3092: TSGetRHSJacobian - Returns the Jacobian J at the present timestep.
3094: Not Collective, but parallel objects are returned if TS is parallel
3096: Input Parameter:
3097: . ts - The TS context obtained from TSCreate()
3099: Output Parameters:
3100: + Amat - The (approximate) Jacobian J of G, where U_t = G(U,t) (or NULL)
3101: . Pmat - The matrix from which the preconditioner is constructed, usually the same as Amat (or NULL)
3102: . func - Function to compute the Jacobian of the RHS (or NULL)
3103: - ctx - User-defined context for Jacobian evaluation routine (or NULL)
3105: Notes: You can pass in NULL for any return argument you do not need.
3107: Level: intermediate
3109: .seealso: TSGetTimeStep(), TSGetMatrices(), TSGetTime(), TSGetTimeStepNumber()
3111: .keywords: TS, timestep, get, matrix, Jacobian
3112: @*/
3113: PetscErrorCode TSGetRHSJacobian(TS ts,Mat *Amat,Mat *Pmat,TSRHSJacobian *func,void **ctx)
3114: {
3116: SNES snes;
3117: DM dm;
3120: TSGetSNES(ts,&snes);
3121: SNESGetJacobian(snes,Amat,Pmat,NULL,NULL);
3122: TSGetDM(ts,&dm);
3123: DMTSGetRHSJacobian(dm,func,ctx);
3124: return(0);
3125: }
3129: /*@C
3130: TSGetIJacobian - Returns the implicit Jacobian at the present timestep.
3132: Not Collective, but parallel objects are returned if TS is parallel
3134: Input Parameter:
3135: . ts - The TS context obtained from TSCreate()
3137: Output Parameters:
3138: + Amat - The (approximate) Jacobian of F(t,U,U_t)
3139: . Pmat - The matrix from which the preconditioner is constructed, often the same as Amat
3140: . f - The function to compute the matrices
3141: - ctx - User-defined context for Jacobian evaluation routine
3143: Notes: You can pass in NULL for any return argument you do not need.
3145: Level: advanced
3147: .seealso: TSGetTimeStep(), TSGetRHSJacobian(), TSGetMatrices(), TSGetTime(), TSGetTimeStepNumber()
3149: .keywords: TS, timestep, get, matrix, Jacobian
3150: @*/
3151: PetscErrorCode TSGetIJacobian(TS ts,Mat *Amat,Mat *Pmat,TSIJacobian *f,void **ctx)
3152: {
3154: SNES snes;
3155: DM dm;
3158: TSGetSNES(ts,&snes);
3159: SNESSetUpMatrices(snes);
3160: SNESGetJacobian(snes,Amat,Pmat,NULL,NULL);
3161: TSGetDM(ts,&dm);
3162: DMTSGetIJacobian(dm,f,ctx);
3163: return(0);
3164: }
3169: /*@C
3170: TSMonitorDrawSolution - Monitors progress of the TS solvers by calling
3171: VecView() for the solution at each timestep
3173: Collective on TS
3175: Input Parameters:
3176: + ts - the TS context
3177: . step - current time-step
3178: . ptime - current time
3179: - dummy - either a viewer or NULL
3181: Options Database:
3182: . -ts_monitor_draw_solution_initial - show initial solution as well as current solution
3184: Notes: the initial solution and current solution are not displayed with a common axis scaling so generally the option -ts_monitor_draw_solution_initial
3185: will look bad
3187: Level: intermediate
3189: .keywords: TS, vector, monitor, view
3191: .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
3192: @*/
3193: PetscErrorCode TSMonitorDrawSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
3194: {
3195: PetscErrorCode ierr;
3196: TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
3197: PetscDraw draw;
3200: if (!step && ictx->showinitial) {
3201: if (!ictx->initialsolution) {
3202: VecDuplicate(u,&ictx->initialsolution);
3203: }
3204: VecCopy(u,ictx->initialsolution);
3205: }
3206: if (!(((ictx->howoften > 0) && (!(step % ictx->howoften))) || ((ictx->howoften == -1) && ts->reason))) return(0);
3208: if (ictx->showinitial) {
3209: PetscReal pause;
3210: PetscViewerDrawGetPause(ictx->viewer,&pause);
3211: PetscViewerDrawSetPause(ictx->viewer,0.0);
3212: VecView(ictx->initialsolution,ictx->viewer);
3213: PetscViewerDrawSetPause(ictx->viewer,pause);
3214: PetscViewerDrawSetHold(ictx->viewer,PETSC_TRUE);
3215: }
3216: VecView(u,ictx->viewer);
3217: if (ictx->showtimestepandtime) {
3218: PetscReal xl,yl,xr,yr,tw,w,h;
3219: char time[32];
3220: size_t len;
3222: PetscViewerDrawGetDraw(ictx->viewer,0,&draw);
3223: PetscSNPrintf(time,32,"Timestep %d Time %f",(int)step,(double)ptime);
3224: PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);
3225: PetscStrlen(time,&len);
3226: PetscDrawStringGetSize(draw,&tw,NULL);
3227: w = xl + .5*(xr - xl) - .5*len*tw;
3228: h = yl + .95*(yr - yl);
3229: PetscDrawString(draw,w,h,PETSC_DRAW_BLACK,time);
3230: PetscDrawFlush(draw);
3231: }
3233: if (ictx->showinitial) {
3234: PetscViewerDrawSetHold(ictx->viewer,PETSC_FALSE);
3235: }
3236: return(0);
3237: }
3241: /*@C
3242: TSMonitorDrawSolutionPhase - Monitors progress of the TS solvers by plotting the solution as a phase diagram
3244: Collective on TS
3246: Input Parameters:
3247: + ts - the TS context
3248: . step - current time-step
3249: . ptime - current time
3250: - dummy - either a viewer or NULL
3252: Level: intermediate
3254: .keywords: TS, vector, monitor, view
3256: .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
3257: @*/
3258: PetscErrorCode TSMonitorDrawSolutionPhase(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
3259: {
3260: PetscErrorCode ierr;
3261: TSMonitorDrawCtx ictx = (TSMonitorDrawCtx)dummy;
3262: PetscDraw draw;
3263: MPI_Comm comm;
3264: PetscInt n;
3265: PetscMPIInt size;
3266: PetscReal xl,yl,xr,yr,tw,w,h;
3267: char time[32];
3268: size_t len;
3269: const PetscScalar *U;
3272: PetscObjectGetComm((PetscObject)ts,&comm);
3273: MPI_Comm_size(comm,&size);
3274: if (size != 1) SETERRQ(comm,PETSC_ERR_SUP,"Only allowed for sequential runs");
3275: VecGetSize(u,&n);
3276: if (n != 2) SETERRQ(comm,PETSC_ERR_SUP,"Only for ODEs with two unknowns");
3278: PetscViewerDrawGetDraw(ictx->viewer,0,&draw);
3280: VecGetArrayRead(u,&U);
3281: PetscDrawAxisGetLimits(ictx->axis,&xl,&xr,&yl,&yr);
3282: if ((PetscRealPart(U[0]) < xl) || (PetscRealPart(U[1]) < yl) || (PetscRealPart(U[0]) > xr) || (PetscRealPart(U[1]) > yr)) {
3283: VecRestoreArrayRead(u,&U);
3284: return(0);
3285: }
3286: if (!step) ictx->color++;
3287: PetscDrawPoint(draw,PetscRealPart(U[0]),PetscRealPart(U[1]),ictx->color);
3288: VecRestoreArrayRead(u,&U);
3290: if (ictx->showtimestepandtime) {
3291: PetscDrawGetCoordinates(draw,&xl,&yl,&xr,&yr);
3292: PetscSNPrintf(time,32,"Timestep %d Time %f",(int)step,(double)ptime);
3293: PetscStrlen(time,&len);
3294: PetscDrawStringGetSize(draw,&tw,NULL);
3295: w = xl + .5*(xr - xl) - .5*len*tw;
3296: h = yl + .95*(yr - yl);
3297: PetscDrawString(draw,w,h,PETSC_DRAW_BLACK,time);
3298: }
3299: PetscDrawFlush(draw);
3300: return(0);
3301: }
3306: /*@C
3307: TSMonitorDrawCtxDestroy - Destroys the monitor context for TSMonitorDrawSolution()
3309: Collective on TS
3311: Input Parameters:
3312: . ctx - the monitor context
3314: Level: intermediate
3316: .keywords: TS, vector, monitor, view
3318: .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorDrawSolution(), TSMonitorDrawError()
3319: @*/
3320: PetscErrorCode TSMonitorDrawCtxDestroy(TSMonitorDrawCtx *ictx)
3321: {
3325: PetscDrawAxisDestroy(&(*ictx)->axis);
3326: PetscViewerDestroy(&(*ictx)->viewer);
3327: VecDestroy(&(*ictx)->initialsolution);
3328: PetscFree(*ictx);
3329: return(0);
3330: }
3334: /*@C
3335: TSMonitorDrawCtxCreate - Creates the monitor context for TSMonitorDrawCtx
3337: Collective on TS
3339: Input Parameter:
3340: . ts - time-step context
3342: Output Patameter:
3343: . ctx - the monitor context
3345: Options Database:
3346: . -ts_monitor_draw_solution_initial - show initial solution as well as current solution
3348: Level: intermediate
3350: .keywords: TS, vector, monitor, view
3352: .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSMonitorDrawCtx()
3353: @*/
3354: PetscErrorCode TSMonitorDrawCtxCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscInt howoften,TSMonitorDrawCtx *ctx)
3355: {
3356: PetscErrorCode ierr;
3359: PetscNew(ctx);
3360: PetscViewerDrawOpen(comm,host,label,x,y,m,n,&(*ctx)->viewer);
3361: PetscViewerSetFromOptions((*ctx)->viewer);
3363: (*ctx)->howoften = howoften;
3364: (*ctx)->showinitial = PETSC_FALSE;
3365: PetscOptionsGetBool(NULL,"-ts_monitor_draw_solution_initial",&(*ctx)->showinitial,NULL);
3367: (*ctx)->showtimestepandtime = PETSC_FALSE;
3368: PetscOptionsGetBool(NULL,"-ts_monitor_draw_solution_show_time",&(*ctx)->showtimestepandtime,NULL);
3369: (*ctx)->color = PETSC_DRAW_WHITE;
3370: return(0);
3371: }
3375: /*@C
3376: TSMonitorDrawError - Monitors progress of the TS solvers by calling
3377: VecView() for the error at each timestep
3379: Collective on TS
3381: Input Parameters:
3382: + ts - the TS context
3383: . step - current time-step
3384: . ptime - current time
3385: - dummy - either a viewer or NULL
3387: Level: intermediate
3389: .keywords: TS, vector, monitor, view
3391: .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
3392: @*/
3393: PetscErrorCode TSMonitorDrawError(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
3394: {
3395: PetscErrorCode ierr;
3396: TSMonitorDrawCtx ctx = (TSMonitorDrawCtx)dummy;
3397: PetscViewer viewer = ctx->viewer;
3398: Vec work;
3401: if (!(((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason))) return(0);
3402: VecDuplicate(u,&work);
3403: TSComputeSolutionFunction(ts,ptime,work);
3404: VecAXPY(work,-1.0,u);
3405: VecView(work,viewer);
3406: VecDestroy(&work);
3407: return(0);
3408: }
3410: #include <petsc-private/dmimpl.h>
3413: /*@
3414: TSSetDM - Sets the DM that may be used by some preconditioners
3416: Logically Collective on TS and DM
3418: Input Parameters:
3419: + ts - the preconditioner context
3420: - dm - the dm
3422: Level: intermediate
3425: .seealso: TSGetDM(), SNESSetDM(), SNESGetDM()
3426: @*/
3427: PetscErrorCode TSSetDM(TS ts,DM dm)
3428: {
3430: SNES snes;
3431: DMTS tsdm;
3435: PetscObjectReference((PetscObject)dm);
3436: if (ts->dm) { /* Move the DMTS context over to the new DM unless the new DM already has one */
3437: if (ts->dm->dmts && !dm->dmts) {
3438: DMCopyDMTS(ts->dm,dm);
3439: DMGetDMTS(ts->dm,&tsdm);
3440: if (tsdm->originaldm == ts->dm) { /* Grant write privileges to the replacement DM */
3441: tsdm->originaldm = dm;
3442: }
3443: }
3444: DMDestroy(&ts->dm);
3445: }
3446: ts->dm = dm;
3448: TSGetSNES(ts,&snes);
3449: SNESSetDM(snes,dm);
3450: return(0);
3451: }
3455: /*@
3456: TSGetDM - Gets the DM that may be used by some preconditioners
3458: Not Collective
3460: Input Parameter:
3461: . ts - the preconditioner context
3463: Output Parameter:
3464: . dm - the dm
3466: Level: intermediate
3469: .seealso: TSSetDM(), SNESSetDM(), SNESGetDM()
3470: @*/
3471: PetscErrorCode TSGetDM(TS ts,DM *dm)
3472: {
3477: if (!ts->dm) {
3478: DMShellCreate(PetscObjectComm((PetscObject)ts),&ts->dm);
3479: if (ts->snes) {SNESSetDM(ts->snes,ts->dm);}
3480: }
3481: *dm = ts->dm;
3482: return(0);
3483: }
3487: /*@
3488: SNESTSFormFunction - Function to evaluate nonlinear residual
3490: Logically Collective on SNES
3492: Input Parameter:
3493: + snes - nonlinear solver
3494: . U - the current state at which to evaluate the residual
3495: - ctx - user context, must be a TS
3497: Output Parameter:
3498: . F - the nonlinear residual
3500: Notes:
3501: This function is not normally called by users and is automatically registered with the SNES used by TS.
3502: It is most frequently passed to MatFDColoringSetFunction().
3504: Level: advanced
3506: .seealso: SNESSetFunction(), MatFDColoringSetFunction()
3507: @*/
3508: PetscErrorCode SNESTSFormFunction(SNES snes,Vec U,Vec F,void *ctx)
3509: {
3510: TS ts = (TS)ctx;
3518: (ts->ops->snesfunction)(snes,U,F,ts);
3519: return(0);
3520: }
3524: /*@
3525: SNESTSFormJacobian - Function to evaluate the Jacobian
3527: Collective on SNES
3529: Input Parameter:
3530: + snes - nonlinear solver
3531: . U - the current state at which to evaluate the residual
3532: - ctx - user context, must be a TS
3534: Output Parameter:
3535: + A - the Jacobian
3536: . B - the preconditioning matrix (may be the same as A)
3537: - flag - indicates any structure change in the matrix
3539: Notes:
3540: This function is not normally called by users and is automatically registered with the SNES used by TS.
3542: Level: developer
3544: .seealso: SNESSetJacobian()
3545: @*/
3546: PetscErrorCode SNESTSFormJacobian(SNES snes,Vec U,Mat A,Mat B,void *ctx)
3547: {
3548: TS ts = (TS)ctx;
3559: (ts->ops->snesjacobian)(snes,U,A,B,ts);
3560: return(0);
3561: }
3565: /*@C
3566: TSComputeRHSFunctionLinear - Evaluate the right hand side via the user-provided Jacobian, for linear problems only
3568: Collective on TS
3570: Input Arguments:
3571: + ts - time stepping context
3572: . t - time at which to evaluate
3573: . U - state at which to evaluate
3574: - ctx - context
3576: Output Arguments:
3577: . F - right hand side
3579: Level: intermediate
3581: Notes:
3582: This function is intended to be passed to TSSetRHSFunction() to evaluate the right hand side for linear problems.
3583: The matrix (and optionally the evaluation context) should be passed to TSSetRHSJacobian().
3585: .seealso: TSSetRHSFunction(), TSSetRHSJacobian(), TSComputeRHSJacobianConstant()
3586: @*/
3587: PetscErrorCode TSComputeRHSFunctionLinear(TS ts,PetscReal t,Vec U,Vec F,void *ctx)
3588: {
3590: Mat Arhs,Brhs;
3593: TSGetRHSMats_Private(ts,&Arhs,&Brhs);
3594: TSComputeRHSJacobian(ts,t,U,Arhs,Brhs);
3595: MatMult(Arhs,U,F);
3596: return(0);
3597: }
3601: /*@C
3602: TSComputeRHSJacobianConstant - Reuses a Jacobian that is time-independent.
3604: Collective on TS
3606: Input Arguments:
3607: + ts - time stepping context
3608: . t - time at which to evaluate
3609: . U - state at which to evaluate
3610: - ctx - context
3612: Output Arguments:
3613: + A - pointer to operator
3614: . B - pointer to preconditioning matrix
3615: - flg - matrix structure flag
3617: Level: intermediate
3619: Notes:
3620: This function is intended to be passed to TSSetRHSJacobian() to evaluate the Jacobian for linear time-independent problems.
3622: .seealso: TSSetRHSFunction(), TSSetRHSJacobian(), TSComputeRHSFunctionLinear()
3623: @*/
3624: PetscErrorCode TSComputeRHSJacobianConstant(TS ts,PetscReal t,Vec U,Mat A,Mat B,void *ctx)
3625: {
3627: return(0);
3628: }
3632: /*@C
3633: TSComputeIFunctionLinear - Evaluate the left hand side via the user-provided Jacobian, for linear problems only
3635: Collective on TS
3637: Input Arguments:
3638: + ts - time stepping context
3639: . t - time at which to evaluate
3640: . U - state at which to evaluate
3641: . Udot - time derivative of state vector
3642: - ctx - context
3644: Output Arguments:
3645: . F - left hand side
3647: Level: intermediate
3649: Notes:
3650: The assumption here is that the left hand side is of the form A*Udot (and not A*Udot + B*U). For other cases, the
3651: user is required to write their own TSComputeIFunction.
3652: This function is intended to be passed to TSSetIFunction() to evaluate the left hand side for linear problems.
3653: The matrix (and optionally the evaluation context) should be passed to TSSetIJacobian().
3655: .seealso: TSSetIFunction(), TSSetIJacobian(), TSComputeIJacobianConstant()
3656: @*/
3657: PetscErrorCode TSComputeIFunctionLinear(TS ts,PetscReal t,Vec U,Vec Udot,Vec F,void *ctx)
3658: {
3660: Mat A,B;
3663: TSGetIJacobian(ts,&A,&B,NULL,NULL);
3664: TSComputeIJacobian(ts,t,U,Udot,1.0,A,B,PETSC_TRUE);
3665: MatMult(A,Udot,F);
3666: return(0);
3667: }
3671: /*@C
3672: TSComputeIJacobianConstant - Reuses a time-independent for a semi-implicit DAE or ODE
3674: Collective on TS
3676: Input Arguments:
3677: + ts - time stepping context
3678: . t - time at which to evaluate
3679: . U - state at which to evaluate
3680: . Udot - time derivative of state vector
3681: . shift - shift to apply
3682: - ctx - context
3684: Output Arguments:
3685: + A - pointer to operator
3686: . B - pointer to preconditioning matrix
3687: - flg - matrix structure flag
3689: Level: advanced
3691: Notes:
3692: This function is intended to be passed to TSSetIJacobian() to evaluate the Jacobian for linear time-independent problems.
3694: It is only appropriate for problems of the form
3696: $ M Udot = F(U,t)
3698: where M is constant and F is non-stiff. The user must pass M to TSSetIJacobian(). The current implementation only
3699: works with IMEX time integration methods such as TSROSW and TSARKIMEX, since there is no support for de-constructing
3700: an implicit operator of the form
3702: $ shift*M + J
3704: where J is the Jacobian of -F(U). Support may be added in a future version of PETSc, but for now, the user must store
3705: a copy of M or reassemble it when requested.
3707: .seealso: TSSetIFunction(), TSSetIJacobian(), TSComputeIFunctionLinear()
3708: @*/
3709: PetscErrorCode TSComputeIJacobianConstant(TS ts,PetscReal t,Vec U,Vec Udot,PetscReal shift,Mat A,Mat B,void *ctx)
3710: {
3714: MatScale(A, shift / ts->ijacobian.shift);
3715: ts->ijacobian.shift = shift;
3716: return(0);
3717: }
3721: /*@
3722: TSGetEquationType - Gets the type of the equation that TS is solving.
3724: Not Collective
3726: Input Parameter:
3727: . ts - the TS context
3729: Output Parameter:
3730: . equation_type - see TSEquationType
3732: Level: beginner
3734: .keywords: TS, equation type
3736: .seealso: TSSetEquationType(), TSEquationType
3737: @*/
3738: PetscErrorCode TSGetEquationType(TS ts,TSEquationType *equation_type)
3739: {
3743: *equation_type = ts->equation_type;
3744: return(0);
3745: }
3749: /*@
3750: TSSetEquationType - Sets the type of the equation that TS is solving.
3752: Not Collective
3754: Input Parameter:
3755: + ts - the TS context
3756: . equation_type - see TSEquationType
3758: Level: advanced
3760: .keywords: TS, equation type
3762: .seealso: TSGetEquationType(), TSEquationType
3763: @*/
3764: PetscErrorCode TSSetEquationType(TS ts,TSEquationType equation_type)
3765: {
3768: ts->equation_type = equation_type;
3769: return(0);
3770: }
3774: /*@
3775: TSGetConvergedReason - Gets the reason the TS iteration was stopped.
3777: Not Collective
3779: Input Parameter:
3780: . ts - the TS context
3782: Output Parameter:
3783: . reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the
3784: manual pages for the individual convergence tests for complete lists
3786: Level: beginner
3788: Notes:
3789: Can only be called after the call to TSSolve() is complete.
3791: .keywords: TS, nonlinear, set, convergence, test
3793: .seealso: TSSetConvergenceTest(), TSConvergedReason
3794: @*/
3795: PetscErrorCode TSGetConvergedReason(TS ts,TSConvergedReason *reason)
3796: {
3800: *reason = ts->reason;
3801: return(0);
3802: }
3806: /*@
3807: TSSetConvergedReason - Sets the reason for handling the convergence of TSSolve.
3809: Not Collective
3811: Input Parameter:
3812: + ts - the TS context
3813: . reason - negative value indicates diverged, positive value converged, see TSConvergedReason or the
3814: manual pages for the individual convergence tests for complete lists
3816: Level: advanced
3818: Notes:
3819: Can only be called during TSSolve() is active.
3821: .keywords: TS, nonlinear, set, convergence, test
3823: .seealso: TSConvergedReason
3824: @*/
3825: PetscErrorCode TSSetConvergedReason(TS ts,TSConvergedReason reason)
3826: {
3829: ts->reason = reason;
3830: return(0);
3831: }
3835: /*@
3836: TSGetSolveTime - Gets the time after a call to TSSolve()
3838: Not Collective
3840: Input Parameter:
3841: . ts - the TS context
3843: Output Parameter:
3844: . ftime - the final time. This time should correspond to the final time set with TSSetDuration()
3846: Level: beginner
3848: Notes:
3849: Can only be called after the call to TSSolve() is complete.
3851: .keywords: TS, nonlinear, set, convergence, test
3853: .seealso: TSSetConvergenceTest(), TSConvergedReason
3854: @*/
3855: PetscErrorCode TSGetSolveTime(TS ts,PetscReal *ftime)
3856: {
3860: *ftime = ts->solvetime;
3861: return(0);
3862: }
3866: /*@
3867: TSGetSNESIterations - Gets the total number of nonlinear iterations
3868: used by the time integrator.
3870: Not Collective
3872: Input Parameter:
3873: . ts - TS context
3875: Output Parameter:
3876: . nits - number of nonlinear iterations
3878: Notes:
3879: This counter is reset to zero for each successive call to TSSolve().
3881: Level: intermediate
3883: .keywords: TS, get, number, nonlinear, iterations
3885: .seealso: TSGetKSPIterations()
3886: @*/
3887: PetscErrorCode TSGetSNESIterations(TS ts,PetscInt *nits)
3888: {
3892: *nits = ts->snes_its;
3893: return(0);
3894: }
3898: /*@
3899: TSGetKSPIterations - Gets the total number of linear iterations
3900: used by the time integrator.
3902: Not Collective
3904: Input Parameter:
3905: . ts - TS context
3907: Output Parameter:
3908: . lits - number of linear iterations
3910: Notes:
3911: This counter is reset to zero for each successive call to TSSolve().
3913: Level: intermediate
3915: .keywords: TS, get, number, linear, iterations
3917: .seealso: TSGetSNESIterations(), SNESGetKSPIterations()
3918: @*/
3919: PetscErrorCode TSGetKSPIterations(TS ts,PetscInt *lits)
3920: {
3924: *lits = ts->ksp_its;
3925: return(0);
3926: }
3930: /*@
3931: TSGetStepRejections - Gets the total number of rejected steps.
3933: Not Collective
3935: Input Parameter:
3936: . ts - TS context
3938: Output Parameter:
3939: . rejects - number of steps rejected
3941: Notes:
3942: This counter is reset to zero for each successive call to TSSolve().
3944: Level: intermediate
3946: .keywords: TS, get, number
3948: .seealso: TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetSNESFailures(), TSSetMaxSNESFailures(), TSSetErrorIfStepFails()
3949: @*/
3950: PetscErrorCode TSGetStepRejections(TS ts,PetscInt *rejects)
3951: {
3955: *rejects = ts->reject;
3956: return(0);
3957: }
3961: /*@
3962: TSGetSNESFailures - Gets the total number of failed SNES solves
3964: Not Collective
3966: Input Parameter:
3967: . ts - TS context
3969: Output Parameter:
3970: . fails - number of failed nonlinear solves
3972: Notes:
3973: This counter is reset to zero for each successive call to TSSolve().
3975: Level: intermediate
3977: .keywords: TS, get, number
3979: .seealso: TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSSetMaxSNESFailures()
3980: @*/
3981: PetscErrorCode TSGetSNESFailures(TS ts,PetscInt *fails)
3982: {
3986: *fails = ts->num_snes_failures;
3987: return(0);
3988: }
3992: /*@
3993: TSSetMaxStepRejections - Sets the maximum number of step rejections before a step fails
3995: Not Collective
3997: Input Parameter:
3998: + ts - TS context
3999: - rejects - maximum number of rejected steps, pass -1 for unlimited
4001: Notes:
4002: The counter is reset to zero for each step
4004: Options Database Key:
4005: . -ts_max_reject - Maximum number of step rejections before a step fails
4007: Level: intermediate
4009: .keywords: TS, set, maximum, number
4011: .seealso: TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxSNESFailures(), TSGetStepRejections(), TSGetSNESFailures(), TSSetErrorIfStepFails(), TSGetConvergedReason()
4012: @*/
4013: PetscErrorCode TSSetMaxStepRejections(TS ts,PetscInt rejects)
4014: {
4017: ts->max_reject = rejects;
4018: return(0);
4019: }
4023: /*@
4024: TSSetMaxSNESFailures - Sets the maximum number of failed SNES solves
4026: Not Collective
4028: Input Parameter:
4029: + ts - TS context
4030: - fails - maximum number of failed nonlinear solves, pass -1 for unlimited
4032: Notes:
4033: The counter is reset to zero for each successive call to TSSolve().
4035: Options Database Key:
4036: . -ts_max_snes_failures - Maximum number of nonlinear solve failures
4038: Level: intermediate
4040: .keywords: TS, set, maximum, number
4042: .seealso: TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSGetSNESFailures(), SNESGetConvergedReason(), TSGetConvergedReason()
4043: @*/
4044: PetscErrorCode TSSetMaxSNESFailures(TS ts,PetscInt fails)
4045: {
4048: ts->max_snes_failures = fails;
4049: return(0);
4050: }
4054: /*@
4055: TSSetErrorIfStepFails - Error if no step succeeds
4057: Not Collective
4059: Input Parameter:
4060: + ts - TS context
4061: - err - PETSC_TRUE to error if no step succeeds, PETSC_FALSE to return without failure
4063: Options Database Key:
4064: . -ts_error_if_step_fails - Error if no step succeeds
4066: Level: intermediate
4068: .keywords: TS, set, error
4070: .seealso: TSGetSNESIterations(), TSGetKSPIterations(), TSSetMaxStepRejections(), TSGetStepRejections(), TSGetSNESFailures(), TSSetErrorIfStepFails(), TSGetConvergedReason()
4071: @*/
4072: PetscErrorCode TSSetErrorIfStepFails(TS ts,PetscBool err)
4073: {
4076: ts->errorifstepfailed = err;
4077: return(0);
4078: }
4082: /*@C
4083: TSMonitorSolutionBinary - Monitors progress of the TS solvers by VecView() for the solution at each timestep. Normally the viewer is a binary file
4085: Collective on TS
4087: Input Parameters:
4088: + ts - the TS context
4089: . step - current time-step
4090: . ptime - current time
4091: . u - current state
4092: - viewer - binary viewer
4094: Level: intermediate
4096: .keywords: TS, vector, monitor, view
4098: .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
4099: @*/
4100: PetscErrorCode TSMonitorSolutionBinary(TS ts,PetscInt step,PetscReal ptime,Vec u,void *viewer)
4101: {
4103: PetscViewer v = (PetscViewer)viewer;
4106: VecView(u,v);
4107: return(0);
4108: }
4112: /*@C
4113: TSMonitorSolutionVTK - Monitors progress of the TS solvers by VecView() for the solution at each timestep.
4115: Collective on TS
4117: Input Parameters:
4118: + ts - the TS context
4119: . step - current time-step
4120: . ptime - current time
4121: . u - current state
4122: - filenametemplate - string containing a format specifier for the integer time step (e.g. %03D)
4124: Level: intermediate
4126: Notes:
4127: The VTK format does not allow writing multiple time steps in the same file, therefore a different file will be written for each time step.
4128: These are named according to the file name template.
4130: This function is normally passed as an argument to TSMonitorSet() along with TSMonitorSolutionVTKDestroy().
4132: .keywords: TS, vector, monitor, view
4134: .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
4135: @*/
4136: PetscErrorCode TSMonitorSolutionVTK(TS ts,PetscInt step,PetscReal ptime,Vec u,void *filenametemplate)
4137: {
4139: char filename[PETSC_MAX_PATH_LEN];
4140: PetscViewer viewer;
4143: PetscSNPrintf(filename,sizeof(filename),(const char*)filenametemplate,step);
4144: PetscViewerVTKOpen(PetscObjectComm((PetscObject)ts),filename,FILE_MODE_WRITE,&viewer);
4145: VecView(u,viewer);
4146: PetscViewerDestroy(&viewer);
4147: return(0);
4148: }
4152: /*@C
4153: TSMonitorSolutionVTKDestroy - Destroy context for monitoring
4155: Collective on TS
4157: Input Parameters:
4158: . filenametemplate - string containing a format specifier for the integer time step (e.g. %03D)
4160: Level: intermediate
4162: Note:
4163: This function is normally passed to TSMonitorSet() along with TSMonitorSolutionVTK().
4165: .keywords: TS, vector, monitor, view
4167: .seealso: TSMonitorSet(), TSMonitorSolutionVTK()
4168: @*/
4169: PetscErrorCode TSMonitorSolutionVTKDestroy(void *filenametemplate)
4170: {
4174: PetscFree(*(char**)filenametemplate);
4175: return(0);
4176: }
4180: /*@
4181: TSGetAdapt - Get the adaptive controller context for the current method
4183: Collective on TS if controller has not been created yet
4185: Input Arguments:
4186: . ts - time stepping context
4188: Output Arguments:
4189: . adapt - adaptive controller
4191: Level: intermediate
4193: .seealso: TSAdapt, TSAdaptSetType(), TSAdaptChoose()
4194: @*/
4195: PetscErrorCode TSGetAdapt(TS ts,TSAdapt *adapt)
4196: {
4202: if (!ts->adapt) {
4203: TSAdaptCreate(PetscObjectComm((PetscObject)ts),&ts->adapt);
4204: PetscLogObjectParent((PetscObject)ts,(PetscObject)ts->adapt);
4205: PetscObjectIncrementTabLevel((PetscObject)ts->adapt,(PetscObject)ts,1);
4206: }
4207: *adapt = ts->adapt;
4208: return(0);
4209: }
4213: /*@
4214: TSSetTolerances - Set tolerances for local truncation error when using adaptive controller
4216: Logically Collective
4218: Input Arguments:
4219: + ts - time integration context
4220: . atol - scalar absolute tolerances, PETSC_DECIDE to leave current value
4221: . vatol - vector of absolute tolerances or NULL, used in preference to atol if present
4222: . rtol - scalar relative tolerances, PETSC_DECIDE to leave current value
4223: - vrtol - vector of relative tolerances or NULL, used in preference to atol if present
4225: Level: beginner
4227: .seealso: TS, TSAdapt, TSVecNormWRMS(), TSGetTolerances()
4228: @*/
4229: PetscErrorCode TSSetTolerances(TS ts,PetscReal atol,Vec vatol,PetscReal rtol,Vec vrtol)
4230: {
4234: if (atol != PETSC_DECIDE && atol != PETSC_DEFAULT) ts->atol = atol;
4235: if (vatol) {
4236: PetscObjectReference((PetscObject)vatol);
4237: VecDestroy(&ts->vatol);
4239: ts->vatol = vatol;
4240: }
4241: if (rtol != PETSC_DECIDE && rtol != PETSC_DEFAULT) ts->rtol = rtol;
4242: if (vrtol) {
4243: PetscObjectReference((PetscObject)vrtol);
4244: VecDestroy(&ts->vrtol);
4246: ts->vrtol = vrtol;
4247: }
4248: return(0);
4249: }
4253: /*@
4254: TSGetTolerances - Get tolerances for local truncation error when using adaptive controller
4256: Logically Collective
4258: Input Arguments:
4259: . ts - time integration context
4261: Output Arguments:
4262: + atol - scalar absolute tolerances, NULL to ignore
4263: . vatol - vector of absolute tolerances, NULL to ignore
4264: . rtol - scalar relative tolerances, NULL to ignore
4265: - vrtol - vector of relative tolerances, NULL to ignore
4267: Level: beginner
4269: .seealso: TS, TSAdapt, TSVecNormWRMS(), TSSetTolerances()
4270: @*/
4271: PetscErrorCode TSGetTolerances(TS ts,PetscReal *atol,Vec *vatol,PetscReal *rtol,Vec *vrtol)
4272: {
4274: if (atol) *atol = ts->atol;
4275: if (vatol) *vatol = ts->vatol;
4276: if (rtol) *rtol = ts->rtol;
4277: if (vrtol) *vrtol = ts->vrtol;
4278: return(0);
4279: }
4283: /*@
4284: TSErrorNormWRMS - compute a weighted norm of the difference between a vector and the current state
4286: Collective on TS
4288: Input Arguments:
4289: + ts - time stepping context
4290: - Y - state vector to be compared to ts->vec_sol
4292: Output Arguments:
4293: . norm - weighted norm, a value of 1.0 is considered small
4295: Level: developer
4297: .seealso: TSSetTolerances()
4298: @*/
4299: PetscErrorCode TSErrorNormWRMS(TS ts,Vec Y,PetscReal *norm)
4300: {
4301: PetscErrorCode ierr;
4302: PetscInt i,n,N;
4303: const PetscScalar *u,*y;
4304: Vec U;
4305: PetscReal sum,gsum;
4311: U = ts->vec_sol;
4313: if (U == Y) SETERRQ(PetscObjectComm((PetscObject)U),PETSC_ERR_ARG_IDN,"Y cannot be the TS solution vector");
4315: VecGetSize(U,&N);
4316: VecGetLocalSize(U,&n);
4317: VecGetArrayRead(U,&u);
4318: VecGetArrayRead(Y,&y);
4319: sum = 0.;
4320: if (ts->vatol && ts->vrtol) {
4321: const PetscScalar *atol,*rtol;
4322: VecGetArrayRead(ts->vatol,&atol);
4323: VecGetArrayRead(ts->vrtol,&rtol);
4324: for (i=0; i<n; i++) {
4325: PetscReal tol = PetscRealPart(atol[i]) + PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
4326: sum += PetscSqr(PetscAbsScalar(y[i] - u[i]) / tol);
4327: }
4328: VecRestoreArrayRead(ts->vatol,&atol);
4329: VecRestoreArrayRead(ts->vrtol,&rtol);
4330: } else if (ts->vatol) { /* vector atol, scalar rtol */
4331: const PetscScalar *atol;
4332: VecGetArrayRead(ts->vatol,&atol);
4333: for (i=0; i<n; i++) {
4334: PetscReal tol = PetscRealPart(atol[i]) + ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
4335: sum += PetscSqr(PetscAbsScalar(y[i] - u[i]) / tol);
4336: }
4337: VecRestoreArrayRead(ts->vatol,&atol);
4338: } else if (ts->vrtol) { /* scalar atol, vector rtol */
4339: const PetscScalar *rtol;
4340: VecGetArrayRead(ts->vrtol,&rtol);
4341: for (i=0; i<n; i++) {
4342: PetscReal tol = ts->atol + PetscRealPart(rtol[i]) * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
4343: sum += PetscSqr(PetscAbsScalar(y[i] - u[i]) / tol);
4344: }
4345: VecRestoreArrayRead(ts->vrtol,&rtol);
4346: } else { /* scalar atol, scalar rtol */
4347: for (i=0; i<n; i++) {
4348: PetscReal tol = ts->atol + ts->rtol * PetscMax(PetscAbsScalar(u[i]),PetscAbsScalar(y[i]));
4349: sum += PetscSqr(PetscAbsScalar(y[i] - u[i]) / tol);
4350: }
4351: }
4352: VecRestoreArrayRead(U,&u);
4353: VecRestoreArrayRead(Y,&y);
4355: MPI_Allreduce(&sum,&gsum,1,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)ts));
4356: *norm = PetscSqrtReal(gsum / N);
4357: if (PetscIsInfOrNanScalar(*norm)) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_FP,"Infinite or not-a-number generated in norm");
4358: return(0);
4359: }
4363: /*@
4364: TSSetCFLTimeLocal - Set the local CFL constraint relative to forward Euler
4366: Logically Collective on TS
4368: Input Arguments:
4369: + ts - time stepping context
4370: - cfltime - maximum stable time step if using forward Euler (value can be different on each process)
4372: Note:
4373: After calling this function, the global CFL time can be obtained by calling TSGetCFLTime()
4375: Level: intermediate
4377: .seealso: TSGetCFLTime(), TSADAPTCFL
4378: @*/
4379: PetscErrorCode TSSetCFLTimeLocal(TS ts,PetscReal cfltime)
4380: {
4383: ts->cfltime_local = cfltime;
4384: ts->cfltime = -1.;
4385: return(0);
4386: }
4390: /*@
4391: TSGetCFLTime - Get the maximum stable time step according to CFL criteria applied to forward Euler
4393: Collective on TS
4395: Input Arguments:
4396: . ts - time stepping context
4398: Output Arguments:
4399: . cfltime - maximum stable time step for forward Euler
4401: Level: advanced
4403: .seealso: TSSetCFLTimeLocal()
4404: @*/
4405: PetscErrorCode TSGetCFLTime(TS ts,PetscReal *cfltime)
4406: {
4410: if (ts->cfltime < 0) {
4411: MPI_Allreduce(&ts->cfltime_local,&ts->cfltime,1,MPIU_REAL,MPIU_MIN,PetscObjectComm((PetscObject)ts));
4412: }
4413: *cfltime = ts->cfltime;
4414: return(0);
4415: }
4419: /*@
4420: TSVISetVariableBounds - Sets the lower and upper bounds for the solution vector. xl <= x <= xu
4422: Input Parameters:
4423: . ts - the TS context.
4424: . xl - lower bound.
4425: . xu - upper bound.
4427: Notes:
4428: If this routine is not called then the lower and upper bounds are set to
4429: PETSC_NINFINITY and PETSC_INFINITY respectively during SNESSetUp().
4431: Level: advanced
4433: @*/
4434: PetscErrorCode TSVISetVariableBounds(TS ts, Vec xl, Vec xu)
4435: {
4437: SNES snes;
4440: TSGetSNES(ts,&snes);
4441: SNESVISetVariableBounds(snes,xl,xu);
4442: return(0);
4443: }
4445: #if defined(PETSC_HAVE_MATLAB_ENGINE)
4446: #include <mex.h>
4448: typedef struct {char *funcname; mxArray *ctx;} TSMatlabContext;
4452: /*
4453: TSComputeFunction_Matlab - Calls the function that has been set with
4454: TSSetFunctionMatlab().
4456: Collective on TS
4458: Input Parameters:
4459: + snes - the TS context
4460: - u - input vector
4462: Output Parameter:
4463: . y - function vector, as set by TSSetFunction()
4465: Notes:
4466: TSComputeFunction() is typically used within nonlinear solvers
4467: implementations, so most users would not generally call this routine
4468: themselves.
4470: Level: developer
4472: .keywords: TS, nonlinear, compute, function
4474: .seealso: TSSetFunction(), TSGetFunction()
4475: */
4476: PetscErrorCode TSComputeFunction_Matlab(TS snes,PetscReal time,Vec u,Vec udot,Vec y, void *ctx)
4477: {
4478: PetscErrorCode ierr;
4479: TSMatlabContext *sctx = (TSMatlabContext*)ctx;
4480: int nlhs = 1,nrhs = 7;
4481: mxArray *plhs[1],*prhs[7];
4482: long long int lx = 0,lxdot = 0,ly = 0,ls = 0;
4492: PetscMemcpy(&ls,&snes,sizeof(snes));
4493: PetscMemcpy(&lx,&u,sizeof(u));
4494: PetscMemcpy(&lxdot,&udot,sizeof(udot));
4495: PetscMemcpy(&ly,&y,sizeof(u));
4497: prhs[0] = mxCreateDoubleScalar((double)ls);
4498: prhs[1] = mxCreateDoubleScalar(time);
4499: prhs[2] = mxCreateDoubleScalar((double)lx);
4500: prhs[3] = mxCreateDoubleScalar((double)lxdot);
4501: prhs[4] = mxCreateDoubleScalar((double)ly);
4502: prhs[5] = mxCreateString(sctx->funcname);
4503: prhs[6] = sctx->ctx;
4504: mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSComputeFunctionInternal");
4505: mxGetScalar(plhs[0]);
4506: mxDestroyArray(prhs[0]);
4507: mxDestroyArray(prhs[1]);
4508: mxDestroyArray(prhs[2]);
4509: mxDestroyArray(prhs[3]);
4510: mxDestroyArray(prhs[4]);
4511: mxDestroyArray(prhs[5]);
4512: mxDestroyArray(plhs[0]);
4513: return(0);
4514: }
4519: /*
4520: TSSetFunctionMatlab - Sets the function evaluation routine and function
4521: vector for use by the TS routines in solving ODEs
4522: equations from MATLAB. Here the function is a string containing the name of a MATLAB function
4524: Logically Collective on TS
4526: Input Parameters:
4527: + ts - the TS context
4528: - func - function evaluation routine
4530: Calling sequence of func:
4531: $ func (TS ts,PetscReal time,Vec u,Vec udot,Vec f,void *ctx);
4533: Level: beginner
4535: .keywords: TS, nonlinear, set, function
4537: .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
4538: */
4539: PetscErrorCode TSSetFunctionMatlab(TS ts,const char *func,mxArray *ctx)
4540: {
4541: PetscErrorCode ierr;
4542: TSMatlabContext *sctx;
4545: /* currently sctx is memory bleed */
4546: PetscMalloc(sizeof(TSMatlabContext),&sctx);
4547: PetscStrallocpy(func,&sctx->funcname);
4548: /*
4549: This should work, but it doesn't
4550: sctx->ctx = ctx;
4551: mexMakeArrayPersistent(sctx->ctx);
4552: */
4553: sctx->ctx = mxDuplicateArray(ctx);
4555: TSSetIFunction(ts,NULL,TSComputeFunction_Matlab,sctx);
4556: return(0);
4557: }
4561: /*
4562: TSComputeJacobian_Matlab - Calls the function that has been set with
4563: TSSetJacobianMatlab().
4565: Collective on TS
4567: Input Parameters:
4568: + ts - the TS context
4569: . u - input vector
4570: . A, B - the matrices
4571: - ctx - user context
4573: Level: developer
4575: .keywords: TS, nonlinear, compute, function
4577: .seealso: TSSetFunction(), TSGetFunction()
4578: @*/
4579: PetscErrorCode TSComputeJacobian_Matlab(TS ts,PetscReal time,Vec u,Vec udot,PetscReal shift,Mat A,Mat B,void *ctx)
4580: {
4581: PetscErrorCode ierr;
4582: TSMatlabContext *sctx = (TSMatlabContext*)ctx;
4583: int nlhs = 2,nrhs = 9;
4584: mxArray *plhs[2],*prhs[9];
4585: long long int lx = 0,lxdot = 0,lA = 0,ls = 0, lB = 0;
4591: /* call Matlab function in ctx with arguments u and y */
4593: PetscMemcpy(&ls,&ts,sizeof(ts));
4594: PetscMemcpy(&lx,&u,sizeof(u));
4595: PetscMemcpy(&lxdot,&udot,sizeof(u));
4596: PetscMemcpy(&lA,A,sizeof(u));
4597: PetscMemcpy(&lB,B,sizeof(u));
4599: prhs[0] = mxCreateDoubleScalar((double)ls);
4600: prhs[1] = mxCreateDoubleScalar((double)time);
4601: prhs[2] = mxCreateDoubleScalar((double)lx);
4602: prhs[3] = mxCreateDoubleScalar((double)lxdot);
4603: prhs[4] = mxCreateDoubleScalar((double)shift);
4604: prhs[5] = mxCreateDoubleScalar((double)lA);
4605: prhs[6] = mxCreateDoubleScalar((double)lB);
4606: prhs[7] = mxCreateString(sctx->funcname);
4607: prhs[8] = sctx->ctx;
4608: mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSComputeJacobianInternal");
4609: mxGetScalar(plhs[0]);
4610: mxDestroyArray(prhs[0]);
4611: mxDestroyArray(prhs[1]);
4612: mxDestroyArray(prhs[2]);
4613: mxDestroyArray(prhs[3]);
4614: mxDestroyArray(prhs[4]);
4615: mxDestroyArray(prhs[5]);
4616: mxDestroyArray(prhs[6]);
4617: mxDestroyArray(prhs[7]);
4618: mxDestroyArray(plhs[0]);
4619: mxDestroyArray(plhs[1]);
4620: return(0);
4621: }
4626: /*
4627: TSSetJacobianMatlab - Sets the Jacobian function evaluation routine and two empty Jacobian matrices
4628: 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
4630: Logically Collective on TS
4632: Input Parameters:
4633: + ts - the TS context
4634: . A,B - Jacobian matrices
4635: . func - function evaluation routine
4636: - ctx - user context
4638: Calling sequence of func:
4639: $ flag = func (TS ts,PetscReal time,Vec u,Vec udot,Mat A,Mat B,void *ctx);
4642: Level: developer
4644: .keywords: TS, nonlinear, set, function
4646: .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
4647: */
4648: PetscErrorCode TSSetJacobianMatlab(TS ts,Mat A,Mat B,const char *func,mxArray *ctx)
4649: {
4650: PetscErrorCode ierr;
4651: TSMatlabContext *sctx;
4654: /* currently sctx is memory bleed */
4655: PetscMalloc(sizeof(TSMatlabContext),&sctx);
4656: PetscStrallocpy(func,&sctx->funcname);
4657: /*
4658: This should work, but it doesn't
4659: sctx->ctx = ctx;
4660: mexMakeArrayPersistent(sctx->ctx);
4661: */
4662: sctx->ctx = mxDuplicateArray(ctx);
4664: TSSetIJacobian(ts,A,B,TSComputeJacobian_Matlab,sctx);
4665: return(0);
4666: }
4670: /*
4671: TSMonitor_Matlab - Calls the function that has been set with TSMonitorSetMatlab().
4673: Collective on TS
4675: .seealso: TSSetFunction(), TSGetFunction()
4676: @*/
4677: PetscErrorCode TSMonitor_Matlab(TS ts,PetscInt it, PetscReal time,Vec u, void *ctx)
4678: {
4679: PetscErrorCode ierr;
4680: TSMatlabContext *sctx = (TSMatlabContext*)ctx;
4681: int nlhs = 1,nrhs = 6;
4682: mxArray *plhs[1],*prhs[6];
4683: long long int lx = 0,ls = 0;
4689: PetscMemcpy(&ls,&ts,sizeof(ts));
4690: PetscMemcpy(&lx,&u,sizeof(u));
4692: prhs[0] = mxCreateDoubleScalar((double)ls);
4693: prhs[1] = mxCreateDoubleScalar((double)it);
4694: prhs[2] = mxCreateDoubleScalar((double)time);
4695: prhs[3] = mxCreateDoubleScalar((double)lx);
4696: prhs[4] = mxCreateString(sctx->funcname);
4697: prhs[5] = sctx->ctx;
4698: mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscTSMonitorInternal");
4699: mxGetScalar(plhs[0]);
4700: mxDestroyArray(prhs[0]);
4701: mxDestroyArray(prhs[1]);
4702: mxDestroyArray(prhs[2]);
4703: mxDestroyArray(prhs[3]);
4704: mxDestroyArray(prhs[4]);
4705: mxDestroyArray(plhs[0]);
4706: return(0);
4707: }
4712: /*
4713: TSMonitorSetMatlab - Sets the monitor function from Matlab
4715: Level: developer
4717: .keywords: TS, nonlinear, set, function
4719: .seealso: TSGetFunction(), TSComputeFunction(), TSSetJacobian(), TSSetFunction()
4720: */
4721: PetscErrorCode TSMonitorSetMatlab(TS ts,const char *func,mxArray *ctx)
4722: {
4723: PetscErrorCode ierr;
4724: TSMatlabContext *sctx;
4727: /* currently sctx is memory bleed */
4728: PetscMalloc(sizeof(TSMatlabContext),&sctx);
4729: PetscStrallocpy(func,&sctx->funcname);
4730: /*
4731: This should work, but it doesn't
4732: sctx->ctx = ctx;
4733: mexMakeArrayPersistent(sctx->ctx);
4734: */
4735: sctx->ctx = mxDuplicateArray(ctx);
4737: TSMonitorSet(ts,TSMonitor_Matlab,sctx,NULL);
4738: return(0);
4739: }
4740: #endif
4746: /*@C
4747: TSMonitorLGSolution - Monitors progress of the TS solvers by plotting each component of the solution vector
4748: in a time based line graph
4750: Collective on TS
4752: Input Parameters:
4753: + ts - the TS context
4754: . step - current time-step
4755: . ptime - current time
4756: - lg - a line graph object
4758: Level: intermediate
4760: Notes: each process in a parallel run displays its component solutions in a separate window
4762: .keywords: TS, vector, monitor, view
4764: .seealso: TSMonitorSet(), TSMonitorDefault(), VecView()
4765: @*/
4766: PetscErrorCode TSMonitorLGSolution(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
4767: {
4768: PetscErrorCode ierr;
4769: TSMonitorLGCtx ctx = (TSMonitorLGCtx)dummy;
4770: const PetscScalar *yy;
4771: PetscInt dim;
4774: if (!step) {
4775: PetscDrawAxis axis;
4776: PetscDrawLGGetAxis(ctx->lg,&axis);
4777: PetscDrawAxisSetLabels(axis,"Solution as function of time","Time","Solution");
4778: VecGetLocalSize(u,&dim);
4779: PetscDrawLGSetDimension(ctx->lg,dim);
4780: PetscDrawLGReset(ctx->lg);
4781: }
4782: VecGetArrayRead(u,&yy);
4783: #if defined(PETSC_USE_COMPLEX)
4784: {
4785: PetscReal *yreal;
4786: PetscInt i,n;
4787: VecGetLocalSize(u,&n);
4788: PetscMalloc1(n,&yreal);
4789: for (i=0; i<n; i++) yreal[i] = PetscRealPart(yy[i]);
4790: PetscDrawLGAddCommonPoint(ctx->lg,ptime,yreal);
4791: PetscFree(yreal);
4792: }
4793: #else
4794: PetscDrawLGAddCommonPoint(ctx->lg,ptime,yy);
4795: #endif
4796: VecRestoreArrayRead(u,&yy);
4797: if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
4798: PetscDrawLGDraw(ctx->lg);
4799: }
4800: return(0);
4801: }
4805: /*@C
4806: TSMonitorLGError - Monitors progress of the TS solvers by plotting each component of the solution vector
4807: in a time based line graph
4809: Collective on TS
4811: Input Parameters:
4812: + ts - the TS context
4813: . step - current time-step
4814: . ptime - current time
4815: - lg - a line graph object
4817: Level: intermediate
4819: Notes:
4820: Only for sequential solves.
4822: The user must provide the solution using TSSetSolutionFunction() to use this monitor.
4824: Options Database Keys:
4825: . -ts_monitor_lg_error - create a graphical monitor of error history
4827: .keywords: TS, vector, monitor, view
4829: .seealso: TSMonitorSet(), TSMonitorDefault(), VecView(), TSSetSolutionFunction()
4830: @*/
4831: PetscErrorCode TSMonitorLGError(TS ts,PetscInt step,PetscReal ptime,Vec u,void *dummy)
4832: {
4833: PetscErrorCode ierr;
4834: TSMonitorLGCtx ctx = (TSMonitorLGCtx)dummy;
4835: const PetscScalar *yy;
4836: Vec y;
4837: PetscInt dim;
4840: if (!step) {
4841: PetscDrawAxis axis;
4842: PetscDrawLGGetAxis(ctx->lg,&axis);
4843: PetscDrawAxisSetLabels(axis,"Error in solution as function of time","Time","Solution");
4844: VecGetLocalSize(u,&dim);
4845: PetscDrawLGSetDimension(ctx->lg,dim);
4846: PetscDrawLGReset(ctx->lg);
4847: }
4848: VecDuplicate(u,&y);
4849: TSComputeSolutionFunction(ts,ptime,y);
4850: VecAXPY(y,-1.0,u);
4851: VecGetArrayRead(y,&yy);
4852: #if defined(PETSC_USE_COMPLEX)
4853: {
4854: PetscReal *yreal;
4855: PetscInt i,n;
4856: VecGetLocalSize(y,&n);
4857: PetscMalloc1(n,&yreal);
4858: for (i=0; i<n; i++) yreal[i] = PetscRealPart(yy[i]);
4859: PetscDrawLGAddCommonPoint(ctx->lg,ptime,yreal);
4860: PetscFree(yreal);
4861: }
4862: #else
4863: PetscDrawLGAddCommonPoint(ctx->lg,ptime,yy);
4864: #endif
4865: VecRestoreArrayRead(y,&yy);
4866: VecDestroy(&y);
4867: if (((ctx->howoften > 0) && (!(step % ctx->howoften))) || ((ctx->howoften == -1) && ts->reason)) {
4868: PetscDrawLGDraw(ctx->lg);
4869: }
4870: return(0);
4871: }
4875: PetscErrorCode TSMonitorLGSNESIterations(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
4876: {
4877: TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
4878: PetscReal x = ptime,y;
4880: PetscInt its;
4883: if (!n) {
4884: PetscDrawAxis axis;
4886: PetscDrawLGGetAxis(ctx->lg,&axis);
4887: PetscDrawAxisSetLabels(axis,"Nonlinear iterations as function of time","Time","SNES Iterations");
4888: PetscDrawLGReset(ctx->lg);
4890: ctx->snes_its = 0;
4891: }
4892: TSGetSNESIterations(ts,&its);
4893: y = its - ctx->snes_its;
4894: PetscDrawLGAddPoint(ctx->lg,&x,&y);
4895: if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
4896: PetscDrawLGDraw(ctx->lg);
4897: }
4898: ctx->snes_its = its;
4899: return(0);
4900: }
4904: PetscErrorCode TSMonitorLGKSPIterations(TS ts,PetscInt n,PetscReal ptime,Vec v,void *monctx)
4905: {
4906: TSMonitorLGCtx ctx = (TSMonitorLGCtx) monctx;
4907: PetscReal x = ptime,y;
4909: PetscInt its;
4912: if (!n) {
4913: PetscDrawAxis axis;
4915: PetscDrawLGGetAxis(ctx->lg,&axis);
4916: PetscDrawAxisSetLabels(axis,"Linear iterations as function of time","Time","KSP Iterations");
4917: PetscDrawLGReset(ctx->lg);
4919: ctx->ksp_its = 0;
4920: }
4921: TSGetKSPIterations(ts,&its);
4922: y = its - ctx->ksp_its;
4923: PetscDrawLGAddPoint(ctx->lg,&x,&y);
4924: if (((ctx->howoften > 0) && (!(n % ctx->howoften)) && (n > -1)) || ((ctx->howoften == -1) && (n == -1))) {
4925: PetscDrawLGDraw(ctx->lg);
4926: }
4927: ctx->ksp_its = its;
4928: return(0);
4929: }
4933: /*@
4934: TSComputeLinearStability - computes the linear stability function at a point
4936: Collective on TS and Vec
4938: Input Parameters:
4939: + ts - the TS context
4940: - xr,xi - real and imaginary part of input arguments
4942: Output Parameters:
4943: . yr,yi - real and imaginary part of function value
4945: Level: developer
4947: .keywords: TS, compute
4949: .seealso: TSSetRHSFunction(), TSComputeIFunction()
4950: @*/
4951: PetscErrorCode TSComputeLinearStability(TS ts,PetscReal xr,PetscReal xi,PetscReal *yr,PetscReal *yi)
4952: {
4957: if (!ts->ops->linearstability) SETERRQ(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"Linearized stability function not provided for this method");
4958: (*ts->ops->linearstability)(ts,xr,xi,yr,yi);
4959: return(0);
4960: }
4964: /*@
4965: TSRollBack - Rolls back one time step
4967: Collective on TS
4969: Input Parameter:
4970: . ts - the TS context obtained from TSCreate()
4972: Level: advanced
4974: .keywords: TS, timestep, rollback
4976: .seealso: TSCreate(), TSSetUp(), TSDestroy(), TSSolve(), TSSetPreStep(), TSSetPreStage(), TSInterpolate()
4977: @*/
4978: PetscErrorCode TSRollBack(TS ts)
4979: {
4985: if (!ts->ops->rollback) SETERRQ1(PetscObjectComm((PetscObject)ts),PETSC_ERR_SUP,"TSRollBack not implemented for type '%s'",((PetscObject)ts)->type_name);
4986: (*ts->ops->rollback)(ts);
4987: ts->time_step = ts->ptime - ts->ptime_prev;
4988: ts->ptime = ts->ptime_prev;
4989: return(0);
4990: }