xref: /petsc/src/snes/utils/dmsnes.c (revision 3e08d2bebf9958b2a7617e5d4703c5f9c1d28ec4)
1 #include <petsc-private/snesimpl.h>   /*I "petscsnes.h" I*/
2 #include <petsc-private/dmimpl.h>     /*I "petscdm.h" I*/
3 
4 #undef __FUNCT__
5 #define __FUNCT__ "SNESDMComputeFunction"
6 /*@C
7   SNESDMComputeFunction - This is a universal function evaluation routine that
8   may be used with SNESSetFunction() as long as the user context has a DM
9   as its first record and the user has called DMSetLocalFunction().
10 
11   Collective on SNES
12 
13   Input Parameters:
14 + snes - the SNES context
15 . X - input vector
16 . F - function vector
17 - ptr - pointer to a structure that must have a DM as its first entry.
18         This ptr must have been passed into SNESDMComputeFunction() as the context.
19 
20   Level: intermediate
21 
22 .seealso: DMSetLocalFunction(), DMSetLocalJacobian(), SNESSetFunction(), SNESSetJacobian()
23 @*/
24 PetscErrorCode SNESDMComputeFunction(SNES snes, Vec X, Vec F, void *ptr)
25 {
26   DM               dm = *(DM*) ptr;
27   PetscErrorCode (*lf)(DM, Vec, Vec, void *);
28   Vec              localX, localF;
29   PetscInt         N, n;
30   PetscErrorCode   ierr;
31 
32   PetscFunctionBegin;
33   PetscValidHeaderSpecific(snes, SNES_CLASSID, 1);
34   PetscValidHeaderSpecific(X, VEC_CLASSID, 2);
35   PetscValidHeaderSpecific(F, VEC_CLASSID, 3);
36   if (!dm) SETERRQ(((PetscObject)snes)->comm, PETSC_ERR_ARG_WRONGSTATE, "Looks like you called SNESSetFromFuntion(snes,SNESDMComputeFunction,) without the DM context");
37   PetscValidHeaderSpecific(dm, DM_CLASSID, 4);
38 
39   /* determine whether X = localX */
40   ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr);
41   ierr = DMGetLocalVector(dm, &localF);CHKERRQ(ierr);
42   ierr = VecGetSize(X, &N);CHKERRQ(ierr);
43   ierr = VecGetSize(localX, &n);CHKERRQ(ierr);
44 
45   if (n != N){ /* X != localX */
46     /* Scatter ghost points to local vector, using the 2-step process
47         DMGlobalToLocalBegin(), DMGlobalToLocalEnd().
48     */
49     ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr);
50     ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr);
51   } else {
52     ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr);
53     localX = X;
54   }
55   ierr = DMGetLocalFunction(dm, &lf);CHKERRQ(ierr);
56   ierr = (*lf)(dm, localX, localF, ptr);CHKERRQ(ierr);
57   if (n != N){
58     ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr);
59   }
60   ierr = DMLocalToGlobalBegin(dm, localF, ADD_VALUES, F);CHKERRQ(ierr);
61   ierr = DMLocalToGlobalEnd(dm, localF, ADD_VALUES, F);CHKERRQ(ierr);
62   ierr = DMRestoreLocalVector(dm, &localF);CHKERRQ(ierr);
63   PetscFunctionReturn(0);
64 }
65 
66 #undef __FUNCT__
67 #define __FUNCT__ "SNESDMComputeJacobian"
68 /*
69   SNESDMComputeJacobian - This is a universal Jacobian evaluation routine that
70   may be used with SNESSetJacobian() as long as the user context has a DM
71   as its first record and the user has called DMSetLocalJacobian().
72 
73   Collective on SNES
74 
75   Input Parameters:
76 + snes - the SNES context
77 . X - input vector
78 . J - Jacobian
79 . B - Jacobian used in preconditioner (usally same as J)
80 . flag - indicates if the matrix changed its structure
81 - ptr - pointer to a structure that must have a DM as its first entry.
82         This ptr must have been passed into SNESDMComputeFunction() as the context.
83 
84   Level: intermediate
85 
86 .seealso: DMSetLocalFunction(), DMSetLocalJacobian(), SNESSetFunction(), SNESSetJacobian()
87 */
88 PetscErrorCode SNESDMComputeJacobian(SNES snes, Vec X, Mat *J, Mat *B, MatStructure *flag, void *ptr)
89 {
90   DM               dm = *(DM*) ptr;
91   PetscErrorCode (*lj)(DM, Vec, Mat, Mat, void *);
92   Vec              localX;
93   PetscErrorCode   ierr;
94 
95   PetscFunctionBegin;
96   ierr = DMGetLocalVector(dm, &localX);CHKERRQ(ierr);
97   ierr = DMGlobalToLocalBegin(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr);
98   ierr = DMGlobalToLocalEnd(dm, X, INSERT_VALUES, localX);CHKERRQ(ierr);
99   ierr = DMGetLocalJacobian(dm, &lj);CHKERRQ(ierr);
100   ierr = (*lj)(dm, localX, *J, *B, ptr);CHKERRQ(ierr);
101   ierr = DMRestoreLocalVector(dm, &localX);CHKERRQ(ierr);
102   /* Assemble true Jacobian; if it is different */
103   if (*J != *B) {
104     ierr  = MatAssemblyBegin(*J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
105     ierr  = MatAssemblyEnd(*J, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
106   }
107   ierr  = MatSetOption(*B, MAT_NEW_NONZERO_LOCATION_ERR, PETSC_TRUE);CHKERRQ(ierr);
108   *flag = SAME_NONZERO_PATTERN;
109   PetscFunctionReturn(0);
110 }
111 
112 #undef __FUNCT__
113 #define __FUNCT__ "PetscContainerDestroy_SNESDM"
114 static PetscErrorCode PetscContainerDestroy_SNESDM(void *ctx)
115 {
116   PetscErrorCode ierr;
117   SNESDM sdm = (SNESDM)ctx;
118 
119   PetscFunctionBegin;
120   if (sdm->destroy) {ierr = (*sdm->destroy)(sdm);CHKERRQ(ierr);}
121   ierr = PetscFree(sdm);CHKERRQ(ierr);
122   PetscFunctionReturn(0);
123 }
124 
125 #undef __FUNCT__
126 #define __FUNCT__ "DMCoarsenHook_SNESDM"
127 /* Attaches the SNESDM to the coarse level.
128  * Under what conditions should we copy versus duplicate?
129  */
130 static PetscErrorCode DMCoarsenHook_SNESDM(DM dm,DM dmc,void *ctx)
131 {
132   PetscErrorCode ierr;
133 
134   PetscFunctionBegin;
135   ierr = DMSNESCopyContext(dm,dmc);CHKERRQ(ierr);
136   PetscFunctionReturn(0);
137 }
138 
139 #undef __FUNCT__
140 #define __FUNCT__ "DMRestrictHook_SNESDM"
141 /* This could restrict auxiliary information to the coarse level.
142  */
143 static PetscErrorCode DMRestrictHook_SNESDM(DM dm,Mat Restrict,Vec rscale,Mat Inject,DM dmc,void *ctx)
144 {
145 
146   PetscFunctionBegin;
147   PetscFunctionReturn(0);
148 }
149 
150 #undef __FUNCT__
151 #define __FUNCT__ "DMSNESGetContext"
152 /*@C
153    DMSNESGetContext - get read-only private SNESDM context from a DM
154 
155    Not Collective
156 
157    Input Argument:
158 .  dm - DM to be used with SNES
159 
160    Output Argument:
161 .  snesdm - private SNESDM context
162 
163    Level: developer
164 
165    Notes:
166    Use DMSNESGetContextWrite() if write access is needed. The DMSNESSetXXX API should be used wherever possible.
167 
168 .seealso: DMSNESGetContextWrite()
169 @*/
170 PetscErrorCode DMSNESGetContext(DM dm,SNESDM *snesdm)
171 {
172   PetscErrorCode ierr;
173   PetscContainer container;
174   SNESDM         sdm;
175 
176   PetscFunctionBegin;
177   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
178   ierr = PetscObjectQuery((PetscObject)dm,"SNESDM",(PetscObject*)&container);CHKERRQ(ierr);
179   if (container) {
180     ierr = PetscContainerGetPointer(container,(void**)snesdm);CHKERRQ(ierr);
181   } else {
182     ierr = PetscInfo(dm,"Creating new SNESDM\n");CHKERRQ(ierr);
183     ierr = PetscContainerCreate(((PetscObject)dm)->comm,&container);CHKERRQ(ierr);
184     ierr = PetscNewLog(dm,struct _n_SNESDM,&sdm);CHKERRQ(ierr);
185     ierr = PetscContainerSetPointer(container,sdm);CHKERRQ(ierr);
186     ierr = PetscContainerSetUserDestroy(container,PetscContainerDestroy_SNESDM);CHKERRQ(ierr);
187     ierr = PetscObjectCompose((PetscObject)dm,"SNESDM",(PetscObject)container);CHKERRQ(ierr);
188     ierr = DMCoarsenHookAdd(dm,DMCoarsenHook_SNESDM,DMRestrictHook_SNESDM,PETSC_NULL);CHKERRQ(ierr);
189     ierr = PetscContainerGetPointer(container,(void**)snesdm);CHKERRQ(ierr);
190     ierr = PetscContainerDestroy(&container);CHKERRQ(ierr);
191   }
192   PetscFunctionReturn(0);
193 }
194 
195 #undef __FUNCT__
196 #define __FUNCT__ "DMSNESGetContextWrite"
197 /*@C
198    DMSNESGetContextWrite - get write access to private SNESDM context from a DM
199 
200    Not Collective
201 
202    Input Argument:
203 .  dm - DM to be used with SNES
204 
205    Output Argument:
206 .  snesdm - private SNESDM context
207 
208    Level: developer
209 
210 .seealso: DMSNESGetContext()
211 @*/
212 PetscErrorCode DMSNESGetContextWrite(DM dm,SNESDM *snesdm)
213 {
214   PetscErrorCode ierr;
215   SNESDM         sdm;
216 
217   PetscFunctionBegin;
218   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
219   ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr);
220   if (!sdm->originaldm) sdm->originaldm = dm;
221   if (sdm->originaldm != dm) {  /* Copy on write */
222     PetscContainer container;
223     SNESDM         oldsdm = sdm;
224     ierr = PetscInfo(dm,"Copying SNESDM due to write\n");CHKERRQ(ierr);
225     ierr = PetscContainerCreate(((PetscObject)dm)->comm,&container);CHKERRQ(ierr);
226     ierr = PetscNewLog(dm,struct _n_SNESDM,&sdm);CHKERRQ(ierr);
227     ierr = PetscMemcpy(sdm,oldsdm,sizeof(*sdm));CHKERRQ(ierr);
228     ierr = PetscContainerSetPointer(container,sdm);CHKERRQ(ierr);
229     ierr = PetscContainerSetUserDestroy(container,PetscContainerDestroy_SNESDM);CHKERRQ(ierr);
230     ierr = PetscObjectCompose((PetscObject)dm,"SNESDM",(PetscObject)container);CHKERRQ(ierr);
231     ierr = PetscContainerDestroy(&container);CHKERRQ(ierr);
232   }
233   *snesdm = sdm;
234   PetscFunctionReturn(0);
235 }
236 
237 #undef __FUNCT__
238 #define __FUNCT__ "DMSNESCopyContext"
239 /*@C
240    DMSNESCopyContext - copies a DM context to a new DM
241 
242    Logically Collective
243 
244    Input Arguments:
245 +  dmsrc - DM to obtain context from
246 -  dmdest - DM to add context to
247 
248    Level: developer
249 
250    Note:
251    The context is copied by reference. This function does not ensure that a context exists.
252 
253 .seealso: DMSNESGetContext(), SNESSetDM()
254 @*/
255 PetscErrorCode DMSNESCopyContext(DM dmsrc,DM dmdest)
256 {
257   PetscErrorCode ierr;
258   PetscContainer container;
259 
260   PetscFunctionBegin;
261   PetscValidHeaderSpecific(dmsrc,DM_CLASSID,1);
262   PetscValidHeaderSpecific(dmdest,DM_CLASSID,2);
263   ierr = PetscObjectQuery((PetscObject)dmsrc,"SNESDM",(PetscObject*)&container);CHKERRQ(ierr);
264   if (container) {
265     ierr = PetscObjectCompose((PetscObject)dmdest,"SNESDM",(PetscObject)container);CHKERRQ(ierr);
266     ierr = DMCoarsenHookAdd(dmdest,DMCoarsenHook_SNESDM,DMRestrictHook_SNESDM,PETSC_NULL);CHKERRQ(ierr);
267   }
268   PetscFunctionReturn(0);
269 }
270 
271 #undef __FUNCT__
272 #define __FUNCT__ "DMSNESSetFunction"
273 /*@C
274    DMSNESSetFunction - set SNES residual evaluation function
275 
276    Not Collective
277 
278    Input Arguments:
279 +  dm - DM to be used with SNES
280 .  func - residual evaluation function, see SNESSetFunction() for calling sequence
281 -  ctx - context for residual evaluation
282 
283    Level: advanced
284 
285    Note:
286    SNESSetFunction() is normally used, but it calls this function internally because the user context is actually
287    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
288    not. If DM took a more central role at some later date, this could become the primary method of setting the residual.
289 
290 .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian()
291 @*/
292 PetscErrorCode DMSNESSetFunction(DM dm,PetscErrorCode (*func)(SNES,Vec,Vec,void*),void *ctx)
293 {
294   PetscErrorCode ierr;
295   SNESDM sdm;
296 
297   PetscFunctionBegin;
298   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
299   ierr = DMSNESGetContextWrite(dm,&sdm);CHKERRQ(ierr);
300   if (func) sdm->computefunction = func;
301   if (ctx)  sdm->functionctx = ctx;
302   PetscFunctionReturn(0);
303 }
304 
305 #undef __FUNCT__
306 #define __FUNCT__ "DMSNESGetFunction"
307 /*@C
308    DMSNESGetFunction - get SNES residual evaluation function
309 
310    Not Collective
311 
312    Input Argument:
313 .  dm - DM to be used with SNES
314 
315    Output Arguments:
316 +  func - residual evaluation function, see SNESSetFunction() for calling sequence
317 -  ctx - context for residual evaluation
318 
319    Level: advanced
320 
321    Note:
322    SNESGetFunction() is normally used, but it calls this function internally because the user context is actually
323    associated with the DM.
324 
325 .seealso: DMSNESSetContext(), DMSNESSetFunction(), SNESSetFunction()
326 @*/
327 PetscErrorCode DMSNESGetFunction(DM dm,PetscErrorCode (**func)(SNES,Vec,Vec,void*),void **ctx)
328 {
329   PetscErrorCode ierr;
330   SNESDM sdm;
331 
332   PetscFunctionBegin;
333   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
334   ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr);
335   if (func) *func = sdm->computefunction;
336   if (ctx)  *ctx = sdm->functionctx;
337   PetscFunctionReturn(0);
338 }
339 
340 #undef __FUNCT__
341 #define __FUNCT__ "DMSNESSetGS"
342 /*@C
343    DMSNESSetGS - set SNES Gauss-Seidel relaxation function
344 
345    Not Collective
346 
347    Input Argument:
348 +  dm - DM to be used with SNES
349 .  func - relaxation function, see SNESSetGS() for calling sequence
350 -  ctx - context for residual evaluation
351 
352    Level: advanced
353 
354    Note:
355    SNESSetGS() is normally used, but it calls this function internally because the user context is actually
356    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
357    not. If DM took a more central role at some later date, this could become the primary method of setting the residual.
358 
359 .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian(), DMSNESSetFunction()
360 @*/
361 PetscErrorCode DMSNESSetGS(DM dm,PetscErrorCode (*func)(SNES,Vec,Vec,void*),void *ctx)
362 {
363   PetscErrorCode ierr;
364   SNESDM sdm;
365 
366   PetscFunctionBegin;
367   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
368   ierr = DMSNESGetContextWrite(dm,&sdm);CHKERRQ(ierr);
369   if (func) sdm->computegs = func;
370   if (ctx)  sdm->gsctx = ctx;
371   PetscFunctionReturn(0);
372 }
373 
374 #undef __FUNCT__
375 #define __FUNCT__ "DMSNESGetGS"
376 /*@C
377    DMSNESGetGS - get SNES Gauss-Seidel relaxation function
378 
379    Not Collective
380 
381    Input Argument:
382 .  dm - DM to be used with SNES
383 
384    Output Arguments:
385 +  func - relaxation function, see SNESSetGS() for calling sequence
386 -  ctx - context for residual evaluation
387 
388    Level: advanced
389 
390    Note:
391    SNESGetGS() is normally used, but it calls this function internally because the user context is actually
392    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
393    not. If DM took a more central role at some later date, this could become the primary method of setting the residual.
394 
395 .seealso: DMSNESSetContext(), SNESGetGS(), DMSNESGetJacobian(), DMSNESGetFunction()
396 @*/
397 PetscErrorCode DMSNESGetGS(DM dm,PetscErrorCode (**func)(SNES,Vec,Vec,void*),void **ctx)
398 {
399   PetscErrorCode ierr;
400   SNESDM sdm;
401 
402   PetscFunctionBegin;
403   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
404   ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr);
405   if (func) *func = sdm->computegs;
406   if (ctx)  *ctx = sdm->gsctx;
407   PetscFunctionReturn(0);
408 }
409 
410 #undef __FUNCT__
411 #define __FUNCT__ "DMSNESSetJacobian"
412 /*@C
413    DMSNESSetJacobian - set SNES Jacobian evaluation function
414 
415    Not Collective
416 
417    Input Argument:
418 +  dm - DM to be used with SNES
419 .  func - Jacobian evaluation function, see SNESSetJacobian() for calling sequence
420 -  ctx - context for residual evaluation
421 
422    Level: advanced
423 
424    Note:
425    SNESSetJacobian() is normally used, but it calls this function internally because the user context is actually
426    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
427    not. If DM took a more central role at some later date, this could become the primary method of setting the Jacobian.
428 
429 .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESGetJacobian(), SNESSetJacobian()
430 @*/
431 PetscErrorCode DMSNESSetJacobian(DM dm,PetscErrorCode (*func)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void *ctx)
432 {
433   PetscErrorCode ierr;
434   SNESDM sdm;
435 
436   PetscFunctionBegin;
437   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
438   ierr = DMSNESGetContextWrite(dm,&sdm);CHKERRQ(ierr);
439   if (func) sdm->computejacobian = func;
440   if (ctx)  sdm->jacobianctx = ctx;
441   PetscFunctionReturn(0);
442 }
443 
444 #undef __FUNCT__
445 #define __FUNCT__ "DMSNESGetJacobian"
446 /*@C
447    DMSNESGetJacobian - get SNES Jacobian evaluation function
448 
449    Not Collective
450 
451    Input Argument:
452 .  dm - DM to be used with SNES
453 
454    Output Arguments:
455 +  func - Jacobian evaluation function, see SNESSetJacobian() for calling sequence
456 -  ctx - context for residual evaluation
457 
458    Level: advanced
459 
460    Note:
461    SNESGetJacobian() is normally used, but it calls this function internally because the user context is actually
462    associated with the DM.  This makes the interface consistent regardless of whether the user interacts with a DM or
463    not. If DM took a more central role at some later date, this could become the primary method of setting the Jacobian.
464 
465 .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian()
466 @*/
467 PetscErrorCode DMSNESGetJacobian(DM dm,PetscErrorCode (**func)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void **ctx)
468 {
469   PetscErrorCode ierr;
470   SNESDM sdm;
471 
472   PetscFunctionBegin;
473   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
474   ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr);
475   if (func) *func = sdm->computejacobian;
476   if (ctx)  *ctx = sdm->jacobianctx;
477   PetscFunctionReturn(0);
478 }
479 
480 #undef __FUNCT__
481 #define __FUNCT__ "DMSNESSetPicard"
482 /*@C
483    DMSNESSetPicard - set SNES Picard iteration matrix and RHS evaluation functions.
484 
485    Not Collective
486 
487    Input Argument:
488 +  dm - DM to be used with SNES
489 .  func - RHS evaluation function, see SNESSetFunction() for calling sequence
490 .  pjac - Picard matrix evaluation function, see SNESSetJacobian() for calling sequence
491 -  ctx - context for residual evaluation
492 
493    Level: advanced
494 
495 .seealso: SNESSetPicard(), DMSNESSetFunction(), DMSNESSetJacobian()
496 @*/
497 PetscErrorCode DMSNESSetPicard(DM dm,PetscErrorCode (*pfunc)(SNES,Vec,Vec,void*),PetscErrorCode (*pjac)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void *ctx)
498 {
499   PetscErrorCode ierr;
500   SNESDM sdm;
501 
502   PetscFunctionBegin;
503   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
504   ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr);
505   if (pfunc) sdm->computepfunction = pfunc;
506   if (pjac)  sdm->computepjacobian = pjac;
507   if (ctx)   sdm->pctx             = ctx;
508   PetscFunctionReturn(0);
509 }
510 
511 
512 #undef __FUNCT__
513 #define __FUNCT__ "DMSNESGetPicard"
514 /*@C
515    DMSNESGetPicard - get SNES Picard iteration evaluation functions
516 
517    Not Collective
518 
519    Input Argument:
520 .  dm - DM to be used with SNES
521 
522    Output Arguments:
523 +  pfunc - Jacobian evaluation function, see SNESSetJacobian() for calling sequence
524 .  pjac  - RHS evaluation function, see SNESSetFunction() for calling sequence
525 -  ctx - context for residual evaluation
526 
527    Level: advanced
528 
529 .seealso: DMSNESSetContext(), SNESSetFunction(), DMSNESSetJacobian()
530 @*/
531 PetscErrorCode DMSNESGetPicard(DM dm,PetscErrorCode (**pfunc)(SNES,Vec,Vec,void*),PetscErrorCode (**pjac)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void **ctx)
532 {
533   PetscErrorCode ierr;
534   SNESDM sdm;
535 
536   PetscFunctionBegin;
537   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
538   ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr);
539   if (pfunc) *pfunc = sdm->computepfunction;
540   if (pjac) *pjac   = sdm->computepjacobian;
541   if (ctx)  *ctx    = sdm->pctx;
542   PetscFunctionReturn(0);
543 }
544 
545 
546 #undef __FUNCT__
547 #define __FUNCT__ "SNESDefaultComputeFunction_DMLegacy"
548 static PetscErrorCode SNESDefaultComputeFunction_DMLegacy(SNES snes,Vec X,Vec F,void *ctx)
549 {
550   PetscErrorCode ierr;
551   DM             dm;
552 
553   PetscFunctionBegin;
554   ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr);
555   ierr = DMComputeFunction(dm,X,F);CHKERRQ(ierr);
556   PetscFunctionReturn(0);
557 }
558 
559 #undef __FUNCT__
560 #define __FUNCT__ "SNESDefaultComputeJacobian_DMLegacy"
561 static PetscErrorCode SNESDefaultComputeJacobian_DMLegacy(SNES snes,Vec X,Mat *A,Mat *B,MatStructure *mstr,void *ctx)
562 {
563   PetscErrorCode ierr;
564   DM             dm;
565 
566   PetscFunctionBegin;
567   ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr);
568   ierr = DMComputeJacobian(dm,X,*A,*B,mstr);CHKERRQ(ierr);
569   PetscFunctionReturn(0);
570 }
571 
572 #undef __FUNCT__
573 #define __FUNCT__ "DMSNESSetUpLegacy"
574 /* Sets up calling of legacy DM routines */
575 PetscErrorCode DMSNESSetUpLegacy(DM dm)
576 {
577   PetscErrorCode ierr;
578   SNESDM         sdm;
579 
580   PetscFunctionBegin;
581   ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr);
582   if (!sdm->computefunction) {ierr = DMSNESSetFunction(dm,SNESDefaultComputeFunction_DMLegacy,PETSC_NULL);CHKERRQ(ierr);}
583   ierr = DMSNESGetContext(dm,&sdm);CHKERRQ(ierr);
584   if (!sdm->computejacobian) {
585     if (dm->ops->functionj) {
586       ierr = DMSNESSetJacobian(dm,SNESDefaultComputeJacobian_DMLegacy,PETSC_NULL);CHKERRQ(ierr);
587     } else {
588       ierr = DMSNESSetJacobian(dm,SNESDefaultComputeJacobianColor,PETSC_NULL);CHKERRQ(ierr);
589     }
590   }
591   PetscFunctionReturn(0);
592 }
593