xref: /petsc/src/snes/interface/ftn-custom/zsnesf.c (revision 6a4a1270853b5b1995c94de98f44d28bec57470a)
1 #include <petsc/private/fortranimpl.h>
2 #include <petscsnes.h>
3 #include <petscviewer.h>
4 #include <petsc/private/f90impl.h>
5 
6 #if defined(PETSC_HAVE_FORTRAN_CAPS)
7 #define snesconvergedreasonview_         SNESCONVERGEDREASONVIEW
8 #define snessetpicard_                   SNESSETPICARD
9 #define matmffdcomputejacobian_          MATMFFDCOMPUTEJACOBIAN
10 #define snessolve_                       SNESSOLVE
11 #define snescomputejacobiandefault_      SNESCOMPUTEJACOBIANDEFAULT
12 #define snescomputejacobiandefaultcolor_ SNESCOMPUTEJACOBIANDEFAULTCOLOR
13 #define snessetjacobian_                 SNESSETJACOBIAN
14 #define snessetjacobian1_                SNESSETJACOBIAN1
15 #define snessetjacobian2_                SNESSETJACOBIAN2
16 #define snesgetoptionsprefix_            SNESGETOPTIONSPREFIX
17 #define snesgettype_                     SNESGETTYPE
18 #define snessetfunction_                 SNESSETFUNCTION
19 #define snessetngs_                      SNESSETNGS
20 #define snessetupdate_                   SNESSETUPDATE
21 #define snesgetfunction_                 SNESGETFUNCTION
22 #define snesgetngs_                      SNESGETNGS
23 #define snessetconvergencetest_          SNESSETCONVERGENCETEST
24 #define snesconvergeddefault_            SNESCONVERGEDDEFAULT
25 #define snesconvergedskip_               SNESCONVERGEDSKIP
26 #define snesview_                        SNESVIEW
27 #define snesgetconvergencehistory_       SNESGETCONVERGENCEHISTORY
28 #define snesgetjacobian_                 SNESGETJACOBIAN
29 #define snessettype_                     SNESSETTYPE
30 #define snesappendoptionsprefix_         SNESAPPENDOPTIONSPREFIX
31 #define snessetoptionsprefix_            SNESSETOPTIONSPREFIX
32 #define snesmonitordefault_              SNESMONITORDEFAULT
33 #define snesmonitorsolution_             SNESMONITORSOLUTION
34 #define snesmonitorsolutionupdate_       SNESMONITORSOLUTIONUPDATE
35 #define snesmonitorset_                  SNESMONITORSET
36 #define snesnewtontrsetprecheck_         SNESNEWTONTRSETPRECHECK
37 #define snesnewtontrsetpostcheck_        SNESNEWTONTRSETPOSTCHECK
38 #define snesnewtontrdcsetprecheck_       SNESNEWTONTRDCSETPRECHECK
39 #define snesnewtontrdcsetpostcheck_      SNESNEWTONTRDCSETPOSTCHECK
40 #define snesviewfromoptions_             SNESVIEWFROMOPTIONS
41 #define snesgetconvergedreasonstring_    SNESGETCONVERGEDREASONSTRING
42 #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
43 #define snesconvergedreasonview_         snesconvergedreasonview
44 #define snessetpicard_                   snessetpicard
45 #define matmffdcomputejacobian_          matmffdcomputejacobian
46 #define snessolve_                       snessolve
47 #define snescomputejacobiandefault_      snescomputejacobiandefault
48 #define snescomputejacobiandefaultcolor_ snescomputejacobiandefaultcolor
49 #define snessetjacobian_                 snessetjacobian
50 #define snessetjacobian1_                snessetjacobian1
51 #define snessetjacobian2_                snessetjacobian2
52 #define snesgetoptionsprefix_            snesgetoptionsprefix
53 #define snesgettype_                     snesgettype
54 #define snessetfunction_                 snessetfunction
55 #define snessetngs_                      snessetngs
56 #define snessetupdate_                   snessetupdate
57 #define snesgetfunction_                 snesgetfunction
58 #define snesgetngs_                      snesgetngs
59 #define snessetconvergencetest_          snessetconvergencetest
60 #define snesconvergeddefault_            snesconvergeddefault
61 #define snesconvergedskip_               snesconvergedskip
62 #define snesview_                        snesview
63 #define snesgetjacobian_                 snesgetjacobian
64 #define snesgetconvergencehistory_       snesgetconvergencehistory
65 #define snessettype_                     snessettype
66 #define snesappendoptionsprefix_         snesappendoptionsprefix
67 #define snessetoptionsprefix_            snessetoptionsprefix
68 #define snesmonitordefault_              snesmonitordefault
69 #define snesmonitorsolution_             snesmonitorsolution
70 #define snesmonitorsolutionupdate_       snesmonitorsolutionupdate
71 #define snesmonitorset_                  snesmonitorset
72 #define snesnewtontrsetprecheck_         snesnewtontrsetprecheck
73 #define snesnewtontrsetpostcheck_        snesnewtontrsetpostcheck
74 #define snesnewtontrdcsetprecheck_       snesnewtontrdcsetprecheck
75 #define snesnewtontrdcsetpostcheck_      snesnewtontrdcsetpostcheck
76 #define snesviewfromoptions_             snesviewfromoptions
77 #define snesgetconvergedreasonstring_    snesgetconvergedreasonstring
78 #endif
79 
80 static struct {
81   PetscFortranCallbackId function;
82   PetscFortranCallbackId test;
83   PetscFortranCallbackId destroy;
84   PetscFortranCallbackId jacobian;
85   PetscFortranCallbackId monitor;
86   PetscFortranCallbackId mondestroy;
87   PetscFortranCallbackId ngs;
88   PetscFortranCallbackId update;
89   PetscFortranCallbackId trprecheck;
90   PetscFortranCallbackId trpostcheck;
91 #if defined(PETSC_HAVE_F90_2PTR_ARG)
92   PetscFortranCallbackId function_pgiptr;
93   PetscFortranCallbackId trprecheck_pgiptr;
94   PetscFortranCallbackId trpostcheck_pgiptr;
95 #endif
96 } _cb;
97 
98 static PetscErrorCode ourtrprecheckfunction(SNES snes,Vec x,Vec y,PetscBool *changed_y,void *ctx)
99 {
100 #if defined(PETSC_HAVE_F90_2PTR_ARG)
101   void* ptr;
102   PetscObjectGetFortranCallback((PetscObject)snes,PETSC_FORTRAN_CALLBACK_CLASS,_cb.trprecheck_pgiptr,NULL,&ptr);
103 #endif
104   PetscObjectUseFortranCallback(snes,_cb.trprecheck,(SNES*,Vec*,Vec*,PetscBool *,void*,PetscErrorCode* PETSC_F90_2PTR_PROTO_NOVAR),(&snes,&x,&y,changed_y,_ctx,&ierr PETSC_F90_2PTR_PARAM(ptr)));
105 }
106 
107 PETSC_EXTERN void snesnewtontrsetprecheck_(SNES *snes, void (*func)(SNES,Vec,Vec,PetscBool*,void*),void *ctx,PetscErrorCode *ierr PETSC_F90_2PTR_PROTO(ptr))
108 {
109   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.trprecheck,(PetscVoidFunction)func,ctx);if (*ierr) return;
110 #if defined(PETSC_HAVE_F90_2PTR_ARG)
111   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.trprecheck_pgiptr,NULL,ptr);if (*ierr) return;
112 #endif
113   SNESNewtonTRSetPreCheck(*snes,ourtrprecheckfunction,NULL);
114 }
115 
116 PETSC_EXTERN void snesnewtontrdcsetprecheck_(SNES *snes, void (*func)(SNES,Vec,Vec,PetscBool*,void*),void *ctx,PetscErrorCode *ierr PETSC_F90_2PTR_PROTO(ptr))
117 {
118   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.trprecheck,(PetscVoidFunction)func,ctx);if (*ierr) return;
119 #if defined(PETSC_HAVE_F90_2PTR_ARG)
120   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.trprecheck_pgiptr,NULL,ptr);if (*ierr) return;
121 #endif
122   SNESNewtonTRDCSetPreCheck(*snes,ourtrprecheckfunction,NULL);
123 }
124 
125 static PetscErrorCode ourtrpostcheckfunction(SNES snes,Vec x,Vec y,Vec w,PetscBool *changed_y,PetscBool *changed_w,void *ctx)
126 {
127 #if defined(PETSC_HAVE_F90_2PTR_ARG)
128   void* ptr;
129   PetscObjectGetFortranCallback((PetscObject)snes,PETSC_FORTRAN_CALLBACK_CLASS,_cb.trpostcheck_pgiptr,NULL,&ptr);
130 #endif
131   PetscObjectUseFortranCallback(snes,_cb.trpostcheck,(SNES*,Vec*,Vec*,Vec *,PetscBool *,PetscBool *,void*,PetscErrorCode* PETSC_F90_2PTR_PROTO_NOVAR),(&snes,&x,&y,&w,changed_y,changed_w,_ctx,&ierr PETSC_F90_2PTR_PARAM(ptr)));
132 }
133 
134 PETSC_EXTERN void snesnewtontrsetpostcheck_(SNES *snes, void (*func)(SNES,Vec,Vec,Vec,PetscBool*,PetscBool*,void*),void *ctx,PetscErrorCode *ierr PETSC_F90_2PTR_PROTO(ptr))
135 {
136   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.trpostcheck,(PetscVoidFunction)func,ctx);if (*ierr) return;
137 #if defined(PETSC_HAVE_F90_2PTR_ARG)
138   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.trpostcheck_pgiptr,NULL,ptr);if (*ierr) return;
139 #endif
140   SNESNewtonTRSetPostCheck(*snes,ourtrpostcheckfunction,NULL);
141 }
142 
143 PETSC_EXTERN void snesnewtontrdcsetpostcheck_(SNES *snes, void (*func)(SNES,Vec,Vec,Vec,PetscBool*,PetscBool*,void*),void *ctx,PetscErrorCode *ierr PETSC_F90_2PTR_PROTO(ptr))
144 {
145   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.trpostcheck,(PetscVoidFunction)func,ctx);if (*ierr) return;
146 #if defined(PETSC_HAVE_F90_2PTR_ARG)
147   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.trpostcheck_pgiptr,NULL,ptr);if (*ierr) return;
148 #endif
149   SNESNewtonTRDCSetPostCheck(*snes,ourtrpostcheckfunction,NULL);
150 }
151 
152 static PetscErrorCode oursnesfunction(SNES snes,Vec x,Vec f,void *ctx)
153 {
154 #if defined(PETSC_HAVE_F90_2PTR_ARG)
155   void* ptr;
156   PetscObjectGetFortranCallback((PetscObject)snes,PETSC_FORTRAN_CALLBACK_CLASS,_cb.function_pgiptr,NULL,&ptr);
157 #endif
158   PetscObjectUseFortranCallback(snes,_cb.function,(SNES*,Vec*,Vec*,void*,PetscErrorCode* PETSC_F90_2PTR_PROTO_NOVAR),(&snes,&x,&f,_ctx,&ierr PETSC_F90_2PTR_PARAM(ptr)));
159 }
160 
161 static PetscErrorCode oursnestest(SNES snes,PetscInt it,PetscReal a,PetscReal d,PetscReal c,SNESConvergedReason *reason,void *ctx)
162 {
163   PetscObjectUseFortranCallback(snes,_cb.test,(SNES*,PetscInt*,PetscReal*,PetscReal*,PetscReal*,SNESConvergedReason*,void*,PetscErrorCode*),(&snes,&it,&a,&d,&c,reason,_ctx,&ierr));
164 }
165 
166 static PetscErrorCode ourdestroy(void *ctx)
167 {
168   PetscObjectUseFortranCallback(ctx,_cb.destroy,(void*,PetscErrorCode*),(_ctx,&ierr));
169 }
170 
171 static PetscErrorCode oursnesjacobian(SNES snes,Vec x,Mat m,Mat p,void *ctx)
172 {
173   PetscObjectUseFortranCallback(snes,_cb.jacobian,(SNES*,Vec*,Mat*,Mat*,void*,PetscErrorCode*),(&snes,&x,&m,&p,_ctx,&ierr));
174 }
175 
176 static PetscErrorCode oursnesupdate(SNES snes,PetscInt i)
177 {
178   PetscObjectUseFortranCallback(snes,_cb.update,(SNES*,PetscInt *,PetscErrorCode*),(&snes,&i,&ierr));
179 }
180 static PetscErrorCode oursnesngs(SNES snes,Vec x,Vec b,void *ctx)
181 {
182   PetscObjectUseFortranCallback(snes,_cb.ngs,(SNES*,Vec*,Vec*,void*,PetscErrorCode*),(&snes,&x,&b,_ctx,&ierr));
183 }
184 static PetscErrorCode oursnesmonitor(SNES snes,PetscInt i,PetscReal d,void *ctx)
185 {
186   PetscObjectUseFortranCallback(snes,_cb.monitor,(SNES*,PetscInt*,PetscReal*,void*,PetscErrorCode*),(&snes,&i,&d,_ctx,&ierr));
187 }
188 static PetscErrorCode ourmondestroy(void **ctx)
189 {
190   SNES snes = (SNES)*ctx;
191   PetscObjectUseFortranCallback(snes,_cb.mondestroy,(void*,PetscErrorCode*),(_ctx,&ierr));
192 }
193 
194 /*
195      snescomputejacobiandefault() and snescomputejacobiandefaultcolor()
196   These can be used directly from Fortran but are mostly so that
197   Fortran SNESSetJacobian() will properly handle the defaults being passed in.
198 */
199 PETSC_EXTERN void matmffdcomputejacobian_(SNES *snes,Vec *x,Mat *m,Mat *p,void *ctx,PetscErrorCode *ierr)
200 {
201   *ierr = MatMFFDComputeJacobian(*snes,*x,*m,*p,ctx);
202 }
203 PETSC_EXTERN void snescomputejacobiandefault_(SNES *snes,Vec *x,Mat *m,Mat *p,void *ctx,PetscErrorCode *ierr)
204 {
205   *ierr = SNESComputeJacobianDefault(*snes,*x,*m,*p,ctx);
206 }
207 PETSC_EXTERN void  snescomputejacobiandefaultcolor_(SNES *snes,Vec *x,Mat *m,Mat *p,void *ctx,PetscErrorCode *ierr)
208 {
209   *ierr = SNESComputeJacobianDefaultColor(*snes,*x,*m,*p,*(MatFDColoring*)ctx);
210 }
211 
212 PETSC_EXTERN void snessetjacobian_(SNES *snes,Mat *A,Mat *B,
213                                     void (*func)(SNES*,Vec*,Mat*,Mat*,void*,PetscErrorCode*),
214                                     void *ctx,PetscErrorCode *ierr)
215 {
216   CHKFORTRANNULLFUNCTION(func);
217   if ((PetscVoidFunction)func == (PetscVoidFunction)snescomputejacobiandefault_) {
218     *ierr = SNESSetJacobian(*snes,*A,*B,SNESComputeJacobianDefault,ctx);
219   } else if ((PetscVoidFunction)func == (PetscVoidFunction)snescomputejacobiandefaultcolor_) {
220     if (!ctx) {
221       *ierr = PETSC_ERR_ARG_NULL;
222       return;
223     }
224     *ierr = SNESSetJacobian(*snes,*A,*B,SNESComputeJacobianDefaultColor,*(MatFDColoring*)ctx);
225   } else if ((PetscVoidFunction)func == (PetscVoidFunction)matmffdcomputejacobian_) {
226     *ierr = SNESSetJacobian(*snes,*A,*B,MatMFFDComputeJacobian,ctx);
227   } else {
228     *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.jacobian,(PetscVoidFunction)func,ctx);
229     if (!*ierr) *ierr = SNESSetJacobian(*snes,*A,*B,oursnesjacobian,NULL);
230   }
231 }
232 PETSC_EXTERN void snessetjacobian1_(SNES *snes,Mat *A,Mat *B,
233                                     void (*func)(SNES*,Vec*,Mat*,Mat*,void*,PetscErrorCode*),
234                                     void *ctx,PetscErrorCode *ierr)
235 {
236   snessetjacobian_(snes,A,B,func,ctx,ierr);
237 }
238 PETSC_EXTERN void snessetjacobian2_(SNES *snes,Mat *A,Mat *B,
239                                     void (*func)(SNES*,Vec*,Mat*,Mat*,void*,PetscErrorCode*),
240                                     void *ctx,PetscErrorCode *ierr)
241 {
242   snessetjacobian_(snes,A,B,func,ctx,ierr);
243 }
244 
245 static PetscErrorCode oursnespicardfunction(SNES snes,Vec x,Vec f,void *ctx)
246 {
247 #if defined(PETSC_HAVE_F90_2PTR_ARG)
248   void* ptr;
249   PetscObjectGetFortranCallback((PetscObject)snes,PETSC_FORTRAN_CALLBACK_CLASS,_cb.function_pgiptr,NULL,&ptr);
250 #endif
251   PetscObjectUseFortranCallback(snes,_cb.function,(SNES*,Vec*,Vec*,void*,PetscErrorCode* PETSC_F90_2PTR_PROTO_NOVAR),(&snes,&x,&f,_ctx,&ierr PETSC_F90_2PTR_PARAM(ptr)));
252 }
253 
254 static PetscErrorCode oursnespicardjacobian(SNES snes,Vec x,Mat m,Mat p,void *ctx)
255 {
256   PetscObjectUseFortranCallback(snes,_cb.jacobian,(SNES*,Vec*,Mat*,Mat*,void*,PetscErrorCode*),(&snes,&x,&m,&p,_ctx,&ierr));
257 }
258 
259 PETSC_EXTERN void snessetpicard_(SNES *snes,Vec *r,void (*func)(SNES*,Vec*,Vec *,void*,PetscErrorCode*),Mat *A,Mat *B,
260                                  PetscErrorCode (*J)(SNES,Vec,Mat,Mat,void*),void *ctx,PetscErrorCode *ierr PETSC_F90_2PTR_PROTO(ptr))
261 {
262     *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.function,(PetscVoidFunction)func,ctx);
263 #if defined(PETSC_HAVE_F90_2PTR_ARG)
264   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.function_pgiptr,NULL,ptr);if (*ierr) return;
265 #endif
266     *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.jacobian,(PetscVoidFunction)J,ctx);
267     if (!*ierr) *ierr = SNESSetPicard(*snes,*r,oursnespicardfunction,*A,*B,oursnespicardjacobian,NULL);
268 }
269 
270 PETSC_EXTERN void snesgetoptionsprefix_(SNES *snes,char* prefix,PetscErrorCode *ierr,PETSC_FORTRAN_CHARLEN_T len)
271 {
272   const char *tname;
273 
274   *ierr = SNESGetOptionsPrefix(*snes,&tname);
275   *ierr = PetscStrncpy(prefix,tname,len);if (*ierr) return;
276   FIXRETURNCHAR(PETSC_TRUE,prefix,len);
277 }
278 
279 PETSC_EXTERN void snesgettype_(SNES *snes,char* name, PetscErrorCode *ierr,PETSC_FORTRAN_CHARLEN_T len)
280 {
281   const char *tname;
282 
283   *ierr = SNESGetType(*snes,&tname);
284   *ierr = PetscStrncpy(name,tname,len);if (*ierr) return;
285   FIXRETURNCHAR(PETSC_TRUE,name,len);
286 }
287 
288 /*
289    These are not usually called from Fortran but allow Fortran users
290    to transparently set these monitors from .F code
291 */
292 
293 PETSC_EXTERN void snessetfunction_(SNES *snes,Vec *r,void (*func)(SNES*,Vec*,Vec*,void*,PetscErrorCode*),void *ctx,PetscErrorCode *ierr PETSC_F90_2PTR_PROTO(ptr))
294 {
295   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.function,(PetscVoidFunction)func,ctx);if (*ierr) return;
296 #if defined(PETSC_HAVE_F90_2PTR_ARG)
297   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.function_pgiptr,NULL,ptr);if (*ierr) return;
298 #endif
299   *ierr = SNESSetFunction(*snes,*r,oursnesfunction,NULL);
300 }
301 
302 PETSC_EXTERN void snessetngs_(SNES *snes,void (*func)(SNES*,Vec*,Vec*,void*,PetscErrorCode*),void *ctx,PetscErrorCode *ierr)
303 {
304   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.ngs,(PetscVoidFunction)func,ctx);if (*ierr) return;
305   *ierr = SNESSetNGS(*snes,oursnesngs,NULL);
306 }
307 PETSC_EXTERN void snessetupdate_(SNES *snes,void (*func)(SNES*,PetscInt*,PetscErrorCode*),PetscErrorCode *ierr)
308 {
309   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.update,(PetscVoidFunction)func,NULL);if (*ierr) return;
310   *ierr = SNESSetUpdate(*snes,oursnesupdate);
311 }
312 
313 /* the func argument is ignored */
314 PETSC_EXTERN void snesgetfunction_(SNES *snes,Vec *r,void (*func)(SNES,Vec,Vec,void*),void **ctx,PetscErrorCode *ierr)
315 {
316   CHKFORTRANNULLOBJECT(r);
317   *ierr = SNESGetFunction(*snes,r,NULL,NULL); if (*ierr) return;
318   if ((PetscVoidFunction)func == (PetscVoidFunction)PETSC_NULL_FUNCTION_Fortran) return;
319   *ierr = PetscObjectGetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,_cb.function,NULL,ctx);
320 }
321 
322 PETSC_EXTERN void snesgetngs_(SNES *snes,void *func,void **ctx,PetscErrorCode *ierr)
323 {
324   *ierr = PetscObjectGetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,_cb.ngs,NULL,ctx);
325 }
326 
327 PETSC_EXTERN void snesconvergeddefault_(SNES *snes,PetscInt *it,PetscReal *a,PetscReal *b,PetscReal *c,SNESConvergedReason *r, void *ct,PetscErrorCode *ierr)
328 {
329   *ierr = SNESConvergedDefault(*snes,*it,*a,*b,*c,r,ct);
330 }
331 
332 PETSC_EXTERN void snesconvergedskip_(SNES *snes,PetscInt *it,PetscReal *a,PetscReal *b,PetscReal *c,SNESConvergedReason *r,void *ct,PetscErrorCode *ierr)
333 {
334   *ierr = SNESConvergedSkip(*snes,*it,*a,*b,*c,r,ct);
335 }
336 
337 PETSC_EXTERN void snessetconvergencetest_(SNES *snes,void (*func)(SNES*,PetscInt*,PetscReal*,PetscReal*,PetscReal*,SNESConvergedReason*,void*,PetscErrorCode*), void *cctx,void (*destroy)(void*),PetscErrorCode *ierr)
338 {
339   CHKFORTRANNULLFUNCTION(destroy);
340 
341   if ((PetscVoidFunction)func == (PetscVoidFunction)snesconvergeddefault_) {
342     *ierr = SNESSetConvergenceTest(*snes,SNESConvergedDefault,0,0);
343   } else if ((PetscVoidFunction)func == (PetscVoidFunction)snesconvergedskip_) {
344     *ierr = SNESSetConvergenceTest(*snes,SNESConvergedSkip,0,0);
345   } else {
346     *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.test,(PetscVoidFunction)func,cctx);if (*ierr) return;
347     *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.destroy,(PetscVoidFunction)destroy,cctx);if (*ierr) return;
348     *ierr = SNESSetConvergenceTest(*snes,oursnestest,*snes,ourdestroy);
349   }
350 }
351 
352 PETSC_EXTERN void snesview_(SNES *snes,PetscViewer *viewer, PetscErrorCode *ierr)
353 {
354   PetscViewer v;
355   PetscPatchDefaultViewers_Fortran(viewer,v);
356   *ierr = SNESView(*snes,v);
357 }
358 
359 /*  func is currently ignored from Fortran */
360 PETSC_EXTERN void snesgetjacobian_(SNES *snes,Mat *A,Mat *B,int *func,void **ctx,PetscErrorCode *ierr)
361 {
362   CHKFORTRANNULLINTEGER(ctx);
363   CHKFORTRANNULLOBJECT(A);
364   CHKFORTRANNULLOBJECT(B);
365   *ierr = SNESGetJacobian(*snes,A,B,0,NULL); if (*ierr) return;
366   *ierr = PetscObjectGetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,_cb.jacobian,NULL,ctx);
367 
368 }
369 
370 PETSC_EXTERN void snesgetconvergencehistory_(SNES *snes,PetscInt *na,PetscErrorCode *ierr)
371 {
372   *ierr = SNESGetConvergenceHistory(*snes,NULL,NULL,na);
373 }
374 
375 PETSC_EXTERN void snessettype_(SNES *snes,char* type,PetscErrorCode *ierr,PETSC_FORTRAN_CHARLEN_T len)
376 {
377   char *t;
378 
379   FIXCHAR(type,len,t);
380   *ierr = SNESSetType(*snes,t);if (*ierr) return;
381   FREECHAR(type,t);
382 }
383 
384 PETSC_EXTERN void snesappendoptionsprefix_(SNES *snes,char* prefix,PetscErrorCode *ierr,PETSC_FORTRAN_CHARLEN_T len)
385 {
386   char *t;
387 
388   FIXCHAR(prefix,len,t);
389   *ierr = SNESAppendOptionsPrefix(*snes,t);if (*ierr) return;
390   FREECHAR(prefix,t);
391 }
392 
393 PETSC_EXTERN void snessetoptionsprefix_(SNES *snes,char* prefix,PetscErrorCode *ierr,PETSC_FORTRAN_CHARLEN_T len)
394 {
395   char *t;
396 
397   FIXCHAR(prefix,len,t);
398   *ierr = SNESSetOptionsPrefix(*snes,t);if (*ierr) return;
399   FREECHAR(prefix,t);
400 }
401 
402 PETSC_EXTERN void snesmonitordefault_(SNES *snes,PetscInt *its,PetscReal *fgnorm,PetscViewerAndFormat **dummy,PetscErrorCode *ierr)
403 {
404   *ierr = SNESMonitorDefault(*snes,*its,*fgnorm,*dummy);
405 }
406 
407 PETSC_EXTERN void snesmonitorsolution_(SNES *snes,PetscInt *its,PetscReal *fgnorm,PetscViewerAndFormat **dummy,PetscErrorCode *ierr)
408 {
409   *ierr = SNESMonitorSolution(*snes,*its,*fgnorm,*dummy);
410 }
411 
412 PETSC_EXTERN void snesmonitorsolutionupdate_(SNES *snes,PetscInt *its,PetscReal *fgnorm,PetscViewerAndFormat **dummy,PetscErrorCode *ierr)
413 {
414   *ierr = SNESMonitorSolutionUpdate(*snes,*its,*fgnorm,*dummy);
415 }
416 
417 PETSC_EXTERN void snesmonitorset_(SNES *snes,void (*func)(SNES*,PetscInt*,PetscReal*,void*,PetscErrorCode*),void *mctx,void (*mondestroy)(void*,PetscErrorCode*),PetscErrorCode *ierr)
418 {
419   CHKFORTRANNULLFUNCTION(mondestroy);
420   if ((PetscVoidFunction)func == (PetscVoidFunction)snesmonitordefault_) {
421     *ierr = SNESMonitorSet(*snes,(PetscErrorCode (*)(SNES,PetscInt,PetscReal,void*))SNESMonitorDefault,*(PetscViewerAndFormat**)mctx,(PetscErrorCode (*)(void **))PetscViewerAndFormatDestroy);
422   } else if ((PetscVoidFunction)func == (PetscVoidFunction)snesmonitorsolution_) {
423     *ierr = SNESMonitorSet(*snes,(PetscErrorCode (*)(SNES,PetscInt,PetscReal,void*))SNESMonitorSolution,*(PetscViewerAndFormat**)mctx,(PetscErrorCode (*)(void **))PetscViewerAndFormatDestroy);
424   } else if ((PetscVoidFunction)func == (PetscVoidFunction)snesmonitorsolutionupdate_) {
425     *ierr = SNESMonitorSet(*snes,(PetscErrorCode (*)(SNES,PetscInt,PetscReal,void*))SNESMonitorSolutionUpdate,*(PetscViewerAndFormat**)mctx,(PetscErrorCode (*)(void **))PetscViewerAndFormatDestroy);
426   } else {
427     *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.monitor,(PetscVoidFunction)func,mctx);if (*ierr) return;
428     *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.mondestroy,(PetscVoidFunction)mondestroy,mctx);if (*ierr) return;
429     *ierr = SNESMonitorSet(*snes,oursnesmonitor,*snes,ourmondestroy);
430   }
431 }
432 
433 PETSC_EXTERN void snesviewfromoptions_(SNES *ao,PetscObject obj,char* type,PetscErrorCode *ierr,PETSC_FORTRAN_CHARLEN_T len)
434 {
435   char *t;
436 
437   FIXCHAR(type,len,t);
438   CHKFORTRANNULLOBJECT(obj);
439   *ierr = SNESViewFromOptions(*ao,obj,t);if (*ierr) return;
440   FREECHAR(type,t);
441 }
442 
443 PETSC_EXTERN void snesconvergedreasonview_(SNES *snes,PetscViewer *viewer, PetscErrorCode *ierr)
444 {
445   PetscViewer v;
446   PetscPatchDefaultViewers_Fortran(viewer,v);
447   *ierr = SNESConvergedReasonView(*snes,v);
448 }
449 
450 PETSC_EXTERN void snesgetconvergedreasonstring_(SNES *snes, char* strreason, PetscErrorCode *ierr, PETSC_FORTRAN_CHARLEN_T len)
451 {
452   const char *tstrreason;
453   *ierr = SNESGetConvergedReasonString(*snes,&tstrreason);
454   *ierr = PetscStrncpy(strreason,tstrreason,len);if (*ierr) return;
455   FIXRETURNCHAR(PETSC_TRUE,strreason,len);
456 }
457