xref: /petsc/src/snes/interface/ftn-custom/zsnesf.c (revision 00a402e09c6d62f19dbf72eef0e53394ab690d5c)
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   CHKFORTRANNULLFUNCTION(func);
144   if ((PetscVoidFunction)func == (PetscVoidFunction)snescomputejacobiandefault_) {
145     *ierr = SNESSetJacobian(*snes,*A,*B,SNESComputeJacobianDefault,ctx);
146   } else if ((PetscVoidFunction)func == (PetscVoidFunction)snescomputejacobiandefaultcolor_) {
147     if (!ctx) {
148       *ierr = PETSC_ERR_ARG_NULL;
149       return;
150     }
151     *ierr = SNESSetJacobian(*snes,*A,*B,SNESComputeJacobianDefaultColor,*(MatFDColoring*)ctx);
152   } else if ((PetscVoidFunction)func == (PetscVoidFunction)matmffdcomputejacobian_) {
153     *ierr = SNESSetJacobian(*snes,*A,*B,MatMFFDComputeJacobian,ctx);
154   } else {
155     *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.jacobian,(PetscVoidFunction)func,ctx);
156     if (!*ierr) *ierr = SNESSetJacobian(*snes,*A,*B,oursnesjacobian,NULL);
157   }
158 }
159 /* -------------------------------------------------------------*/
160 
161 PETSC_EXTERN void PETSC_STDCALL snessolve_(SNES *snes,Vec *b,Vec *x, int *ierr)
162 {
163   CHKFORTRANNULLOBJECTDEREFERENCE(b);
164   CHKFORTRANNULLOBJECTDEREFERENCE(x);
165   *ierr = SNESSolve(*snes,*b,*x);
166 }
167 
168 PETSC_EXTERN void PETSC_STDCALL snesgetoptionsprefix_(SNES *snes,char* prefix PETSC_MIXED_LEN(len),PetscErrorCode *ierr PETSC_END_LEN(len))
169 {
170   const char *tname;
171 
172   *ierr = SNESGetOptionsPrefix(*snes,&tname);
173   *ierr = PetscStrncpy(prefix,tname,len);if (*ierr) return;
174   FIXRETURNCHAR(PETSC_TRUE,prefix,len);
175 }
176 
177 PETSC_EXTERN void PETSC_STDCALL snesgettype_(SNES *snes,char* name PETSC_MIXED_LEN(len), PetscErrorCode *ierr PETSC_END_LEN(len))
178 {
179   const char *tname;
180 
181   *ierr = SNESGetType(*snes,&tname);
182   *ierr = PetscStrncpy(name,tname,len);if (*ierr) return;
183   FIXRETURNCHAR(PETSC_TRUE,name,len);
184 }
185 
186 /* ---------------------------------------------------------*/
187 
188 /*
189    These are not usually called from Fortran but allow Fortran users
190    to transparently set these monitors from .F code
191 
192    functions, hence no STDCALL
193 */
194 
195 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))
196 {
197   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.function,(PetscVoidFunction)func,ctx);if (*ierr) return;
198 #if defined(PETSC_HAVE_F90_2PTR_ARG)
199   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.function_pgiptr,NULL,ptr);if (*ierr) return;
200 #endif
201   *ierr = SNESSetFunction(*snes,*r,oursnesfunction,NULL);
202 }
203 
204 
205 PETSC_EXTERN void PETSC_STDCALL snessetngs_(SNES *snes,void (PETSC_STDCALL *func)(SNES*,Vec*,Vec*,void*,PetscErrorCode*),void *ctx,PetscErrorCode *ierr)
206 {
207   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.ngs,(PetscVoidFunction)func,ctx);if (*ierr) return;
208   *ierr = SNESSetNGS(*snes,oursnesngs,NULL);
209 }
210 PETSC_EXTERN void PETSC_STDCALL snessetupdate_(SNES *snes,void (PETSC_STDCALL *func)(SNES*,PetscInt*,PetscErrorCode*),PetscErrorCode *ierr)
211 {
212   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.update,(PetscVoidFunction)func,NULL);if (*ierr) return;
213   *ierr = SNESSetUpdate(*snes,oursnesupdate);
214 }
215 /* ---------------------------------------------------------*/
216 
217 /* the func argument is ignored */
218 PETSC_EXTERN void PETSC_STDCALL snesgetfunction_(SNES *snes,Vec *r,void (PETSC_STDCALL *func)(SNES,Vec,Vec,void*),void **ctx,PetscErrorCode *ierr)
219 {
220   CHKFORTRANNULLOBJECT(r);
221   *ierr = SNESGetFunction(*snes,r,NULL,NULL); if (*ierr) return;
222   if ((PetscVoidFunction)func == (PetscVoidFunction)PETSC_NULL_FUNCTION_Fortran) return;
223   *ierr = PetscObjectGetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,_cb.function,NULL,ctx);
224 }
225 
226 PETSC_EXTERN void PETSC_STDCALL snesgetngs_(SNES *snes,void *func,void **ctx,PetscErrorCode *ierr)
227 {
228   *ierr = PetscObjectGetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,_cb.ngs,NULL,ctx);
229 }
230 
231 /*----------------------------------------------------------------------*/
232 
233 PETSC_EXTERN void snesconvergeddefault_(SNES *snes,PetscInt *it,PetscReal *a,PetscReal *b,PetscReal *c,SNESConvergedReason *r, void *ct,PetscErrorCode *ierr)
234 {
235   *ierr = SNESConvergedDefault(*snes,*it,*a,*b,*c,r,ct);
236 }
237 
238 PETSC_EXTERN void snesconvergedskip_(SNES *snes,PetscInt *it,PetscReal *a,PetscReal *b,PetscReal *c,SNESConvergedReason *r,void *ct,PetscErrorCode *ierr)
239 {
240   *ierr = SNESConvergedSkip(*snes,*it,*a,*b,*c,r,ct);
241 }
242 
243 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)
244 {
245   CHKFORTRANNULLOBJECT(cctx);
246   CHKFORTRANNULLFUNCTION(destroy);
247 
248   if ((PetscVoidFunction)func == (PetscVoidFunction)snesconvergeddefault_) {
249     *ierr = SNESSetConvergenceTest(*snes,SNESConvergedDefault,0,0);
250   } else if ((PetscVoidFunction)func == (PetscVoidFunction)snesconvergedskip_) {
251     *ierr = SNESSetConvergenceTest(*snes,SNESConvergedSkip,0,0);
252   } else {
253     *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.test,(PetscVoidFunction)func,cctx);if (*ierr) return;
254     *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.destroy,(PetscVoidFunction)destroy,cctx);if (*ierr) return;
255     *ierr = SNESSetConvergenceTest(*snes,oursnestest,*snes,ourdestroy);
256   }
257 }
258 /*----------------------------------------------------------------------*/
259 
260 PETSC_EXTERN void PETSC_STDCALL snesview_(SNES *snes,PetscViewer *viewer, PetscErrorCode *ierr)
261 {
262   PetscViewer v;
263   PetscPatchDefaultViewers_Fortran(viewer,v);
264   *ierr = SNESView(*snes,v);
265 }
266 
267 /*  func is currently ignored from Fortran */
268 PETSC_EXTERN void PETSC_STDCALL snesgetjacobian_(SNES *snes,Mat *A,Mat *B,int *func,void **ctx,PetscErrorCode *ierr)
269 {
270   CHKFORTRANNULLINTEGER(ctx);
271   CHKFORTRANNULLOBJECT(A);
272   CHKFORTRANNULLOBJECT(B);
273   *ierr = SNESGetJacobian(*snes,A,B,0,NULL); if (*ierr) return;
274   *ierr = PetscObjectGetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,_cb.jacobian,NULL,ctx);
275 
276 }
277 
278 PETSC_EXTERN void PETSC_STDCALL snesgetconvergencehistory_(SNES *snes,PetscInt *na,PetscErrorCode *ierr)
279 {
280   *ierr = SNESGetConvergenceHistory(*snes,NULL,NULL,na);
281 }
282 
283 PETSC_EXTERN void PETSC_STDCALL snessettype_(SNES *snes,char* type PETSC_MIXED_LEN(len),PetscErrorCode *ierr PETSC_END_LEN(len))
284 {
285   char *t;
286 
287   FIXCHAR(type,len,t);
288   *ierr = SNESSetType(*snes,t);
289   FREECHAR(type,t);
290 }
291 
292 PETSC_EXTERN void PETSC_STDCALL snesappendoptionsprefix_(SNES *snes,char* prefix PETSC_MIXED_LEN(len),PetscErrorCode *ierr PETSC_END_LEN(len))
293 {
294   char *t;
295 
296   FIXCHAR(prefix,len,t);
297   *ierr = SNESAppendOptionsPrefix(*snes,t);
298   FREECHAR(prefix,t);
299 }
300 
301 PETSC_EXTERN void PETSC_STDCALL snessetoptionsprefix_(SNES *snes,char* prefix PETSC_MIXED_LEN(len),PetscErrorCode *ierr PETSC_END_LEN(len))
302 {
303   char *t;
304 
305   FIXCHAR(prefix,len,t);
306   *ierr = SNESSetOptionsPrefix(*snes,t);
307   FREECHAR(prefix,t);
308 }
309 
310 /*----------------------------------------------------------------------*/
311 /* functions, hence no STDCALL */
312 
313 PETSC_EXTERN void snesmonitorlgresidualnorm_(SNES *snes,PetscInt *its,PetscReal *fgnorm,PetscObject *dummy,PetscErrorCode *ierr)
314 {
315   *ierr = SNESMonitorLGResidualNorm(*snes,*its,*fgnorm,dummy);
316 }
317 
318 PETSC_EXTERN void snesmonitordefault_(SNES *snes,PetscInt *its,PetscReal *fgnorm,PetscViewerAndFormat **dummy,PetscErrorCode *ierr)
319 {
320   *ierr = SNESMonitorDefault(*snes,*its,*fgnorm,*dummy);
321 }
322 
323 PETSC_EXTERN void snesmonitorsolution_(SNES *snes,PetscInt *its,PetscReal *fgnorm,PetscViewerAndFormat **dummy,PetscErrorCode *ierr)
324 {
325   *ierr = SNESMonitorSolution(*snes,*its,*fgnorm,*dummy);
326 }
327 
328 PETSC_EXTERN void snesmonitorsolutionupdate_(SNES *snes,PetscInt *its,PetscReal *fgnorm,PetscViewerAndFormat **dummy,PetscErrorCode *ierr)
329 {
330   *ierr = SNESMonitorSolutionUpdate(*snes,*its,*fgnorm,*dummy);
331 }
332 
333 
334 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)
335 {
336   CHKFORTRANNULLOBJECT(mctx);
337   CHKFORTRANNULLFUNCTION(mondestroy);
338   if ((PetscVoidFunction)func == (PetscVoidFunction)snesmonitordefault_) {
339     *ierr = SNESMonitorSet(*snes,(PetscErrorCode (*)(SNES,PetscInt,PetscReal,void*))SNESMonitorDefault,*(PetscViewerAndFormat**)mctx,(PetscErrorCode (*)(void **))PetscViewerAndFormatDestroy);
340   } else if ((PetscVoidFunction)func == (PetscVoidFunction)snesmonitorsolution_) {
341     *ierr = SNESMonitorSet(*snes,(PetscErrorCode (*)(SNES,PetscInt,PetscReal,void*))SNESMonitorSolution,*(PetscViewerAndFormat**)mctx,(PetscErrorCode (*)(void **))PetscViewerAndFormatDestroy);
342   } else if ((PetscVoidFunction)func == (PetscVoidFunction)snesmonitorsolutionupdate_) {
343     *ierr = SNESMonitorSet(*snes,(PetscErrorCode (*)(SNES,PetscInt,PetscReal,void*))SNESMonitorSolutionUpdate,*(PetscViewerAndFormat**)mctx,(PetscErrorCode (*)(void **))PetscViewerAndFormatDestroy);
344   } else if ((PetscVoidFunction)func == (PetscVoidFunction)snesmonitorlgresidualnorm_) {
345     *ierr = SNESMonitorSet(*snes,(PetscErrorCode (*)(SNES,PetscInt,PetscReal,void*))SNESMonitorLGResidualNorm,0,0);
346   } else {
347     *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.monitor,(PetscVoidFunction)func,mctx);if (*ierr) return;
348     *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.mondestroy,(PetscVoidFunction)mondestroy,mctx);if (*ierr) return;
349     *ierr = SNESMonitorSet(*snes,oursnesmonitor,*snes,ourmondestroy);
350   }
351 }
352 
353