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