xref: /petsc/src/ts/utils/dmts.c (revision 5a856986583887c326abe5dfd149e8184a29cd80)
1 #include <petsc/private/tsimpl.h>     /*I "petscts.h" I*/
2 #include <petsc/private/dmimpl.h>
3 
4 static PetscErrorCode DMTSDestroy(DMTS *kdm)
5 {
6   PetscErrorCode ierr;
7 
8   PetscFunctionBegin;
9   if (!*kdm) PetscFunctionReturn(0);
10   PetscValidHeaderSpecific((*kdm),DMTS_CLASSID,1);
11   if (--((PetscObject)(*kdm))->refct > 0) {*kdm = 0; PetscFunctionReturn(0);}
12   if ((*kdm)->ops->destroy) {ierr = ((*kdm)->ops->destroy)(*kdm);CHKERRQ(ierr);}
13   ierr = PetscHeaderDestroy(kdm);CHKERRQ(ierr);
14   PetscFunctionReturn(0);
15 }
16 
17 PetscErrorCode DMTSLoad(DMTS kdm,PetscViewer viewer)
18 {
19   PetscErrorCode ierr;
20 
21   PetscFunctionBegin;
22   ierr = PetscViewerBinaryRead(viewer,&kdm->ops->ifunction,1,NULL,PETSC_FUNCTION);CHKERRQ(ierr);
23   ierr = PetscViewerBinaryRead(viewer,&kdm->ops->ifunctionview,1,NULL,PETSC_FUNCTION);CHKERRQ(ierr);
24   ierr = PetscViewerBinaryRead(viewer,&kdm->ops->ifunctionload,1,NULL,PETSC_FUNCTION);CHKERRQ(ierr);
25   if (kdm->ops->ifunctionload) {
26     ierr = (*kdm->ops->ifunctionload)(&kdm->ifunctionctx,viewer);CHKERRQ(ierr);
27   }
28   ierr = PetscViewerBinaryRead(viewer,&kdm->ops->ijacobian,1,NULL,PETSC_FUNCTION);CHKERRQ(ierr);
29   ierr = PetscViewerBinaryRead(viewer,&kdm->ops->ijacobianview,1,NULL,PETSC_FUNCTION);CHKERRQ(ierr);
30   ierr = PetscViewerBinaryRead(viewer,&kdm->ops->ijacobianload,1,NULL,PETSC_FUNCTION);CHKERRQ(ierr);
31   if (kdm->ops->ijacobianload) {
32     ierr = (*kdm->ops->ijacobianload)(&kdm->ijacobianctx,viewer);CHKERRQ(ierr);
33   }
34   PetscFunctionReturn(0);
35 }
36 
37 PetscErrorCode DMTSView(DMTS kdm,PetscViewer viewer)
38 {
39   PetscErrorCode ierr;
40   PetscBool      isascii,isbinary;
41 
42   PetscFunctionBegin;
43   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
44   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr);
45   if (isascii) {
46 #if defined(PETSC_SERIALIZE_FUNCTIONS)
47     const char *fname;
48 
49     ierr = PetscFPTFind(kdm->ops->ifunction,&fname);CHKERRQ(ierr);
50     if (fname) {
51       ierr = PetscViewerASCIIPrintf(viewer,"  IFunction used by TS: %s\n",fname);CHKERRQ(ierr);
52     }
53     ierr = PetscFPTFind(kdm->ops->ijacobian,&fname);CHKERRQ(ierr);
54     if (fname) {
55       ierr = PetscViewerASCIIPrintf(viewer,"  IJacobian function used by TS: %s\n",fname);CHKERRQ(ierr);
56     }
57 #endif
58   } else if (isbinary) {
59     struct {
60       TSIFunction ifunction;
61     } funcstruct;
62     struct {
63       PetscErrorCode (*ifunctionview)(void*,PetscViewer);
64     } funcviewstruct;
65     struct {
66       PetscErrorCode (*ifunctionload)(void**,PetscViewer);
67     } funcloadstruct;
68     struct {
69       TSIJacobian ijacobian;
70     } jacstruct;
71     struct {
72       PetscErrorCode (*ijacobianview)(void*,PetscViewer);
73     } jacviewstruct;
74     struct {
75       PetscErrorCode (*ijacobianload)(void**,PetscViewer);
76     } jacloadstruct;
77 
78     funcstruct.ifunction         = kdm->ops->ifunction;
79     funcviewstruct.ifunctionview = kdm->ops->ifunctionview;
80     funcloadstruct.ifunctionload = kdm->ops->ifunctionload;
81     ierr = PetscViewerBinaryWrite(viewer,&funcstruct,1,PETSC_FUNCTION,PETSC_FALSE);CHKERRQ(ierr);
82     ierr = PetscViewerBinaryWrite(viewer,&funcviewstruct,1,PETSC_FUNCTION,PETSC_FALSE);CHKERRQ(ierr);
83     ierr = PetscViewerBinaryWrite(viewer,&funcloadstruct,1,PETSC_FUNCTION,PETSC_FALSE);CHKERRQ(ierr);
84     if (kdm->ops->ifunctionview) {
85       ierr = (*kdm->ops->ifunctionview)(kdm->ifunctionctx,viewer);CHKERRQ(ierr);
86     }
87     jacstruct.ijacobian = kdm->ops->ijacobian;
88     jacviewstruct.ijacobianview = kdm->ops->ijacobianview;
89     jacloadstruct.ijacobianload = kdm->ops->ijacobianload;
90     ierr = PetscViewerBinaryWrite(viewer,&jacstruct,1,PETSC_FUNCTION,PETSC_FALSE);CHKERRQ(ierr);
91     ierr = PetscViewerBinaryWrite(viewer,&jacviewstruct,1,PETSC_FUNCTION,PETSC_FALSE);CHKERRQ(ierr);
92     ierr = PetscViewerBinaryWrite(viewer,&jacloadstruct,1,PETSC_FUNCTION,PETSC_FALSE);CHKERRQ(ierr);
93     if (kdm->ops->ijacobianview) {
94       ierr = (*kdm->ops->ijacobianview)(kdm->ijacobianctx,viewer);CHKERRQ(ierr);
95     }
96   }
97   PetscFunctionReturn(0);
98 }
99 
100 static PetscErrorCode DMTSCreate(MPI_Comm comm,DMTS *kdm)
101 {
102   PetscErrorCode ierr;
103 
104   PetscFunctionBegin;
105   ierr = TSInitializePackage();CHKERRQ(ierr);
106   ierr = PetscHeaderCreate(*kdm, DMTS_CLASSID, "DMTS", "DMTS", "DMTS", comm, DMTSDestroy, DMTSView);CHKERRQ(ierr);
107   PetscFunctionReturn(0);
108 }
109 
110 /* Attaches the DMTS to the coarse level.
111  * Under what conditions should we copy versus duplicate?
112  */
113 static PetscErrorCode DMCoarsenHook_DMTS(DM dm,DM dmc,void *ctx)
114 {
115   PetscErrorCode ierr;
116 
117   PetscFunctionBegin;
118   ierr = DMCopyDMTS(dm,dmc);CHKERRQ(ierr);
119   PetscFunctionReturn(0);
120 }
121 
122 /* This could restrict auxiliary information to the coarse level.
123  */
124 static PetscErrorCode DMRestrictHook_DMTS(DM dm,Mat Restrict,Vec rscale,Mat Inject,DM dmc,void *ctx)
125 {
126 
127   PetscFunctionBegin;
128   PetscFunctionReturn(0);
129 }
130 
131 static PetscErrorCode DMSubDomainHook_DMTS(DM dm,DM subdm,void *ctx)
132 {
133   PetscErrorCode ierr;
134 
135   PetscFunctionBegin;
136   ierr = DMCopyDMTS(dm,subdm);CHKERRQ(ierr);
137   PetscFunctionReturn(0);
138 }
139 
140 /* This could restrict auxiliary information to the coarse level.
141  */
142 static PetscErrorCode DMSubDomainRestrictHook_DMTS(DM dm,VecScatter gscat,VecScatter lscat,DM subdm,void *ctx)
143 {
144   PetscFunctionBegin;
145   PetscFunctionReturn(0);
146 }
147 
148 /*@C
149    DMTSCopy - copies the information in a DMTS to another DMTS
150 
151    Not Collective
152 
153    Input Argument:
154 +  kdm - Original DMTS
155 -  nkdm - DMTS to receive the data, should have been created with DMTSCreate()
156 
157    Level: developer
158 
159 .seealso: DMTSCreate(), DMTSDestroy()
160 @*/
161 PetscErrorCode DMTSCopy(DMTS kdm,DMTS nkdm)
162 {
163   PetscErrorCode ierr;
164 
165   PetscFunctionBegin;
166   PetscValidHeaderSpecific(kdm,DMTS_CLASSID,1);
167   PetscValidHeaderSpecific(nkdm,DMTS_CLASSID,2);
168   nkdm->ops->rhsfunction = kdm->ops->rhsfunction;
169   nkdm->ops->rhsjacobian = kdm->ops->rhsjacobian;
170   nkdm->ops->ifunction   = kdm->ops->ifunction;
171   nkdm->ops->ijacobian   = kdm->ops->ijacobian;
172   nkdm->ops->i2function  = kdm->ops->i2function;
173   nkdm->ops->i2jacobian  = kdm->ops->i2jacobian;
174   nkdm->ops->solution    = kdm->ops->solution;
175   nkdm->ops->destroy     = kdm->ops->destroy;
176   nkdm->ops->duplicate   = kdm->ops->duplicate;
177 
178   nkdm->rhsfunctionctx = kdm->rhsfunctionctx;
179   nkdm->rhsjacobianctx = kdm->rhsjacobianctx;
180   nkdm->ifunctionctx   = kdm->ifunctionctx;
181   nkdm->ijacobianctx   = kdm->ijacobianctx;
182   nkdm->i2functionctx  = kdm->i2functionctx;
183   nkdm->i2jacobianctx  = kdm->i2jacobianctx;
184   nkdm->solutionctx    = kdm->solutionctx;
185 
186   nkdm->data = kdm->data;
187 
188   /*
189   nkdm->fortran_func_pointers[0] = kdm->fortran_func_pointers[0];
190   nkdm->fortran_func_pointers[1] = kdm->fortran_func_pointers[1];
191   nkdm->fortran_func_pointers[2] = kdm->fortran_func_pointers[2];
192   */
193 
194   /* implementation specific copy hooks */
195   if (kdm->ops->duplicate) {ierr = (*kdm->ops->duplicate)(kdm,nkdm);CHKERRQ(ierr);}
196   PetscFunctionReturn(0);
197 }
198 
199 /*@C
200    DMGetDMTS - get read-only private DMTS context from a DM
201 
202    Not Collective
203 
204    Input Argument:
205 .  dm - DM to be used with TS
206 
207    Output Argument:
208 .  tsdm - private DMTS context
209 
210    Level: developer
211 
212    Notes:
213    Use DMGetDMTSWrite() if write access is needed. The DMTSSetXXX API should be used wherever possible.
214 
215 .seealso: DMGetDMTSWrite()
216 @*/
217 PetscErrorCode DMGetDMTS(DM dm,DMTS *tsdm)
218 {
219   PetscErrorCode ierr;
220 
221   PetscFunctionBegin;
222   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
223   *tsdm = (DMTS) dm->dmts;
224   if (!*tsdm) {
225     ierr = PetscInfo(dm,"Creating new DMTS\n");CHKERRQ(ierr);
226     ierr = DMTSCreate(PetscObjectComm((PetscObject)dm),tsdm);CHKERRQ(ierr);
227     dm->dmts = (PetscObject) *tsdm;
228     (*tsdm)->originaldm = dm;
229     ierr = DMCoarsenHookAdd(dm,DMCoarsenHook_DMTS,DMRestrictHook_DMTS,NULL);CHKERRQ(ierr);
230     ierr = DMSubDomainHookAdd(dm,DMSubDomainHook_DMTS,DMSubDomainRestrictHook_DMTS,NULL);CHKERRQ(ierr);
231   }
232   PetscFunctionReturn(0);
233 }
234 
235 /*@C
236    DMGetDMTSWrite - get write access to private DMTS context from a DM
237 
238    Not Collective
239 
240    Input Argument:
241 .  dm - DM to be used with TS
242 
243    Output Argument:
244 .  tsdm - private DMTS context
245 
246    Level: developer
247 
248 .seealso: DMGetDMTS()
249 @*/
250 PetscErrorCode DMGetDMTSWrite(DM dm,DMTS *tsdm)
251 {
252   PetscErrorCode ierr;
253   DMTS           sdm;
254 
255   PetscFunctionBegin;
256   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
257   ierr = DMGetDMTS(dm,&sdm);CHKERRQ(ierr);
258   if (!sdm->originaldm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"DMTS has a NULL originaldm");
259   if (sdm->originaldm != dm) {  /* Copy on write */
260     DMTS oldsdm = sdm;
261     ierr     = PetscInfo(dm,"Copying DMTS due to write\n");CHKERRQ(ierr);
262     ierr     = DMTSCreate(PetscObjectComm((PetscObject)dm),&sdm);CHKERRQ(ierr);
263     ierr     = DMTSCopy(oldsdm,sdm);CHKERRQ(ierr);
264     ierr     = DMTSDestroy((DMTS*)&dm->dmts);CHKERRQ(ierr);
265     dm->dmts = (PetscObject) sdm;
266     sdm->originaldm = dm;
267   }
268   *tsdm = sdm;
269   PetscFunctionReturn(0);
270 }
271 
272 /*@C
273    DMCopyDMTS - copies a DM context to a new DM
274 
275    Logically Collective
276 
277    Input Arguments:
278 +  dmsrc - DM to obtain context from
279 -  dmdest - DM to add context to
280 
281    Level: developer
282 
283    Note:
284    The context is copied by reference. This function does not ensure that a context exists.
285 
286 .seealso: DMGetDMTS(), TSSetDM()
287 @*/
288 PetscErrorCode DMCopyDMTS(DM dmsrc,DM dmdest)
289 {
290   PetscErrorCode ierr;
291 
292   PetscFunctionBegin;
293   PetscValidHeaderSpecific(dmsrc,DM_CLASSID,1);
294   PetscValidHeaderSpecific(dmdest,DM_CLASSID,2);
295   ierr         = DMTSDestroy((DMTS*)&dmdest->dmts);CHKERRQ(ierr);
296   dmdest->dmts = dmsrc->dmts;
297   ierr         = PetscObjectReference(dmdest->dmts);CHKERRQ(ierr);
298   ierr         = DMCoarsenHookAdd(dmdest,DMCoarsenHook_DMTS,DMRestrictHook_DMTS,NULL);CHKERRQ(ierr);
299   ierr         = DMSubDomainHookAdd(dmdest,DMSubDomainHook_DMTS,DMSubDomainRestrictHook_DMTS,NULL);CHKERRQ(ierr);
300   PetscFunctionReturn(0);
301 }
302 
303 /*@C
304    DMTSSetIFunction - set TS implicit function evaluation function
305 
306    Not Collective
307 
308    Input Arguments:
309 +  dm - DM to be used with TS
310 .  func - function evaluation function, see TSSetIFunction() for calling sequence
311 -  ctx - context for residual evaluation
312 
313    Level: advanced
314 
315    Note:
316    TSSetFunction() is normally used, but it calls this function internally because the user context is actually
317    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
318    not. If DM took a more central role at some later date, this could become the primary method of setting the residual.
319 
320 .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian()
321 @*/
322 PetscErrorCode DMTSSetIFunction(DM dm,TSIFunction func,void *ctx)
323 {
324   PetscErrorCode ierr;
325   DMTS           tsdm;
326 
327   PetscFunctionBegin;
328   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
329   ierr = DMGetDMTSWrite(dm,&tsdm);CHKERRQ(ierr);
330   if (func) tsdm->ops->ifunction = func;
331   if (ctx)  tsdm->ifunctionctx = ctx;
332   PetscFunctionReturn(0);
333 }
334 
335 /*@C
336    DMTSGetIFunction - get TS implicit residual evaluation function
337 
338    Not Collective
339 
340    Input Argument:
341 .  dm - DM to be used with TS
342 
343    Output Arguments:
344 +  func - function evaluation function, see TSSetIFunction() for calling sequence
345 -  ctx - context for residual evaluation
346 
347    Level: advanced
348 
349    Note:
350    TSGetFunction() is normally used, but it calls this function internally because the user context is actually
351    associated with the DM.
352 
353 .seealso: DMTSSetContext(), DMTSSetFunction(), TSSetFunction()
354 @*/
355 PetscErrorCode DMTSGetIFunction(DM dm,TSIFunction *func,void **ctx)
356 {
357   PetscErrorCode ierr;
358   DMTS           tsdm;
359 
360   PetscFunctionBegin;
361   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
362   ierr = DMGetDMTS(dm,&tsdm);CHKERRQ(ierr);
363   if (func) *func = tsdm->ops->ifunction;
364   if (ctx)  *ctx = tsdm->ifunctionctx;
365   PetscFunctionReturn(0);
366 }
367 
368 /*@C
369    DMTSSetI2Function - set TS implicit function evaluation function for 2nd order systems
370 
371    Not Collective
372 
373    Input Arguments:
374 +  dm - DM to be used with TS
375 .  fun - function evaluation function, see TSSetI2Function() for calling sequence
376 -  ctx - context for residual evaluation
377 
378    Level: advanced
379 
380    Note:
381    TSSetI2Function() is normally used, but it calls this function internally because the user context is actually
382    associated with the DM.
383 
384 .seealso: TSSetI2Function()
385 @*/
386 PetscErrorCode DMTSSetI2Function(DM dm,TSI2Function fun,void *ctx)
387 {
388   DMTS           tsdm;
389   PetscErrorCode ierr;
390 
391   PetscFunctionBegin;
392   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
393   ierr = DMGetDMTSWrite(dm,&tsdm);CHKERRQ(ierr);
394   if (fun) tsdm->ops->i2function = fun;
395   if (ctx) tsdm->i2functionctx   = ctx;
396   PetscFunctionReturn(0);
397 }
398 
399 /*@C
400    DMTSGetI2Function - get TS implicit residual evaluation function for 2nd order systems
401 
402    Not Collective
403 
404    Input Argument:
405 .  dm - DM to be used with TS
406 
407    Output Arguments:
408 +  fun - function evaluation function, see TSSetI2Function() for calling sequence
409 -  ctx - context for residual evaluation
410 
411    Level: advanced
412 
413    Note:
414    TSGetI2Function() is normally used, but it calls this function internally because the user context is actually
415    associated with the DM.
416 
417 .seealso: DMTSSetI2Function(),TSGetI2Function()
418 @*/
419 PetscErrorCode DMTSGetI2Function(DM dm,TSI2Function *fun,void **ctx)
420 {
421   DMTS           tsdm;
422   PetscErrorCode ierr;
423 
424   PetscFunctionBegin;
425   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
426   ierr = DMGetDMTS(dm,&tsdm);CHKERRQ(ierr);
427   if (fun) *fun = tsdm->ops->i2function;
428   if (ctx) *ctx = tsdm->i2functionctx;
429   PetscFunctionReturn(0);
430 }
431 
432 /*@C
433    DMTSSetI2Jacobian - set TS implicit Jacobian evaluation function for 2nd order systems
434 
435    Not Collective
436 
437    Input Arguments:
438 +  dm - DM to be used with TS
439 .  fun - Jacobian evaluation function, see TSSetI2Jacobian() for calling sequence
440 -  ctx - context for Jacobian evaluation
441 
442    Level: advanced
443 
444    Note:
445    TSSetI2Jacobian() is normally used, but it calls this function internally because the user context is actually
446    associated with the DM.
447 
448 .seealso: TSSetI2Jacobian()
449 @*/
450 PetscErrorCode DMTSSetI2Jacobian(DM dm,TSI2Jacobian jac,void *ctx)
451 {
452   DMTS           tsdm;
453   PetscErrorCode ierr;
454 
455   PetscFunctionBegin;
456   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
457   ierr = DMGetDMTSWrite(dm,&tsdm);CHKERRQ(ierr);
458   if (jac) tsdm->ops->i2jacobian = jac;
459   if (ctx) tsdm->i2jacobianctx   = ctx;
460   PetscFunctionReturn(0);
461 }
462 
463 /*@C
464    DMTSGetI2Jacobian - get TS implicit Jacobian evaluation function for 2nd order systems
465 
466    Not Collective
467 
468    Input Argument:
469 .  dm - DM to be used with TS
470 
471    Output Arguments:
472 +  jac - Jacobian evaluation function, see TSSetI2Jacobian() for calling sequence
473 -  ctx - context for Jacobian evaluation
474 
475    Level: advanced
476 
477    Note:
478    TSGetI2Jacobian() is normally used, but it calls this function internally because the user context is actually
479    associated with the DM.
480 
481 .seealso: DMTSSetI2Jacobian(),TSGetI2Jacobian()
482 @*/
483 PetscErrorCode DMTSGetI2Jacobian(DM dm,TSI2Jacobian *jac,void **ctx)
484 {
485   DMTS           tsdm;
486   PetscErrorCode ierr;
487 
488   PetscFunctionBegin;
489   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
490   ierr = DMGetDMTS(dm,&tsdm);CHKERRQ(ierr);
491   if (jac) *jac = tsdm->ops->i2jacobian;
492   if (ctx) *ctx = tsdm->i2jacobianctx;
493   PetscFunctionReturn(0);
494 }
495 
496 /*@C
497    DMTSSetRHSFunction - set TS explicit residual evaluation function
498 
499    Not Collective
500 
501    Input Arguments:
502 +  dm - DM to be used with TS
503 .  func - RHS function evaluation function, see TSSetRHSFunction() for calling sequence
504 -  ctx - context for residual evaluation
505 
506    Level: advanced
507 
508    Note:
509    TSSetRSHFunction() is normally used, but it calls this function internally because the user context is actually
510    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
511    not. If DM took a more central role at some later date, this could become the primary method of setting the residual.
512 
513 .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian()
514 @*/
515 PetscErrorCode DMTSSetRHSFunction(DM dm,TSRHSFunction func,void *ctx)
516 {
517   PetscErrorCode ierr;
518   DMTS           tsdm;
519 
520   PetscFunctionBegin;
521   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
522   ierr = DMGetDMTSWrite(dm,&tsdm);CHKERRQ(ierr);
523   if (func) tsdm->ops->rhsfunction = func;
524   if (ctx)  tsdm->rhsfunctionctx = ctx;
525   PetscFunctionReturn(0);
526 }
527 
528 /*@C
529    DMTSGetSolutionFunction - gets the TS solution evaluation function
530 
531    Not Collective
532 
533    Input Arguments:
534 .  dm - DM to be used with TS
535 
536    Output Parameters:
537 +  func - solution function evaluation function, see TSSetSolution() for calling sequence
538 -  ctx - context for solution evaluation
539 
540    Level: advanced
541 
542 .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian(), DMTSSetSolutionFunction()
543 @*/
544 PetscErrorCode DMTSGetSolutionFunction(DM dm,TSSolutionFunction *func,void **ctx)
545 {
546   PetscErrorCode ierr;
547   DMTS           tsdm;
548 
549   PetscFunctionBegin;
550   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
551   ierr = DMGetDMTS(dm,&tsdm);CHKERRQ(ierr);
552   if (func) *func = tsdm->ops->solution;
553   if (ctx)  *ctx  = tsdm->solutionctx;
554   PetscFunctionReturn(0);
555 }
556 
557 /*@C
558    DMTSSetSolutionFunction - set TS solution evaluation function
559 
560    Not Collective
561 
562    Input Arguments:
563 +  dm - DM to be used with TS
564 .  func - solution function evaluation function, see TSSetSolution() for calling sequence
565 -  ctx - context for solution evaluation
566 
567    Level: advanced
568 
569    Note:
570    TSSetSolutionFunction() is normally used, but it calls this function internally because the user context is actually
571    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
572    not. If DM took a more central role at some later date, this could become the primary method of setting the residual.
573 
574 .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian(), DMTSGetSolutionFunction()
575 @*/
576 PetscErrorCode DMTSSetSolutionFunction(DM dm,TSSolutionFunction func,void *ctx)
577 {
578   PetscErrorCode ierr;
579   DMTS           tsdm;
580 
581   PetscFunctionBegin;
582   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
583   ierr = DMGetDMTSWrite(dm,&tsdm);CHKERRQ(ierr);
584   if (func) tsdm->ops->solution = func;
585   if (ctx)  tsdm->solutionctx   = ctx;
586   PetscFunctionReturn(0);
587 }
588 
589 /*@C
590    DMTSSetForcingFunction - set TS forcing function evaluation function
591 
592    Not Collective
593 
594    Input Arguments:
595 +  dm - DM to be used with TS
596 .  f - forcing function evaluation function; see TSForcingFunction
597 -  ctx - context for solution evaluation
598 
599    Level: advanced
600 
601    Note:
602    TSSetForcingFunction() is normally used, but it calls this function internally because the user context is actually
603    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
604    not. If DM took a more central role at some later date, this could become the primary method of setting the residual.
605 
606 .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian(), TSSetForcingFunction(), DMTSGetForcingFunction()
607 @*/
608 PetscErrorCode DMTSSetForcingFunction(DM dm,TSForcingFunction f,void *ctx)
609 {
610   PetscErrorCode ierr;
611   DMTS           tsdm;
612 
613   PetscFunctionBegin;
614   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
615   ierr = DMGetDMTSWrite(dm,&tsdm);CHKERRQ(ierr);
616   if (f)    tsdm->ops->forcing = f;
617   if (ctx)  tsdm->forcingctx   = ctx;
618   PetscFunctionReturn(0);
619 }
620 
621 
622 /*@C
623    DMTSGetForcingFunction - get TS forcing function evaluation function
624 
625    Not Collective
626 
627    Input Argument:
628 .   dm - DM to be used with TS
629 
630    Output Arguments:
631 +  f - forcing function evaluation function; see TSForcingFunction for details
632 -  ctx - context for solution evaluation
633 
634    Level: advanced
635 
636    Note:
637    TSSetForcingFunction() is normally used, but it calls this function internally because the user context is actually
638    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
639    not. If DM took a more central role at some later date, this could become the primary method of setting the residual.
640 
641 .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian(), TSSetForcingFunction(), DMTSGetForcingFunction()
642 @*/
643 PetscErrorCode DMTSGetForcingFunction(DM dm,TSForcingFunction *f,void **ctx)
644 {
645   PetscErrorCode ierr;
646   DMTS           tsdm;
647 
648   PetscFunctionBegin;
649   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
650   ierr = DMGetDMTSWrite(dm,&tsdm);CHKERRQ(ierr);
651   if (f)   *f   = tsdm->ops->forcing;
652   if (ctx) *ctx = tsdm->forcingctx;
653   PetscFunctionReturn(0);
654 }
655 
656 /*@C
657    DMTSGetRHSFunction - get TS explicit residual evaluation function
658 
659    Not Collective
660 
661    Input Argument:
662 .  dm - DM to be used with TS
663 
664    Output Arguments:
665 +  func - residual evaluation function, see TSSetRHSFunction() for calling sequence
666 -  ctx - context for residual evaluation
667 
668    Level: advanced
669 
670    Note:
671    TSGetFunction() is normally used, but it calls this function internally because the user context is actually
672    associated with the DM.
673 
674 .seealso: DMTSSetContext(), DMTSSetFunction(), TSSetFunction()
675 @*/
676 PetscErrorCode DMTSGetRHSFunction(DM dm,TSRHSFunction *func,void **ctx)
677 {
678   PetscErrorCode ierr;
679   DMTS           tsdm;
680 
681   PetscFunctionBegin;
682   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
683   ierr = DMGetDMTS(dm,&tsdm);CHKERRQ(ierr);
684   if (func) *func = tsdm->ops->rhsfunction;
685   if (ctx)  *ctx = tsdm->rhsfunctionctx;
686   PetscFunctionReturn(0);
687 }
688 
689 /*@C
690    DMTSSetIJacobian - set TS Jacobian evaluation function
691 
692    Not Collective
693 
694    Input Argument:
695 +  dm - DM to be used with TS
696 .  func - Jacobian evaluation function, see TSSetIJacobian() for calling sequence
697 -  ctx - context for residual evaluation
698 
699    Level: advanced
700 
701    Note:
702    TSSetJacobian() is normally used, but it calls this function internally because the user context is actually
703    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
704    not. If DM took a more central role at some later date, this could become the primary method of setting the Jacobian.
705 
706 .seealso: DMTSSetContext(), TSSetFunction(), DMTSGetJacobian(), TSSetJacobian()
707 @*/
708 PetscErrorCode DMTSSetIJacobian(DM dm,TSIJacobian func,void *ctx)
709 {
710   PetscErrorCode ierr;
711   DMTS           sdm;
712 
713   PetscFunctionBegin;
714   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
715   ierr = DMGetDMTSWrite(dm,&sdm);CHKERRQ(ierr);
716   if (func) sdm->ops->ijacobian = func;
717   if (ctx)  sdm->ijacobianctx   = ctx;
718   PetscFunctionReturn(0);
719 }
720 
721 /*@C
722    DMTSGetIJacobian - get TS Jacobian evaluation function
723 
724    Not Collective
725 
726    Input Argument:
727 .  dm - DM to be used with TS
728 
729    Output Arguments:
730 +  func - Jacobian evaluation function, see TSSetIJacobian() for calling sequence
731 -  ctx - context for residual evaluation
732 
733    Level: advanced
734 
735    Note:
736    TSGetJacobian() is normally used, but it calls this function internally because the user context is actually
737    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
738    not. If DM took a more central role at some later date, this could become the primary method of setting the Jacobian.
739 
740 .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian()
741 @*/
742 PetscErrorCode DMTSGetIJacobian(DM dm,TSIJacobian *func,void **ctx)
743 {
744   PetscErrorCode ierr;
745   DMTS           tsdm;
746 
747   PetscFunctionBegin;
748   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
749   ierr = DMGetDMTS(dm,&tsdm);CHKERRQ(ierr);
750   if (func) *func = tsdm->ops->ijacobian;
751   if (ctx)  *ctx = tsdm->ijacobianctx;
752   PetscFunctionReturn(0);
753 }
754 
755 
756 /*@C
757    DMTSSetRHSJacobian - set TS Jacobian evaluation function
758 
759    Not Collective
760 
761    Input Argument:
762 +  dm - DM to be used with TS
763 .  func - Jacobian evaluation function, see TSSetRHSJacobian() for calling sequence
764 -  ctx - context for residual evaluation
765 
766    Level: advanced
767 
768    Note:
769    TSSetJacobian() is normally used, but it calls this function internally because the user context is actually
770    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
771    not. If DM took a more central role at some later date, this could become the primary method of setting the Jacobian.
772 
773 .seealso: DMTSSetContext(), TSSetFunction(), DMTSGetJacobian(), TSSetJacobian()
774 @*/
775 PetscErrorCode DMTSSetRHSJacobian(DM dm,TSRHSJacobian func,void *ctx)
776 {
777   PetscErrorCode ierr;
778   DMTS           tsdm;
779 
780   PetscFunctionBegin;
781   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
782   ierr = DMGetDMTSWrite(dm,&tsdm);CHKERRQ(ierr);
783   if (func) tsdm->ops->rhsjacobian = func;
784   if (ctx)  tsdm->rhsjacobianctx = ctx;
785   PetscFunctionReturn(0);
786 }
787 
788 /*@C
789    DMTSGetRHSJacobian - get TS Jacobian evaluation function
790 
791    Not Collective
792 
793    Input Argument:
794 .  dm - DM to be used with TS
795 
796    Output Arguments:
797 +  func - Jacobian evaluation function, see TSSetRHSJacobian() for calling sequence
798 -  ctx - context for residual evaluation
799 
800    Level: advanced
801 
802    Note:
803    TSGetJacobian() is normally used, but it calls this function internally because the user context is actually
804    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
805    not. If DM took a more central role at some later date, this could become the primary method of setting the Jacobian.
806 
807 .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian()
808 @*/
809 PetscErrorCode DMTSGetRHSJacobian(DM dm,TSRHSJacobian *func,void **ctx)
810 {
811   PetscErrorCode ierr;
812   DMTS           tsdm;
813 
814   PetscFunctionBegin;
815   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
816   ierr = DMGetDMTS(dm,&tsdm);CHKERRQ(ierr);
817   if (func) *func = tsdm->ops->rhsjacobian;
818   if (ctx)  *ctx = tsdm->rhsjacobianctx;
819   PetscFunctionReturn(0);
820 }
821 
822 /*@C
823    DMTSSetIFunctionSerialize - sets functions used to view and load a IFunction context
824 
825    Not Collective
826 
827    Input Arguments:
828 +  dm - DM to be used with TS
829 .  view - viewer function
830 -  load - loading function
831 
832    Level: advanced
833 
834 .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian()
835 @*/
836 PetscErrorCode DMTSSetIFunctionSerialize(DM dm,PetscErrorCode (*view)(void*,PetscViewer),PetscErrorCode (*load)(void**,PetscViewer))
837 {
838   PetscErrorCode ierr;
839   DMTS           tsdm;
840 
841   PetscFunctionBegin;
842   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
843   ierr = DMGetDMTSWrite(dm,&tsdm);CHKERRQ(ierr);
844   tsdm->ops->ifunctionview = view;
845   tsdm->ops->ifunctionload = load;
846   PetscFunctionReturn(0);
847 }
848 
849 /*@C
850    DMTSSetIJacobianSerialize - sets functions used to view and load a IJacobian context
851 
852    Not Collective
853 
854    Input Arguments:
855 +  dm - DM to be used with TS
856 .  view - viewer function
857 -  load - loading function
858 
859    Level: advanced
860 
861 .seealso: DMTSSetContext(), TSSetFunction(), DMTSSetJacobian()
862 @*/
863 PetscErrorCode DMTSSetIJacobianSerialize(DM dm,PetscErrorCode (*view)(void*,PetscViewer),PetscErrorCode (*load)(void**,PetscViewer))
864 {
865   PetscErrorCode ierr;
866   DMTS           tsdm;
867 
868   PetscFunctionBegin;
869   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
870   ierr = DMGetDMTSWrite(dm,&tsdm);CHKERRQ(ierr);
871   tsdm->ops->ijacobianview = view;
872   tsdm->ops->ijacobianload = load;
873   PetscFunctionReturn(0);
874 }
875