xref: /petsc/src/snes/interface/ftn-custom/zsnesf.c (revision ffeef943c8ee50edff320d8a3135bb0c94853e4c)
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 snessetfunction_                 SNESSETFUNCTION
16   #define snessetngs_                      SNESSETNGS
17   #define snessetupdate_                   SNESSETUPDATE
18   #define snesgetfunction_                 SNESGETFUNCTION
19   #define snesgetngs_                      SNESGETNGS
20   #define snessetconvergencetest_          SNESSETCONVERGENCETEST
21   #define snesconvergeddefault_            SNESCONVERGEDDEFAULT
22   #define snesconvergedskip_               SNESCONVERGEDSKIP
23   #define snesgetconvergencehistory_       SNESGETCONVERGENCEHISTORY
24   #define snesgetjacobian_                 SNESGETJACOBIAN
25   #define snesmonitordefault_              SNESMONITORDEFAULT
26   #define snesmonitorsolution_             SNESMONITORSOLUTION
27   #define snesmonitorsolutionupdate_       SNESMONITORSOLUTIONUPDATE
28   #define snesmonitorset_                  SNESMONITORSET
29   #define snesnewtontrsetprecheck_         SNESNEWTONTRSETPRECHECK
30   #define snesnewtontrsetpostcheck_        SNESNEWTONTRSETPOSTCHECK
31   #define snesnewtontrdcsetprecheck_       SNESNEWTONTRDCSETPRECHECK
32   #define snesnewtontrdcsetpostcheck_      SNESNEWTONTRDCSETPOSTCHECK
33 #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
34   #define snessetpicard_                   snessetpicard
35   #define matmffdcomputejacobian_          matmffdcomputejacobian
36   #define snessolve_                       snessolve
37   #define snescomputejacobiandefault_      snescomputejacobiandefault
38   #define snescomputejacobiandefaultcolor_ snescomputejacobiandefaultcolor
39   #define snessetjacobian_                 snessetjacobian
40   #define snessetjacobian1_                snessetjacobian1
41   #define snessetjacobian2_                snessetjacobian2
42   #define snessetfunction_                 snessetfunction
43   #define snessetngs_                      snessetngs
44   #define snessetupdate_                   snessetupdate
45   #define snesgetfunction_                 snesgetfunction
46   #define snesgetngs_                      snesgetngs
47   #define snessetconvergencetest_          snessetconvergencetest
48   #define snesconvergeddefault_            snesconvergeddefault
49   #define snesconvergedskip_               snesconvergedskip
50   #define snesgetjacobian_                 snesgetjacobian
51   #define snesgetconvergencehistory_       snesgetconvergencehistory
52   #define snesmonitordefault_              snesmonitordefault
53   #define snesmonitorsolution_             snesmonitorsolution
54   #define snesmonitorsolutionupdate_       snesmonitorsolutionupdate
55   #define snesmonitorset_                  snesmonitorset
56   #define snesnewtontrsetprecheck_         snesnewtontrsetprecheck
57   #define snesnewtontrsetpostcheck_        snesnewtontrsetpostcheck
58   #define snesnewtontrdcsetprecheck_       snesnewtontrdcsetprecheck
59   #define snesnewtontrdcsetpostcheck_      snesnewtontrdcsetpostcheck
60 #endif
61 
62 static struct {
63   PetscFortranCallbackId function;
64   PetscFortranCallbackId test;
65   PetscFortranCallbackId destroy;
66   PetscFortranCallbackId jacobian;
67   PetscFortranCallbackId monitor;
68   PetscFortranCallbackId mondestroy;
69   PetscFortranCallbackId ngs;
70   PetscFortranCallbackId update;
71   PetscFortranCallbackId trprecheck;
72   PetscFortranCallbackId trpostcheck;
73 #if defined(PETSC_HAVE_F90_2PTR_ARG)
74   PetscFortranCallbackId function_pgiptr;
75   PetscFortranCallbackId trprecheck_pgiptr;
76   PetscFortranCallbackId trpostcheck_pgiptr;
77 #endif
78 } _cb;
79 
80 static PetscErrorCode ourtrprecheckfunction(SNES snes, Vec x, Vec y, PetscBool *changed_y, void *ctx)
81 {
82 #if defined(PETSC_HAVE_F90_2PTR_ARG)
83   void *ptr;
84   PetscCall(PetscObjectGetFortranCallback((PetscObject)snes, PETSC_FORTRAN_CALLBACK_CLASS, _cb.trprecheck_pgiptr, NULL, &ptr));
85 #endif
86   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)));
87 }
88 
89 PETSC_EXTERN void snesnewtontrsetprecheck_(SNES *snes, void (*func)(SNES, Vec, Vec, PetscBool *, void *), void *ctx, PetscErrorCode *ierr PETSC_F90_2PTR_PROTO(ptr))
90 {
91   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.trprecheck, (PetscVoidFn *)func, ctx);
92   if (*ierr) return;
93 #if defined(PETSC_HAVE_F90_2PTR_ARG)
94   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.trprecheck_pgiptr, NULL, ptr);
95   if (*ierr) return;
96 #endif
97   *ierr = SNESNewtonTRSetPreCheck(*snes, ourtrprecheckfunction, NULL);
98 }
99 
100 PETSC_EXTERN void snesnewtontrdcsetprecheck_(SNES *snes, void (*func)(SNES, Vec, Vec, PetscBool *, void *), void *ctx, PetscErrorCode *ierr PETSC_F90_2PTR_PROTO(ptr))
101 {
102   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.trprecheck, (PetscVoidFn *)func, ctx);
103   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);
106   if (*ierr) return;
107 #endif
108   *ierr = SNESNewtonTRDCSetPreCheck(*snes, ourtrprecheckfunction, NULL);
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   PetscCall(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, (PetscVoidFn *)func, ctx);
123   if (*ierr) return;
124 #if defined(PETSC_HAVE_F90_2PTR_ARG)
125   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.trpostcheck_pgiptr, NULL, ptr);
126   if (*ierr) return;
127 #endif
128   *ierr = SNESNewtonTRSetPostCheck(*snes, ourtrpostcheckfunction, NULL);
129 }
130 
131 PETSC_EXTERN void snesnewtontrdcsetpostcheck_(SNES *snes, void (*func)(SNES, Vec, Vec, Vec, PetscBool *, PetscBool *, void *), void *ctx, PetscErrorCode *ierr PETSC_F90_2PTR_PROTO(ptr))
132 {
133   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.trpostcheck, (PetscVoidFn *)func, ctx);
134   if (*ierr) return;
135 #if defined(PETSC_HAVE_F90_2PTR_ARG)
136   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.trpostcheck_pgiptr, NULL, ptr);
137   if (*ierr) return;
138 #endif
139   *ierr = SNESNewtonTRDCSetPostCheck(*snes, ourtrpostcheckfunction, NULL);
140 }
141 
142 static PetscErrorCode oursnesfunction(SNES snes, Vec x, Vec f, void *ctx)
143 {
144 #if defined(PETSC_HAVE_F90_2PTR_ARG)
145   void *ptr;
146   PetscCall(PetscObjectGetFortranCallback((PetscObject)snes, PETSC_FORTRAN_CALLBACK_CLASS, _cb.function_pgiptr, NULL, &ptr));
147 #endif
148   PetscObjectUseFortranCallback(snes, _cb.function, (SNES *, Vec *, Vec *, void *, PetscErrorCode *PETSC_F90_2PTR_PROTO_NOVAR), (&snes, &x, &f, _ctx, &ierr PETSC_F90_2PTR_PARAM(ptr)));
149 }
150 
151 static PetscErrorCode oursnestest(SNES snes, PetscInt it, PetscReal a, PetscReal d, PetscReal c, SNESConvergedReason *reason, void *ctx)
152 {
153   PetscObjectUseFortranCallback(snes, _cb.test, (SNES *, PetscInt *, PetscReal *, PetscReal *, PetscReal *, SNESConvergedReason *, void *, PetscErrorCode *), (&snes, &it, &a, &d, &c, reason, _ctx, &ierr));
154 }
155 
156 static PetscErrorCode ourdestroy(void *ctx)
157 {
158   PetscObjectUseFortranCallback(ctx, _cb.destroy, (void *, PetscErrorCode *), (_ctx, &ierr));
159 }
160 
161 static PetscErrorCode oursnesjacobian(SNES snes, Vec x, Mat m, Mat p, void *ctx)
162 {
163   PetscObjectUseFortranCallback(snes, _cb.jacobian, (SNES *, Vec *, Mat *, Mat *, void *, PetscErrorCode *), (&snes, &x, &m, &p, _ctx, &ierr));
164 }
165 
166 static PetscErrorCode oursnesupdate(SNES snes, PetscInt i)
167 {
168   PetscObjectUseFortranCallback(snes, _cb.update, (SNES *, PetscInt *, PetscErrorCode *), (&snes, &i, &ierr));
169 }
170 static PetscErrorCode oursnesngs(SNES snes, Vec x, Vec b, void *ctx)
171 {
172   PetscObjectUseFortranCallback(snes, _cb.ngs, (SNES *, Vec *, Vec *, void *, PetscErrorCode *), (&snes, &x, &b, _ctx, &ierr));
173 }
174 static PetscErrorCode oursnesmonitor(SNES snes, PetscInt i, PetscReal d, void *ctx)
175 {
176   PetscObjectUseFortranCallback(snes, _cb.monitor, (SNES *, PetscInt *, PetscReal *, void *, PetscErrorCode *), (&snes, &i, &d, _ctx, &ierr));
177 }
178 static PetscErrorCode ourmondestroy(void **ctx)
179 {
180   SNES snes = (SNES)*ctx;
181   PetscObjectUseFortranCallback(snes, _cb.mondestroy, (void *, PetscErrorCode *), (_ctx, &ierr));
182 }
183 
184 /*
185      snescomputejacobiandefault() and snescomputejacobiandefaultcolor()
186   These can be used directly from Fortran but are mostly so that
187   Fortran SNESSetJacobian() will properly handle the defaults being passed in.
188 */
189 PETSC_EXTERN void matmffdcomputejacobian_(SNES *snes, Vec *x, Mat *m, Mat *p, void *ctx, PetscErrorCode *ierr)
190 {
191   *ierr = MatMFFDComputeJacobian(*snes, *x, *m, *p, ctx);
192 }
193 PETSC_EXTERN void snescomputejacobiandefault_(SNES *snes, Vec *x, Mat *m, Mat *p, void *ctx, PetscErrorCode *ierr)
194 {
195   *ierr = SNESComputeJacobianDefault(*snes, *x, *m, *p, ctx);
196 }
197 PETSC_EXTERN void snescomputejacobiandefaultcolor_(SNES *snes, Vec *x, Mat *m, Mat *p, void *ctx, PetscErrorCode *ierr)
198 {
199   *ierr = SNESComputeJacobianDefaultColor(*snes, *x, *m, *p, *(MatFDColoring *)ctx);
200 }
201 
202 PETSC_EXTERN void snessetjacobian_(SNES *snes, Mat *A, Mat *B, void (*func)(SNES *, Vec *, Mat *, Mat *, void *, PetscErrorCode *), void *ctx, PetscErrorCode *ierr)
203 {
204   CHKFORTRANNULLFUNCTION(func);
205   if ((PetscVoidFn *)func == (PetscVoidFn *)snescomputejacobiandefault_) {
206     *ierr = SNESSetJacobian(*snes, *A, *B, SNESComputeJacobianDefault, ctx);
207   } else if ((PetscVoidFn *)func == (PetscVoidFn *)snescomputejacobiandefaultcolor_) {
208     if (!ctx) {
209       *ierr = PETSC_ERR_ARG_NULL;
210       return;
211     }
212     *ierr = SNESSetJacobian(*snes, *A, *B, SNESComputeJacobianDefaultColor, *(MatFDColoring *)ctx);
213   } else if ((PetscVoidFn *)func == (PetscVoidFn *)matmffdcomputejacobian_) {
214     *ierr = SNESSetJacobian(*snes, *A, *B, MatMFFDComputeJacobian, ctx);
215   } else {
216     *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.jacobian, (PetscVoidFn *)func, ctx);
217     if (!*ierr) *ierr = SNESSetJacobian(*snes, *A, *B, oursnesjacobian, NULL);
218   }
219 }
220 PETSC_EXTERN void snessetjacobian1_(SNES *snes, Mat *A, Mat *B, void (*func)(SNES *, Vec *, Mat *, Mat *, void *, PetscErrorCode *), void *ctx, PetscErrorCode *ierr)
221 {
222   snessetjacobian_(snes, A, B, func, ctx, ierr);
223 }
224 PETSC_EXTERN void snessetjacobian2_(SNES *snes, Mat *A, Mat *B, void (*func)(SNES *, Vec *, Mat *, Mat *, void *, PetscErrorCode *), void *ctx, PetscErrorCode *ierr)
225 {
226   snessetjacobian_(snes, A, B, func, ctx, ierr);
227 }
228 
229 static PetscErrorCode oursnespicardfunction(SNES snes, Vec x, Vec f, void *ctx)
230 {
231 #if defined(PETSC_HAVE_F90_2PTR_ARG)
232   void *ptr;
233   PetscCall(PetscObjectGetFortranCallback((PetscObject)snes, PETSC_FORTRAN_CALLBACK_CLASS, _cb.function_pgiptr, NULL, &ptr));
234 #endif
235   PetscObjectUseFortranCallback(snes, _cb.function, (SNES *, Vec *, Vec *, void *, PetscErrorCode *PETSC_F90_2PTR_PROTO_NOVAR), (&snes, &x, &f, _ctx, &ierr PETSC_F90_2PTR_PARAM(ptr)));
236 }
237 
238 static PetscErrorCode oursnespicardjacobian(SNES snes, Vec x, Mat m, Mat p, void *ctx)
239 {
240   PetscObjectUseFortranCallback(snes, _cb.jacobian, (SNES *, Vec *, Mat *, Mat *, void *, PetscErrorCode *), (&snes, &x, &m, &p, _ctx, &ierr));
241 }
242 
243 PETSC_EXTERN void snessetpicard_(SNES *snes, Vec *r, void (*func)(SNES *, Vec *, Vec *, void *, PetscErrorCode *), Mat *A, Mat *B, PetscErrorCode (*J)(SNES, Vec, Mat, Mat, void *), void *ctx, PetscErrorCode *ierr PETSC_F90_2PTR_PROTO(ptr))
244 {
245   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.function, (PetscVoidFn *)func, ctx);
246 #if defined(PETSC_HAVE_F90_2PTR_ARG)
247   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.function_pgiptr, NULL, ptr);
248   if (*ierr) return;
249 #endif
250   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.jacobian, (PetscVoidFn *)J, ctx);
251   if (!*ierr) *ierr = SNESSetPicard(*snes, *r, oursnespicardfunction, *A, *B, oursnespicardjacobian, NULL);
252 }
253 
254 /*
255    These are not usually called from Fortran but allow Fortran users
256    to transparently set these monitors from .F code
257 */
258 
259 PETSC_EXTERN void snessetfunction_(SNES *snes, Vec *r, void (*func)(SNES *, Vec *, Vec *, void *, PetscErrorCode *), void *ctx, PetscErrorCode *ierr PETSC_F90_2PTR_PROTO(ptr))
260 {
261   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.function, (PetscVoidFn *)func, ctx);
262   if (*ierr) return;
263 #if defined(PETSC_HAVE_F90_2PTR_ARG)
264   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.function_pgiptr, NULL, ptr);
265   if (*ierr) return;
266 #endif
267   *ierr = SNESSetFunction(*snes, *r, oursnesfunction, NULL);
268 }
269 
270 PETSC_EXTERN void snessetngs_(SNES *snes, void (*func)(SNES *, Vec *, Vec *, void *, PetscErrorCode *), void *ctx, PetscErrorCode *ierr)
271 {
272   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.ngs, (PetscVoidFn *)func, ctx);
273   if (*ierr) return;
274   *ierr = SNESSetNGS(*snes, oursnesngs, NULL);
275 }
276 PETSC_EXTERN void snessetupdate_(SNES *snes, void (*func)(SNES *, PetscInt *, PetscErrorCode *), PetscErrorCode *ierr)
277 {
278   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.update, (PetscVoidFn *)func, NULL);
279   if (*ierr) return;
280   *ierr = SNESSetUpdate(*snes, oursnesupdate);
281 }
282 
283 /* the func argument is ignored */
284 PETSC_EXTERN void snesgetfunction_(SNES *snes, Vec *r, void (*func)(SNES, Vec, Vec, void *), void **ctx, PetscErrorCode *ierr)
285 {
286   CHKFORTRANNULLOBJECT(r);
287   *ierr = SNESGetFunction(*snes, r, NULL, NULL);
288   if (*ierr) return;
289   if ((PetscVoidFn *)func == (PetscVoidFn *)PETSC_NULL_FUNCTION_Fortran) return;
290   *ierr = PetscObjectGetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, _cb.function, NULL, ctx);
291 }
292 
293 PETSC_EXTERN void snesgetngs_(SNES *snes, void *func, void **ctx, PetscErrorCode *ierr)
294 {
295   *ierr = PetscObjectGetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, _cb.ngs, NULL, ctx);
296 }
297 
298 PETSC_EXTERN void snesconvergeddefault_(SNES *snes, PetscInt *it, PetscReal *a, PetscReal *b, PetscReal *c, SNESConvergedReason *r, void *ct, PetscErrorCode *ierr)
299 {
300   *ierr = SNESConvergedDefault(*snes, *it, *a, *b, *c, r, ct);
301 }
302 
303 PETSC_EXTERN void snesconvergedskip_(SNES *snes, PetscInt *it, PetscReal *a, PetscReal *b, PetscReal *c, SNESConvergedReason *r, void *ct, PetscErrorCode *ierr)
304 {
305   *ierr = SNESConvergedSkip(*snes, *it, *a, *b, *c, r, ct);
306 }
307 
308 PETSC_EXTERN void snessetconvergencetest_(SNES *snes, void (*func)(SNES *, PetscInt *, PetscReal *, PetscReal *, PetscReal *, SNESConvergedReason *, void *, PetscErrorCode *), void *cctx, void (*destroy)(void *), PetscErrorCode *ierr)
309 {
310   CHKFORTRANNULLFUNCTION(destroy);
311 
312   if ((PetscVoidFn *)func == (PetscVoidFn *)snesconvergeddefault_) {
313     *ierr = SNESSetConvergenceTest(*snes, SNESConvergedDefault, NULL, NULL);
314   } else if ((PetscVoidFn *)func == (PetscVoidFn *)snesconvergedskip_) {
315     *ierr = SNESSetConvergenceTest(*snes, SNESConvergedSkip, NULL, NULL);
316   } else {
317     *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.test, (PetscVoidFn *)func, cctx);
318     if (*ierr) return;
319     *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.destroy, (PetscVoidFn *)destroy, cctx);
320     if (*ierr) return;
321     *ierr = SNESSetConvergenceTest(*snes, oursnestest, *snes, ourdestroy);
322   }
323 }
324 
325 /*  func is currently ignored from Fortran */
326 PETSC_EXTERN void snesgetjacobian_(SNES *snes, Mat *A, Mat *B, int *func, void **ctx, PetscErrorCode *ierr)
327 {
328   CHKFORTRANNULLINTEGER(ctx);
329   CHKFORTRANNULLOBJECT(A);
330   CHKFORTRANNULLOBJECT(B);
331   *ierr = SNESGetJacobian(*snes, A, B, NULL, NULL);
332   if (*ierr) return;
333   *ierr = PetscObjectGetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, _cb.jacobian, NULL, ctx);
334 }
335 
336 PETSC_EXTERN void snesgetconvergencehistory_(SNES *snes, PetscInt *na, PetscErrorCode *ierr)
337 {
338   *ierr = SNESGetConvergenceHistory(*snes, NULL, NULL, na);
339 }
340 
341 PETSC_EXTERN void snesmonitordefault_(SNES *snes, PetscInt *its, PetscReal *fgnorm, PetscViewerAndFormat **dummy, PetscErrorCode *ierr)
342 {
343   *ierr = SNESMonitorDefault(*snes, *its, *fgnorm, *dummy);
344 }
345 
346 PETSC_EXTERN void snesmonitorsolution_(SNES *snes, PetscInt *its, PetscReal *fgnorm, PetscViewerAndFormat **dummy, PetscErrorCode *ierr)
347 {
348   *ierr = SNESMonitorSolution(*snes, *its, *fgnorm, *dummy);
349 }
350 
351 PETSC_EXTERN void snesmonitorsolutionupdate_(SNES *snes, PetscInt *its, PetscReal *fgnorm, PetscViewerAndFormat **dummy, PetscErrorCode *ierr)
352 {
353   *ierr = SNESMonitorSolutionUpdate(*snes, *its, *fgnorm, *dummy);
354 }
355 
356 PETSC_EXTERN void snesmonitorset_(SNES *snes, void (*func)(SNES *, PetscInt *, PetscReal *, void *, PetscErrorCode *), void *mctx, void (*mondestroy)(void *, PetscErrorCode *), PetscErrorCode *ierr)
357 {
358   CHKFORTRANNULLFUNCTION(mondestroy);
359   if ((PetscVoidFn *)func == (PetscVoidFn *)snesmonitordefault_) {
360     *ierr = SNESMonitorSet(*snes, (PetscErrorCode(*)(SNES, PetscInt, PetscReal, void *))SNESMonitorDefault, *(PetscViewerAndFormat **)mctx, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy);
361   } else if ((PetscVoidFn *)func == (PetscVoidFn *)snesmonitorsolution_) {
362     *ierr = SNESMonitorSet(*snes, (PetscErrorCode(*)(SNES, PetscInt, PetscReal, void *))SNESMonitorSolution, *(PetscViewerAndFormat **)mctx, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy);
363   } else if ((PetscVoidFn *)func == (PetscVoidFn *)snesmonitorsolutionupdate_) {
364     *ierr = SNESMonitorSet(*snes, (PetscErrorCode(*)(SNES, PetscInt, PetscReal, void *))SNESMonitorSolutionUpdate, *(PetscViewerAndFormat **)mctx, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy);
365   } else {
366     *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.monitor, (PetscVoidFn *)func, mctx);
367     if (*ierr) return;
368     *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.mondestroy, (PetscVoidFn *)mondestroy, mctx);
369     if (*ierr) return;
370     *ierr = SNESMonitorSet(*snes, oursnesmonitor, *snes, ourmondestroy);
371   }
372 }
373