xref: /petsc/src/snes/interface/ftn-custom/zsnesf.c (revision 9f4d3c52fa2fe0bb72fec4f4e85d8e495867af35)
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 *func,void **ctx,PetscErrorCode *ierr)
219 {
220   CHKFORTRANNULLOBJECT(r);
221   *ierr = SNESGetFunction(*snes,r,NULL,NULL); if (*ierr) return;
222   *ierr = PetscObjectGetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,_cb.function,NULL,ctx);
223 }
224 
225 PETSC_EXTERN void PETSC_STDCALL snesgetngs_(SNES *snes,void *func,void **ctx,PetscErrorCode *ierr)
226 {
227   *ierr = PetscObjectGetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,_cb.ngs,NULL,ctx);
228 }
229 
230 /*----------------------------------------------------------------------*/
231 
232 PETSC_EXTERN void snesconvergeddefault_(SNES *snes,PetscInt *it,PetscReal *a,PetscReal *b,PetscReal *c,SNESConvergedReason *r, void *ct,PetscErrorCode *ierr)
233 {
234   *ierr = SNESConvergedDefault(*snes,*it,*a,*b,*c,r,ct);
235 }
236 
237 PETSC_EXTERN void snesconvergedskip_(SNES *snes,PetscInt *it,PetscReal *a,PetscReal *b,PetscReal *c,SNESConvergedReason *r,void *ct,PetscErrorCode *ierr)
238 {
239   *ierr = SNESConvergedSkip(*snes,*it,*a,*b,*c,r,ct);
240 }
241 
242 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)
243 {
244   CHKFORTRANNULLOBJECT(cctx);
245   CHKFORTRANNULLFUNCTION(destroy);
246 
247   if ((PetscVoidFunction)func == (PetscVoidFunction)snesconvergeddefault_) {
248     *ierr = SNESSetConvergenceTest(*snes,SNESConvergedDefault,0,0);
249   } else if ((PetscVoidFunction)func == (PetscVoidFunction)snesconvergedskip_) {
250     *ierr = SNESSetConvergenceTest(*snes,SNESConvergedSkip,0,0);
251   } else {
252     *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.test,(PetscVoidFunction)func,cctx);if (*ierr) return;
253     *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.destroy,(PetscVoidFunction)destroy,cctx);if (*ierr) return;
254     *ierr = SNESSetConvergenceTest(*snes,oursnestest,*snes,ourdestroy);
255   }
256 }
257 /*----------------------------------------------------------------------*/
258 
259 PETSC_EXTERN void PETSC_STDCALL snesview_(SNES *snes,PetscViewer *viewer, PetscErrorCode *ierr)
260 {
261   PetscViewer v;
262   PetscPatchDefaultViewers_Fortran(viewer,v);
263   *ierr = SNESView(*snes,v);
264 }
265 
266 /*  func is currently ignored from Fortran */
267 PETSC_EXTERN void PETSC_STDCALL snesgetjacobian_(SNES *snes,Mat *A,Mat *B,int *func,void **ctx,PetscErrorCode *ierr)
268 {
269   CHKFORTRANNULLINTEGER(ctx);
270   CHKFORTRANNULLOBJECT(A);
271   CHKFORTRANNULLOBJECT(B);
272   *ierr = SNESGetJacobian(*snes,A,B,0,NULL); if (*ierr) return;
273   *ierr = PetscObjectGetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,_cb.jacobian,NULL,ctx);
274 
275 }
276 
277 PETSC_EXTERN void PETSC_STDCALL snesgetconvergencehistory_(SNES *snes,PetscInt *na,PetscErrorCode *ierr)
278 {
279   *ierr = SNESGetConvergenceHistory(*snes,NULL,NULL,na);
280 }
281 
282 PETSC_EXTERN void PETSC_STDCALL snessettype_(SNES *snes,char* type PETSC_MIXED_LEN(len),PetscErrorCode *ierr PETSC_END_LEN(len))
283 {
284   char *t;
285 
286   FIXCHAR(type,len,t);
287   *ierr = SNESSetType(*snes,t);
288   FREECHAR(type,t);
289 }
290 
291 PETSC_EXTERN void PETSC_STDCALL snesappendoptionsprefix_(SNES *snes,char* prefix PETSC_MIXED_LEN(len),PetscErrorCode *ierr PETSC_END_LEN(len))
292 {
293   char *t;
294 
295   FIXCHAR(prefix,len,t);
296   *ierr = SNESAppendOptionsPrefix(*snes,t);
297   FREECHAR(prefix,t);
298 }
299 
300 PETSC_EXTERN void PETSC_STDCALL snessetoptionsprefix_(SNES *snes,char* prefix PETSC_MIXED_LEN(len),PetscErrorCode *ierr PETSC_END_LEN(len))
301 {
302   char *t;
303 
304   FIXCHAR(prefix,len,t);
305   *ierr = SNESSetOptionsPrefix(*snes,t);
306   FREECHAR(prefix,t);
307 }
308 
309 /*----------------------------------------------------------------------*/
310 /* functions, hence no STDCALL */
311 
312 PETSC_EXTERN void snesmonitorlgresidualnorm_(SNES *snes,PetscInt *its,PetscReal *fgnorm,PetscObject *dummy,PetscErrorCode *ierr)
313 {
314   *ierr = SNESMonitorLGResidualNorm(*snes,*its,*fgnorm,dummy);
315 }
316 
317 PETSC_EXTERN void snesmonitordefault_(SNES *snes,PetscInt *its,PetscReal *fgnorm,PetscViewerAndFormat **dummy,PetscErrorCode *ierr)
318 {
319   *ierr = SNESMonitorDefault(*snes,*its,*fgnorm,*dummy);
320 }
321 
322 PETSC_EXTERN void snesmonitorsolution_(SNES *snes,PetscInt *its,PetscReal *fgnorm,PetscViewerAndFormat **dummy,PetscErrorCode *ierr)
323 {
324   *ierr = SNESMonitorSolution(*snes,*its,*fgnorm,*dummy);
325 }
326 
327 PETSC_EXTERN void snesmonitorsolutionupdate_(SNES *snes,PetscInt *its,PetscReal *fgnorm,PetscViewerAndFormat **dummy,PetscErrorCode *ierr)
328 {
329   *ierr = SNESMonitorSolutionUpdate(*snes,*its,*fgnorm,*dummy);
330 }
331 
332 
333 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)
334 {
335   CHKFORTRANNULLOBJECT(mctx);
336   CHKFORTRANNULLFUNCTION(mondestroy);
337   if ((PetscVoidFunction)func == (PetscVoidFunction)snesmonitordefault_) {
338     *ierr = SNESMonitorSet(*snes,(PetscErrorCode (*)(SNES,PetscInt,PetscReal,void*))SNESMonitorDefault,*(PetscViewerAndFormat**)mctx,(PetscErrorCode (*)(void **))PetscViewerAndFormatDestroy);
339   } else if ((PetscVoidFunction)func == (PetscVoidFunction)snesmonitorsolution_) {
340     *ierr = SNESMonitorSet(*snes,(PetscErrorCode (*)(SNES,PetscInt,PetscReal,void*))SNESMonitorSolution,*(PetscViewerAndFormat**)mctx,(PetscErrorCode (*)(void **))PetscViewerAndFormatDestroy);
341   } else if ((PetscVoidFunction)func == (PetscVoidFunction)snesmonitorsolutionupdate_) {
342     *ierr = SNESMonitorSet(*snes,(PetscErrorCode (*)(SNES,PetscInt,PetscReal,void*))SNESMonitorSolutionUpdate,*(PetscViewerAndFormat**)mctx,(PetscErrorCode (*)(void **))PetscViewerAndFormatDestroy);
343   } else if ((PetscVoidFunction)func == (PetscVoidFunction)snesmonitorlgresidualnorm_) {
344     *ierr = SNESMonitorSet(*snes,(PetscErrorCode (*)(SNES,PetscInt,PetscReal,void*))SNESMonitorLGResidualNorm,0,0);
345   } else {
346     *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.monitor,(PetscVoidFunction)func,mctx);if (*ierr) return;
347     *ierr = PetscObjectSetFortranCallback((PetscObject)*snes,PETSC_FORTRAN_CALLBACK_CLASS,&_cb.mondestroy,(PetscVoidFunction)mondestroy,mctx);if (*ierr) return;
348     *ierr = SNESMonitorSet(*snes,oursnesmonitor,*snes,ourmondestroy);
349   }
350 }
351 
352