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