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