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