xref: /petsc/src/snes/interface/ftn-custom/zsnesf.c (revision c00ad2bc68eaf75b07ffe004a7a3030395081ef3)
1af0996ceSBarry Smith #include <petsc/private/fortranimpl.h>
2c6db04a5SJed Brown #include <petscsnes.h>
3665c2dedSJed Brown #include <petscviewer.h>
48ad9143bSBarry Smith #include <petsc/private/f90impl.h>
58e27ec22SSatish Balay 
68e27ec22SSatish Balay #if defined(PETSC_HAVE_FORTRAN_CAPS)
791f3e32bSBarry Smith   #define snesconvergedreasonview_         SNESCONVERGEDREASONVIEW
8df2570feSBarry Smith   #define snessetpicard_                   SNESSETPICARD
9df66969eSBarry Smith   #define matmffdcomputejacobian_          MATMFFDCOMPUTEJACOBIAN
106ce558aeSBarry Smith   #define snessolve_                       SNESSOLVE
118d359177SBarry Smith   #define snescomputejacobiandefault_      SNESCOMPUTEJACOBIANDEFAULT
128d359177SBarry Smith   #define snescomputejacobiandefaultcolor_ SNESCOMPUTEJACOBIANDEFAULTCOLOR
138e27ec22SSatish Balay   #define snessetjacobian_                 SNESSETJACOBIAN
1417a42bb7SSatish Balay   #define snessetjacobian1_                SNESSETJACOBIAN1
1517a42bb7SSatish Balay   #define snessetjacobian2_                SNESSETJACOBIAN2
168e27ec22SSatish Balay   #define snesgetoptionsprefix_            SNESGETOPTIONSPREFIX
178e27ec22SSatish Balay   #define snesgettype_                     SNESGETTYPE
188e27ec22SSatish Balay   #define snessetfunction_                 SNESSETFUNCTION
19*c00ad2bcSBarry Smith   #define snessetobjective_                SNESSETOBJECTIVE
20be95d8f1SBarry Smith   #define snessetngs_                      SNESSETNGS
21dfef22ccSBarry Smith   #define snessetupdate_                   SNESSETUPDATE
228e27ec22SSatish Balay   #define snesgetfunction_                 SNESGETFUNCTION
23be95d8f1SBarry Smith   #define snesgetngs_                      SNESGETNGS
248e27ec22SSatish Balay   #define snessetconvergencetest_          SNESSETCONVERGENCETEST
258d359177SBarry Smith   #define snesconvergeddefault_            SNESCONVERGEDDEFAULT
26e07f7f94SSatish Balay   #define snesconvergedskip_               SNESCONVERGEDSKIP
278e27ec22SSatish Balay   #define snesview_                        SNESVIEW
288e27ec22SSatish Balay   #define snesgetconvergencehistory_       SNESGETCONVERGENCEHISTORY
298e27ec22SSatish Balay   #define snesgetjacobian_                 SNESGETJACOBIAN
308e27ec22SSatish Balay   #define snessettype_                     SNESSETTYPE
318e27ec22SSatish Balay   #define snesappendoptionsprefix_         SNESAPPENDOPTIONSPREFIX
328e27ec22SSatish Balay   #define snessetoptionsprefix_            SNESSETOPTIONSPREFIX
33a6570f20SBarry Smith   #define snesmonitordefault_              SNESMONITORDEFAULT
34a6570f20SBarry Smith   #define snesmonitorsolution_             SNESMONITORSOLUTION
35a6570f20SBarry Smith   #define snesmonitorsolutionupdate_       SNESMONITORSOLUTIONUPDATE
36a6570f20SBarry Smith   #define snesmonitorset_                  SNESMONITORSET
37c9368356SGlenn Hammond   #define snesnewtontrsetprecheck_         SNESNEWTONTRSETPRECHECK
383b42469aSBarry Smith   #define snesnewtontrsetpostcheck_        SNESNEWTONTRSETPOSTCHECK
3941ba4c6cSHeeho Park   #define snesnewtontrdcsetprecheck_       SNESNEWTONTRDCSETPRECHECK
4041ba4c6cSHeeho Park   #define snesnewtontrdcsetpostcheck_      SNESNEWTONTRDCSETPOSTCHECK
41fe2efc57SMark   #define snesviewfromoptions_             SNESVIEWFROMOPTIONS
42c4421ceaSFande Kong   #define snesgetconvergedreasonstring_    SNESGETCONVERGEDREASONSTRING
434e2a09fcSBarry Smith #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
4491f3e32bSBarry Smith   #define snesconvergedreasonview_         snesconvergedreasonview
45df2570feSBarry Smith   #define snessetpicard_                   snessetpicard
46df66969eSBarry Smith   #define matmffdcomputejacobian_          matmffdcomputejacobian
476ce558aeSBarry Smith   #define snessolve_                       snessolve
488d359177SBarry Smith   #define snescomputejacobiandefault_      snescomputejacobiandefault
498d359177SBarry Smith   #define snescomputejacobiandefaultcolor_ snescomputejacobiandefaultcolor
508e27ec22SSatish Balay   #define snessetjacobian_                 snessetjacobian
5117a42bb7SSatish Balay   #define snessetjacobian1_                snessetjacobian1
5217a42bb7SSatish Balay   #define snessetjacobian2_                snessetjacobian2
538e27ec22SSatish Balay   #define snesgetoptionsprefix_            snesgetoptionsprefix
548e27ec22SSatish Balay   #define snesgettype_                     snesgettype
558e27ec22SSatish Balay   #define snessetfunction_                 snessetfunction
56*c00ad2bcSBarry Smith   #define snessetobjective_                snessetobjective
57be95d8f1SBarry Smith   #define snessetngs_                      snessetngs
58dfef22ccSBarry Smith   #define snessetupdate_                   snessetupdate
598e27ec22SSatish Balay   #define snesgetfunction_                 snesgetfunction
60be95d8f1SBarry Smith   #define snesgetngs_                      snesgetngs
618e27ec22SSatish Balay   #define snessetconvergencetest_          snessetconvergencetest
628d359177SBarry Smith   #define snesconvergeddefault_            snesconvergeddefault
63e07f7f94SSatish Balay   #define snesconvergedskip_               snesconvergedskip
648e27ec22SSatish Balay   #define snesview_                        snesview
658e27ec22SSatish Balay   #define snesgetjacobian_                 snesgetjacobian
668e27ec22SSatish Balay   #define snesgetconvergencehistory_       snesgetconvergencehistory
678e27ec22SSatish Balay   #define snessettype_                     snessettype
688e27ec22SSatish Balay   #define snesappendoptionsprefix_         snesappendoptionsprefix
698e27ec22SSatish Balay   #define snessetoptionsprefix_            snessetoptionsprefix
70a6570f20SBarry Smith   #define snesmonitordefault_              snesmonitordefault
71a6570f20SBarry Smith   #define snesmonitorsolution_             snesmonitorsolution
72a6570f20SBarry Smith   #define snesmonitorsolutionupdate_       snesmonitorsolutionupdate
73a6570f20SBarry Smith   #define snesmonitorset_                  snesmonitorset
74c9368356SGlenn Hammond   #define snesnewtontrsetprecheck_         snesnewtontrsetprecheck
753b42469aSBarry Smith   #define snesnewtontrsetpostcheck_        snesnewtontrsetpostcheck
7641ba4c6cSHeeho Park   #define snesnewtontrdcsetprecheck_       snesnewtontrdcsetprecheck
7741ba4c6cSHeeho Park   #define snesnewtontrdcsetpostcheck_      snesnewtontrdcsetpostcheck
78fe2efc57SMark   #define snesviewfromoptions_             snesviewfromoptions
79c4421ceaSFande Kong   #define snesgetconvergedreasonstring_    snesgetconvergedreasonstring
808e27ec22SSatish Balay #endif
818e27ec22SSatish Balay 
82f6291634SJed Brown static struct {
83f6291634SJed Brown   PetscFortranCallbackId function;
84*c00ad2bcSBarry Smith   PetscFortranCallbackId objective;
85f6291634SJed Brown   PetscFortranCallbackId test;
86f6291634SJed Brown   PetscFortranCallbackId destroy;
87f6291634SJed Brown   PetscFortranCallbackId jacobian;
88f6291634SJed Brown   PetscFortranCallbackId monitor;
89f6291634SJed Brown   PetscFortranCallbackId mondestroy;
90be95d8f1SBarry Smith   PetscFortranCallbackId ngs;
91dfef22ccSBarry Smith   PetscFortranCallbackId update;
92c9368356SGlenn Hammond   PetscFortranCallbackId trprecheck;
937cb011f5SBarry Smith   PetscFortranCallbackId trpostcheck;
9489e00c7dSSatish Balay #if defined(PETSC_HAVE_F90_2PTR_ARG)
9589e00c7dSSatish Balay   PetscFortranCallbackId function_pgiptr;
96*c00ad2bcSBarry Smith   PetscFortranCallbackId objective_pgiptr;
97c9368356SGlenn Hammond   PetscFortranCallbackId trprecheck_pgiptr;
983c2ee7eaSBarry Smith   PetscFortranCallbackId trpostcheck_pgiptr;
9989e00c7dSSatish Balay #endif
100f6291634SJed Brown } _cb;
10190b77ac2SPeter Brune 
102c9368356SGlenn Hammond static PetscErrorCode ourtrprecheckfunction(SNES snes, Vec x, Vec y, PetscBool *changed_y, void *ctx)
103c9368356SGlenn Hammond {
104c9368356SGlenn Hammond #if defined(PETSC_HAVE_F90_2PTR_ARG)
105c9368356SGlenn Hammond   void *ptr;
1063ba16761SJacob Faibussowitsch   PetscCall(PetscObjectGetFortranCallback((PetscObject)snes, PETSC_FORTRAN_CALLBACK_CLASS, _cb.trprecheck_pgiptr, NULL, &ptr));
107c9368356SGlenn Hammond #endif
108c9368356SGlenn Hammond   PetscObjectUseFortranCallback(snes, _cb.trprecheck, (SNES *, Vec *, Vec *, PetscBool *, void *, PetscErrorCode *PETSC_F90_2PTR_PROTO_NOVAR), (&snes, &x, &y, changed_y, _ctx, &ierr PETSC_F90_2PTR_PARAM(ptr)));
109c9368356SGlenn Hammond }
110c9368356SGlenn Hammond 
11119caf8f3SSatish Balay PETSC_EXTERN void snesnewtontrsetprecheck_(SNES *snes, void (*func)(SNES, Vec, Vec, PetscBool *, void *), void *ctx, PetscErrorCode *ierr PETSC_F90_2PTR_PROTO(ptr))
112c9368356SGlenn Hammond {
1138434afd1SBarry Smith   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.trprecheck, (PetscVoidFn *)func, ctx);
1143ba16761SJacob Faibussowitsch   if (*ierr) return;
115c9368356SGlenn Hammond #if defined(PETSC_HAVE_F90_2PTR_ARG)
1163ba16761SJacob Faibussowitsch   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.trprecheck_pgiptr, NULL, ptr);
1173ba16761SJacob Faibussowitsch   if (*ierr) return;
118c9368356SGlenn Hammond #endif
1193ba16761SJacob Faibussowitsch   *ierr = SNESNewtonTRSetPreCheck(*snes, ourtrprecheckfunction, NULL);
120c9368356SGlenn Hammond }
121c9368356SGlenn Hammond 
12241ba4c6cSHeeho Park PETSC_EXTERN void snesnewtontrdcsetprecheck_(SNES *snes, void (*func)(SNES, Vec, Vec, PetscBool *, void *), void *ctx, PetscErrorCode *ierr PETSC_F90_2PTR_PROTO(ptr))
12341ba4c6cSHeeho Park {
1248434afd1SBarry Smith   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.trprecheck, (PetscVoidFn *)func, ctx);
1253ba16761SJacob Faibussowitsch   if (*ierr) return;
12641ba4c6cSHeeho Park #if defined(PETSC_HAVE_F90_2PTR_ARG)
1273ba16761SJacob Faibussowitsch   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.trprecheck_pgiptr, NULL, ptr);
1283ba16761SJacob Faibussowitsch   if (*ierr) return;
12941ba4c6cSHeeho Park #endif
1303ba16761SJacob Faibussowitsch   *ierr = SNESNewtonTRDCSetPreCheck(*snes, ourtrprecheckfunction, NULL);
13141ba4c6cSHeeho Park }
13241ba4c6cSHeeho Park 
133c9368356SGlenn Hammond static PetscErrorCode ourtrpostcheckfunction(SNES snes, Vec x, Vec y, Vec w, PetscBool *changed_y, PetscBool *changed_w, void *ctx)
1347cb011f5SBarry Smith {
1357cb011f5SBarry Smith #if defined(PETSC_HAVE_F90_2PTR_ARG)
1367cb011f5SBarry Smith   void *ptr;
1373ba16761SJacob Faibussowitsch   PetscCall(PetscObjectGetFortranCallback((PetscObject)snes, PETSC_FORTRAN_CALLBACK_CLASS, _cb.trpostcheck_pgiptr, NULL, &ptr));
1387cb011f5SBarry Smith #endif
139c9368356SGlenn Hammond   PetscObjectUseFortranCallback(snes, _cb.trpostcheck, (SNES *, Vec *, Vec *, Vec *, PetscBool *, PetscBool *, void *, PetscErrorCode *PETSC_F90_2PTR_PROTO_NOVAR), (&snes, &x, &y, &w, changed_y, changed_w, _ctx, &ierr PETSC_F90_2PTR_PARAM(ptr)));
1407cb011f5SBarry Smith }
1417cb011f5SBarry Smith 
14219caf8f3SSatish Balay PETSC_EXTERN void snesnewtontrsetpostcheck_(SNES *snes, void (*func)(SNES, Vec, Vec, Vec, PetscBool *, PetscBool *, void *), void *ctx, PetscErrorCode *ierr PETSC_F90_2PTR_PROTO(ptr))
1437cb011f5SBarry Smith {
1448434afd1SBarry Smith   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.trpostcheck, (PetscVoidFn *)func, ctx);
1453ba16761SJacob Faibussowitsch   if (*ierr) return;
1467cb011f5SBarry Smith #if defined(PETSC_HAVE_F90_2PTR_ARG)
1473ba16761SJacob Faibussowitsch   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.trpostcheck_pgiptr, NULL, ptr);
1483ba16761SJacob Faibussowitsch   if (*ierr) return;
1497cb011f5SBarry Smith #endif
1503ba16761SJacob Faibussowitsch   *ierr = SNESNewtonTRSetPostCheck(*snes, ourtrpostcheckfunction, NULL);
1517cb011f5SBarry Smith }
1527cb011f5SBarry Smith 
15341ba4c6cSHeeho Park PETSC_EXTERN void snesnewtontrdcsetpostcheck_(SNES *snes, void (*func)(SNES, Vec, Vec, Vec, PetscBool *, PetscBool *, void *), void *ctx, PetscErrorCode *ierr PETSC_F90_2PTR_PROTO(ptr))
15441ba4c6cSHeeho Park {
1558434afd1SBarry Smith   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.trpostcheck, (PetscVoidFn *)func, ctx);
1563ba16761SJacob Faibussowitsch   if (*ierr) return;
15741ba4c6cSHeeho Park #if defined(PETSC_HAVE_F90_2PTR_ARG)
1583ba16761SJacob Faibussowitsch   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.trpostcheck_pgiptr, NULL, ptr);
1593ba16761SJacob Faibussowitsch   if (*ierr) return;
16041ba4c6cSHeeho Park #endif
1613ba16761SJacob Faibussowitsch   *ierr = SNESNewtonTRDCSetPostCheck(*snes, ourtrpostcheckfunction, NULL);
16241ba4c6cSHeeho Park }
16341ba4c6cSHeeho Park 
1648e27ec22SSatish Balay static PetscErrorCode oursnesfunction(SNES snes, Vec x, Vec f, void *ctx)
1658e27ec22SSatish Balay {
16689e00c7dSSatish Balay #if defined(PETSC_HAVE_F90_2PTR_ARG)
16789e00c7dSSatish Balay   void *ptr;
1683ba16761SJacob Faibussowitsch   PetscCall(PetscObjectGetFortranCallback((PetscObject)snes, PETSC_FORTRAN_CALLBACK_CLASS, _cb.function_pgiptr, NULL, &ptr));
16989e00c7dSSatish Balay #endif
17089e00c7dSSatish Balay   PetscObjectUseFortranCallback(snes, _cb.function, (SNES *, Vec *, Vec *, void *, PetscErrorCode *PETSC_F90_2PTR_PROTO_NOVAR), (&snes, &x, &f, _ctx, &ierr PETSC_F90_2PTR_PARAM(ptr)));
1718e27ec22SSatish Balay }
172b8ebb45fSBarry Smith 
173*c00ad2bcSBarry Smith static PetscErrorCode oursnesobjective(SNES snes, Vec x, PetscReal *v, void *ctx)
174*c00ad2bcSBarry Smith {
175*c00ad2bcSBarry Smith #if defined(PETSC_HAVE_F90_2PTR_ARG)
176*c00ad2bcSBarry Smith   void *ptr;
177*c00ad2bcSBarry Smith   PetscCall(PetscObjectGetFortranCallback((PetscObject)snes, PETSC_FORTRAN_CALLBACK_CLASS, _cb.objective_pgiptr, NULL, &ptr));
178*c00ad2bcSBarry Smith #endif
179*c00ad2bcSBarry Smith   PetscObjectUseFortranCallback(snes, _cb.objective, (SNES *, Vec *, PetscReal *, void *, PetscErrorCode *PETSC_F90_2PTR_PROTO_NOVAR), (&snes, &x, v, _ctx, &ierr PETSC_F90_2PTR_PARAM(ptr)));
180*c00ad2bcSBarry Smith }
181*c00ad2bcSBarry Smith 
18206ee9f85SBarry Smith static PetscErrorCode oursnestest(SNES snes, PetscInt it, PetscReal a, PetscReal d, PetscReal c, SNESConvergedReason *reason, void *ctx)
1838e27ec22SSatish Balay {
184f6291634SJed Brown   PetscObjectUseFortranCallback(snes, _cb.test, (SNES *, PetscInt *, PetscReal *, PetscReal *, PetscReal *, SNESConvergedReason *, void *, PetscErrorCode *), (&snes, &it, &a, &d, &c, reason, _ctx, &ierr));
1857f7931b9SBarry Smith }
1867f7931b9SBarry Smith 
1877f7931b9SBarry Smith static PetscErrorCode ourdestroy(void *ctx)
1887f7931b9SBarry Smith {
189f6291634SJed Brown   PetscObjectUseFortranCallback(ctx, _cb.destroy, (void *, PetscErrorCode *), (_ctx, &ierr));
1908e27ec22SSatish Balay }
1918e27ec22SSatish Balay 
192d1e9a80fSBarry Smith static PetscErrorCode oursnesjacobian(SNES snes, Vec x, Mat m, Mat p, void *ctx)
1938e27ec22SSatish Balay {
194d1e9a80fSBarry Smith   PetscObjectUseFortranCallback(snes, _cb.jacobian, (SNES *, Vec *, Mat *, Mat *, void *, PetscErrorCode *), (&snes, &x, &m, &p, _ctx, &ierr));
1958e27ec22SSatish Balay }
196f6291634SJed Brown 
197dfef22ccSBarry Smith static PetscErrorCode oursnesupdate(SNES snes, PetscInt i)
198dfef22ccSBarry Smith {
199dfef22ccSBarry Smith   PetscObjectUseFortranCallback(snes, _cb.update, (SNES *, PetscInt *, PetscErrorCode *), (&snes, &i, &ierr));
200dfef22ccSBarry Smith }
201be95d8f1SBarry Smith static PetscErrorCode oursnesngs(SNES snes, Vec x, Vec b, void *ctx)
20290b77ac2SPeter Brune {
203be95d8f1SBarry Smith   PetscObjectUseFortranCallback(snes, _cb.ngs, (SNES *, Vec *, Vec *, void *, PetscErrorCode *), (&snes, &x, &b, _ctx, &ierr));
20490b77ac2SPeter Brune }
2058e27ec22SSatish Balay static PetscErrorCode oursnesmonitor(SNES snes, PetscInt i, PetscReal d, void *ctx)
2068e27ec22SSatish Balay {
207f6291634SJed Brown   PetscObjectUseFortranCallback(snes, _cb.monitor, (SNES *, PetscInt *, PetscReal *, void *, PetscErrorCode *), (&snes, &i, &d, _ctx, &ierr));
2088e27ec22SSatish Balay }
209c2efdce3SBarry Smith static PetscErrorCode ourmondestroy(void **ctx)
2108e27ec22SSatish Balay {
211f6291634SJed Brown   SNES snes = (SNES)*ctx;
212f6291634SJed Brown   PetscObjectUseFortranCallback(snes, _cb.mondestroy, (void *, PetscErrorCode *), (_ctx, &ierr));
2138e27ec22SSatish Balay }
2148e27ec22SSatish Balay 
2158e27ec22SSatish Balay /*
2168d359177SBarry Smith      snescomputejacobiandefault() and snescomputejacobiandefaultcolor()
2178e27ec22SSatish Balay   These can be used directly from Fortran but are mostly so that
2188e27ec22SSatish Balay   Fortran SNESSetJacobian() will properly handle the defaults being passed in.
2198e27ec22SSatish Balay */
220d1e9a80fSBarry Smith PETSC_EXTERN void matmffdcomputejacobian_(SNES *snes, Vec *x, Mat *m, Mat *p, void *ctx, PetscErrorCode *ierr)
221df66969eSBarry Smith {
222d1e9a80fSBarry Smith   *ierr = MatMFFDComputeJacobian(*snes, *x, *m, *p, ctx);
223df66969eSBarry Smith }
224d1e9a80fSBarry Smith PETSC_EXTERN void snescomputejacobiandefault_(SNES *snes, Vec *x, Mat *m, Mat *p, void *ctx, PetscErrorCode *ierr)
2258e27ec22SSatish Balay {
226d1e9a80fSBarry Smith   *ierr = SNESComputeJacobianDefault(*snes, *x, *m, *p, ctx);
2278e27ec22SSatish Balay }
228d1e9a80fSBarry Smith PETSC_EXTERN void snescomputejacobiandefaultcolor_(SNES *snes, Vec *x, Mat *m, Mat *p, void *ctx, PetscErrorCode *ierr)
2298e27ec22SSatish Balay {
230d1e9a80fSBarry Smith   *ierr = SNESComputeJacobianDefaultColor(*snes, *x, *m, *p, *(MatFDColoring *)ctx);
2318e27ec22SSatish Balay }
2328e27ec22SSatish Balay 
2335975b3b6SBarry Smith PETSC_EXTERN void snessetjacobian_(SNES *snes, Mat *A, Mat *B, void (*func)(SNES *, Vec *, Mat *, Mat *, void *, PetscErrorCode *), void *ctx, PetscErrorCode *ierr)
2348e27ec22SSatish Balay {
235f5b6597dSBarry Smith   CHKFORTRANNULLFUNCTION(func);
2368434afd1SBarry Smith   if ((PetscVoidFn *)func == (PetscVoidFn *)snescomputejacobiandefault_) {
2378d359177SBarry Smith     *ierr = SNESSetJacobian(*snes, *A, *B, SNESComputeJacobianDefault, ctx);
2388434afd1SBarry Smith   } else if ((PetscVoidFn *)func == (PetscVoidFn *)snescomputejacobiandefaultcolor_) {
239e025ade3SBarry Smith     if (!ctx) {
240e025ade3SBarry Smith       *ierr = PETSC_ERR_ARG_NULL;
241e025ade3SBarry Smith       return;
242e025ade3SBarry Smith     }
2438d359177SBarry Smith     *ierr = SNESSetJacobian(*snes, *A, *B, SNESComputeJacobianDefaultColor, *(MatFDColoring *)ctx);
2448434afd1SBarry Smith   } else if ((PetscVoidFn *)func == (PetscVoidFn *)matmffdcomputejacobian_) {
245df66969eSBarry Smith     *ierr = SNESSetJacobian(*snes, *A, *B, MatMFFDComputeJacobian, ctx);
2468e27ec22SSatish Balay   } else {
2478434afd1SBarry Smith     *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.jacobian, (PetscVoidFn *)func, ctx);
2480298fd71SBarry Smith     if (!*ierr) *ierr = SNESSetJacobian(*snes, *A, *B, oursnesjacobian, NULL);
2498e27ec22SSatish Balay   }
2508e27ec22SSatish Balay }
2515975b3b6SBarry Smith PETSC_EXTERN void snessetjacobian1_(SNES *snes, Mat *A, Mat *B, void (*func)(SNES *, Vec *, Mat *, Mat *, void *, PetscErrorCode *), void *ctx, PetscErrorCode *ierr)
25217a42bb7SSatish Balay {
25317a42bb7SSatish Balay   snessetjacobian_(snes, A, B, func, ctx, ierr);
25417a42bb7SSatish Balay }
2555975b3b6SBarry Smith PETSC_EXTERN void snessetjacobian2_(SNES *snes, Mat *A, Mat *B, void (*func)(SNES *, Vec *, Mat *, Mat *, void *, PetscErrorCode *), void *ctx, PetscErrorCode *ierr)
25617a42bb7SSatish Balay {
25717a42bb7SSatish Balay   snessetjacobian_(snes, A, B, func, ctx, ierr);
25817a42bb7SSatish Balay }
259f6dfbefdSBarry Smith 
260df2570feSBarry Smith static PetscErrorCode oursnespicardfunction(SNES snes, Vec x, Vec f, void *ctx)
261df2570feSBarry Smith {
262df2570feSBarry Smith #if defined(PETSC_HAVE_F90_2PTR_ARG)
263df2570feSBarry Smith   void *ptr;
2643ba16761SJacob Faibussowitsch   PetscCall(PetscObjectGetFortranCallback((PetscObject)snes, PETSC_FORTRAN_CALLBACK_CLASS, _cb.function_pgiptr, NULL, &ptr));
265df2570feSBarry Smith #endif
266df2570feSBarry Smith   PetscObjectUseFortranCallback(snes, _cb.function, (SNES *, Vec *, Vec *, void *, PetscErrorCode *PETSC_F90_2PTR_PROTO_NOVAR), (&snes, &x, &f, _ctx, &ierr PETSC_F90_2PTR_PARAM(ptr)));
267df2570feSBarry Smith }
268df2570feSBarry Smith 
269df2570feSBarry Smith static PetscErrorCode oursnespicardjacobian(SNES snes, Vec x, Mat m, Mat p, void *ctx)
270df2570feSBarry Smith {
271df2570feSBarry Smith   PetscObjectUseFortranCallback(snes, _cb.jacobian, (SNES *, Vec *, Mat *, Mat *, void *, PetscErrorCode *), (&snes, &x, &m, &p, _ctx, &ierr));
272df2570feSBarry Smith }
273df2570feSBarry Smith 
2745975b3b6SBarry Smith PETSC_EXTERN void snessetpicard_(SNES *snes, Vec *r, void (*func)(SNES *, Vec *, Vec *, void *, PetscErrorCode *), Mat *A, Mat *B, PetscErrorCode (*J)(SNES, Vec, Mat, Mat, void *), void *ctx, PetscErrorCode *ierr PETSC_F90_2PTR_PROTO(ptr))
275df2570feSBarry Smith {
2768434afd1SBarry Smith   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.function, (PetscVoidFn *)func, ctx);
277df2570feSBarry Smith #if defined(PETSC_HAVE_F90_2PTR_ARG)
2785975b3b6SBarry Smith   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.function_pgiptr, NULL, ptr);
2795975b3b6SBarry Smith   if (*ierr) return;
280df2570feSBarry Smith #endif
2818434afd1SBarry Smith   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.jacobian, (PetscVoidFn *)J, ctx);
282df2570feSBarry Smith   if (!*ierr) *ierr = SNESSetPicard(*snes, *r, oursnespicardfunction, *A, *B, oursnespicardjacobian, NULL);
283df2570feSBarry Smith }
2848e27ec22SSatish Balay 
28519caf8f3SSatish Balay PETSC_EXTERN void snesgetoptionsprefix_(SNES *snes, char *prefix, PetscErrorCode *ierr, PETSC_FORTRAN_CHARLEN_T len)
2868e27ec22SSatish Balay {
2878e27ec22SSatish Balay   const char *tname;
2888e27ec22SSatish Balay 
2898e27ec22SSatish Balay   *ierr = SNESGetOptionsPrefix(*snes, &tname);
2905975b3b6SBarry Smith   *ierr = PetscStrncpy(prefix, tname, len);
2915975b3b6SBarry Smith   if (*ierr) return;
292d6a8cea5SBarry Smith   FIXRETURNCHAR(PETSC_TRUE, prefix, len);
2938e27ec22SSatish Balay }
2948e27ec22SSatish Balay 
29519caf8f3SSatish Balay PETSC_EXTERN void snesgettype_(SNES *snes, char *name, PetscErrorCode *ierr, PETSC_FORTRAN_CHARLEN_T len)
2968e27ec22SSatish Balay {
2978e27ec22SSatish Balay   const char *tname;
2988e27ec22SSatish Balay 
2998e27ec22SSatish Balay   *ierr = SNESGetType(*snes, &tname);
3005975b3b6SBarry Smith   *ierr = PetscStrncpy(name, tname, len);
3015975b3b6SBarry Smith   if (*ierr) return;
3027c363081SBarry Smith   FIXRETURNCHAR(PETSC_TRUE, name, len);
3038e27ec22SSatish Balay }
304e3da1266SHong Zhang 
3058e27ec22SSatish Balay /*
3068e27ec22SSatish Balay    These are not usually called from Fortran but allow Fortran users
3078e27ec22SSatish Balay    to transparently set these monitors from .F code
3088e27ec22SSatish Balay */
3098e27ec22SSatish Balay 
31019caf8f3SSatish Balay PETSC_EXTERN void snessetfunction_(SNES *snes, Vec *r, void (*func)(SNES *, Vec *, Vec *, void *, PetscErrorCode *), void *ctx, PetscErrorCode *ierr PETSC_F90_2PTR_PROTO(ptr))
3118e27ec22SSatish Balay {
3128434afd1SBarry Smith   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.function, (PetscVoidFn *)func, ctx);
3135975b3b6SBarry Smith   if (*ierr) return;
31489e00c7dSSatish Balay #if defined(PETSC_HAVE_F90_2PTR_ARG)
3155975b3b6SBarry Smith   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.function_pgiptr, NULL, ptr);
3165975b3b6SBarry Smith   if (*ierr) return;
31789e00c7dSSatish Balay #endif
318aecf964fSBarry Smith   *ierr = SNESSetFunction(*snes, *r, oursnesfunction, NULL);
3198e27ec22SSatish Balay }
320c79ef259SPeter Brune 
321*c00ad2bcSBarry Smith PETSC_EXTERN void snessetobjective_(SNES *snes, void (*func)(SNES *, Vec *, PetscReal *, void *, PetscErrorCode *), void *ctx, PetscErrorCode *ierr PETSC_F90_2PTR_PROTO(ptr))
322*c00ad2bcSBarry Smith {
323*c00ad2bcSBarry Smith   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.objective, (PetscVoidFn *)func, ctx);
324*c00ad2bcSBarry Smith   if (*ierr) return;
325*c00ad2bcSBarry Smith #if defined(PETSC_HAVE_F90_2PTR_ARG)
326*c00ad2bcSBarry Smith   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.objective_pgiptr, NULL, ptr);
327*c00ad2bcSBarry Smith   if (*ierr) return;
328*c00ad2bcSBarry Smith #endif
329*c00ad2bcSBarry Smith   *ierr = SNESSetObjective(*snes, oursnesobjective, NULL);
330*c00ad2bcSBarry Smith }
331*c00ad2bcSBarry Smith 
33219caf8f3SSatish Balay PETSC_EXTERN void snessetngs_(SNES *snes, void (*func)(SNES *, Vec *, Vec *, void *, PetscErrorCode *), void *ctx, PetscErrorCode *ierr)
333c79ef259SPeter Brune {
3348434afd1SBarry Smith   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.ngs, (PetscVoidFn *)func, ctx);
3355975b3b6SBarry Smith   if (*ierr) return;
336aecf964fSBarry Smith   *ierr = SNESSetNGS(*snes, oursnesngs, NULL);
337c79ef259SPeter Brune }
33819caf8f3SSatish Balay PETSC_EXTERN void snessetupdate_(SNES *snes, void (*func)(SNES *, PetscInt *, PetscErrorCode *), PetscErrorCode *ierr)
339dfef22ccSBarry Smith {
3408434afd1SBarry Smith   *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.update, (PetscVoidFn *)func, NULL);
3415975b3b6SBarry Smith   if (*ierr) return;
342aecf964fSBarry Smith   *ierr = SNESSetUpdate(*snes, oursnesupdate);
343dfef22ccSBarry Smith }
3448e27ec22SSatish Balay 
3458e27ec22SSatish Balay /* the func argument is ignored */
34619caf8f3SSatish Balay PETSC_EXTERN void snesgetfunction_(SNES *snes, Vec *r, void (*func)(SNES, Vec, Vec, void *), void **ctx, PetscErrorCode *ierr)
3478e27ec22SSatish Balay {
3488e27ec22SSatish Balay   CHKFORTRANNULLOBJECT(r);
3495975b3b6SBarry Smith   *ierr = SNESGetFunction(*snes, r, NULL, NULL);
3505975b3b6SBarry Smith   if (*ierr) return;
3518434afd1SBarry Smith   if ((PetscVoidFn *)func == (PetscVoidFn *)PETSC_NULL_FUNCTION_Fortran) return;
3520298fd71SBarry Smith   *ierr = PetscObjectGetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, _cb.function, NULL, ctx);
3538e27ec22SSatish Balay }
354c79ef259SPeter Brune 
35519caf8f3SSatish Balay PETSC_EXTERN void snesgetngs_(SNES *snes, void *func, void **ctx, PetscErrorCode *ierr)
356c79ef259SPeter Brune {
357be95d8f1SBarry Smith   *ierr = PetscObjectGetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, _cb.ngs, NULL, ctx);
358c79ef259SPeter Brune }
359c79ef259SPeter Brune 
36069c1e2abSSatish Balay PETSC_EXTERN void snesconvergeddefault_(SNES *snes, PetscInt *it, PetscReal *a, PetscReal *b, PetscReal *c, SNESConvergedReason *r, void *ct, PetscErrorCode *ierr)
3613f149594SLisandro Dalcin {
3628d359177SBarry Smith   *ierr = SNESConvergedDefault(*snes, *it, *a, *b, *c, r, ct);
3633f149594SLisandro Dalcin }
3643f149594SLisandro Dalcin 
365e07f7f94SSatish Balay PETSC_EXTERN void snesconvergedskip_(SNES *snes, PetscInt *it, PetscReal *a, PetscReal *b, PetscReal *c, SNESConvergedReason *r, void *ct, PetscErrorCode *ierr)
3663f149594SLisandro Dalcin {
367e2a6519dSDmitry Karpeev   *ierr = SNESConvergedSkip(*snes, *it, *a, *b, *c, r, ct);
3683f149594SLisandro Dalcin }
3693f149594SLisandro Dalcin 
37019caf8f3SSatish Balay PETSC_EXTERN void snessetconvergencetest_(SNES *snes, void (*func)(SNES *, PetscInt *, PetscReal *, PetscReal *, PetscReal *, SNESConvergedReason *, void *, PetscErrorCode *), void *cctx, void (*destroy)(void *), PetscErrorCode *ierr)
3718e27ec22SSatish Balay {
3723f22127dSBarry Smith   CHKFORTRANNULLFUNCTION(destroy);
3733f149594SLisandro Dalcin 
3748434afd1SBarry Smith   if ((PetscVoidFn *)func == (PetscVoidFn *)snesconvergeddefault_) {
375dfef5ea7SSatish Balay     *ierr = SNESSetConvergenceTest(*snes, SNESConvergedDefault, NULL, NULL);
3768434afd1SBarry Smith   } else if ((PetscVoidFn *)func == (PetscVoidFn *)snesconvergedskip_) {
377dfef5ea7SSatish Balay     *ierr = SNESSetConvergenceTest(*snes, SNESConvergedSkip, NULL, NULL);
3788e27ec22SSatish Balay   } else {
3798434afd1SBarry Smith     *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.test, (PetscVoidFn *)func, cctx);
3805975b3b6SBarry Smith     if (*ierr) return;
3818434afd1SBarry Smith     *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.destroy, (PetscVoidFn *)destroy, cctx);
3825975b3b6SBarry Smith     if (*ierr) return;
383aecf964fSBarry Smith     *ierr = SNESSetConvergenceTest(*snes, oursnestest, *snes, ourdestroy);
3848e27ec22SSatish Balay   }
3858e27ec22SSatish Balay }
3868e27ec22SSatish Balay 
38719caf8f3SSatish Balay PETSC_EXTERN void snesview_(SNES *snes, PetscViewer *viewer, PetscErrorCode *ierr)
3888e27ec22SSatish Balay {
3898e27ec22SSatish Balay   PetscViewer v;
3908e27ec22SSatish Balay   PetscPatchDefaultViewers_Fortran(viewer, v);
3918e27ec22SSatish Balay   *ierr = SNESView(*snes, v);
3928e27ec22SSatish Balay }
3938e27ec22SSatish Balay 
3948e27ec22SSatish Balay /*  func is currently ignored from Fortran */
39519caf8f3SSatish Balay PETSC_EXTERN void snesgetjacobian_(SNES *snes, Mat *A, Mat *B, int *func, void **ctx, PetscErrorCode *ierr)
3968e27ec22SSatish Balay {
3978e27ec22SSatish Balay   CHKFORTRANNULLINTEGER(ctx);
3988e27ec22SSatish Balay   CHKFORTRANNULLOBJECT(A);
3998e27ec22SSatish Balay   CHKFORTRANNULLOBJECT(B);
400dfef5ea7SSatish Balay   *ierr = SNESGetJacobian(*snes, A, B, NULL, NULL);
4015975b3b6SBarry Smith   if (*ierr) return;
4020298fd71SBarry Smith   *ierr = PetscObjectGetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, _cb.jacobian, NULL, ctx);
4038e27ec22SSatish Balay }
4048e27ec22SSatish Balay 
40519caf8f3SSatish Balay PETSC_EXTERN void snesgetconvergencehistory_(SNES *snes, PetscInt *na, PetscErrorCode *ierr)
4068e27ec22SSatish Balay {
4070298fd71SBarry Smith   *ierr = SNESGetConvergenceHistory(*snes, NULL, NULL, na);
4088e27ec22SSatish Balay }
4098e27ec22SSatish Balay 
41019caf8f3SSatish Balay PETSC_EXTERN void snessettype_(SNES *snes, char *type, PetscErrorCode *ierr, PETSC_FORTRAN_CHARLEN_T len)
4118e27ec22SSatish Balay {
4128e27ec22SSatish Balay   char *t;
4138e27ec22SSatish Balay 
4148e27ec22SSatish Balay   FIXCHAR(type, len, t);
4155975b3b6SBarry Smith   *ierr = SNESSetType(*snes, t);
4165975b3b6SBarry Smith   if (*ierr) return;
4178e27ec22SSatish Balay   FREECHAR(type, t);
4188e27ec22SSatish Balay }
4198e27ec22SSatish Balay 
42019caf8f3SSatish Balay PETSC_EXTERN void snesappendoptionsprefix_(SNES *snes, char *prefix, PetscErrorCode *ierr, PETSC_FORTRAN_CHARLEN_T len)
4218e27ec22SSatish Balay {
4228e27ec22SSatish Balay   char *t;
4238e27ec22SSatish Balay 
4248e27ec22SSatish Balay   FIXCHAR(prefix, len, t);
4255975b3b6SBarry Smith   *ierr = SNESAppendOptionsPrefix(*snes, t);
4265975b3b6SBarry Smith   if (*ierr) return;
4278e27ec22SSatish Balay   FREECHAR(prefix, t);
4288e27ec22SSatish Balay }
4298e27ec22SSatish Balay 
43019caf8f3SSatish Balay PETSC_EXTERN void snessetoptionsprefix_(SNES *snes, char *prefix, PetscErrorCode *ierr, PETSC_FORTRAN_CHARLEN_T len)
4318e27ec22SSatish Balay {
4328e27ec22SSatish Balay   char *t;
4338e27ec22SSatish Balay 
4348e27ec22SSatish Balay   FIXCHAR(prefix, len, t);
4355975b3b6SBarry Smith   *ierr = SNESSetOptionsPrefix(*snes, t);
4365975b3b6SBarry Smith   if (*ierr) return;
4378e27ec22SSatish Balay   FREECHAR(prefix, t);
4388e27ec22SSatish Balay }
4398e27ec22SSatish Balay 
44052f0073cSBarry Smith PETSC_EXTERN void snesmonitordefault_(SNES *snes, PetscInt *its, PetscReal *fgnorm, PetscViewerAndFormat **dummy, PetscErrorCode *ierr)
4418e27ec22SSatish Balay {
442410efd14SBarry Smith   *ierr = SNESMonitorDefault(*snes, *its, *fgnorm, *dummy);
4438e27ec22SSatish Balay }
4448e27ec22SSatish Balay 
44552f0073cSBarry Smith PETSC_EXTERN void snesmonitorsolution_(SNES *snes, PetscInt *its, PetscReal *fgnorm, PetscViewerAndFormat **dummy, PetscErrorCode *ierr)
4468e27ec22SSatish Balay {
447410efd14SBarry Smith   *ierr = SNESMonitorSolution(*snes, *its, *fgnorm, *dummy);
4488e27ec22SSatish Balay }
4498e27ec22SSatish Balay 
45052f0073cSBarry Smith PETSC_EXTERN void snesmonitorsolutionupdate_(SNES *snes, PetscInt *its, PetscReal *fgnorm, PetscViewerAndFormat **dummy, PetscErrorCode *ierr)
4518e27ec22SSatish Balay {
452410efd14SBarry Smith   *ierr = SNESMonitorSolutionUpdate(*snes, *its, *fgnorm, *dummy);
4538e27ec22SSatish Balay }
4548e27ec22SSatish Balay 
45519caf8f3SSatish Balay PETSC_EXTERN void snesmonitorset_(SNES *snes, void (*func)(SNES *, PetscInt *, PetscReal *, void *, PetscErrorCode *), void *mctx, void (*mondestroy)(void *, PetscErrorCode *), PetscErrorCode *ierr)
4568e27ec22SSatish Balay {
457aecf964fSBarry Smith   CHKFORTRANNULLFUNCTION(mondestroy);
4588434afd1SBarry Smith   if ((PetscVoidFn *)func == (PetscVoidFn *)snesmonitordefault_) {
4591cb03803SBarry Smith     *ierr = SNESMonitorSet(*snes, (PetscErrorCode(*)(SNES, PetscInt, PetscReal, void *))SNESMonitorDefault, *(PetscViewerAndFormat **)mctx, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy);
4608434afd1SBarry Smith   } else if ((PetscVoidFn *)func == (PetscVoidFn *)snesmonitorsolution_) {
4611cb03803SBarry Smith     *ierr = SNESMonitorSet(*snes, (PetscErrorCode(*)(SNES, PetscInt, PetscReal, void *))SNESMonitorSolution, *(PetscViewerAndFormat **)mctx, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy);
4628434afd1SBarry Smith   } else if ((PetscVoidFn *)func == (PetscVoidFn *)snesmonitorsolutionupdate_) {
4631cb03803SBarry Smith     *ierr = SNESMonitorSet(*snes, (PetscErrorCode(*)(SNES, PetscInt, PetscReal, void *))SNESMonitorSolutionUpdate, *(PetscViewerAndFormat **)mctx, (PetscErrorCode(*)(void **))PetscViewerAndFormatDestroy);
4648e27ec22SSatish Balay   } else {
4658434afd1SBarry Smith     *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.monitor, (PetscVoidFn *)func, mctx);
4665975b3b6SBarry Smith     if (*ierr) return;
4678434afd1SBarry Smith     *ierr = PetscObjectSetFortranCallback((PetscObject)*snes, PETSC_FORTRAN_CALLBACK_CLASS, &_cb.mondestroy, (PetscVoidFn *)mondestroy, mctx);
4685975b3b6SBarry Smith     if (*ierr) return;
469aecf964fSBarry Smith     *ierr = SNESMonitorSet(*snes, oursnesmonitor, *snes, ourmondestroy);
4708e27ec22SSatish Balay   }
4718e27ec22SSatish Balay }
4728e27ec22SSatish Balay 
47319caf8f3SSatish Balay PETSC_EXTERN void snesviewfromoptions_(SNES *ao, PetscObject obj, char *type, PetscErrorCode *ierr, PETSC_FORTRAN_CHARLEN_T len)
474fe2efc57SMark {
475fe2efc57SMark   char *t;
476fe2efc57SMark 
477fe2efc57SMark   FIXCHAR(type, len, t);
478b14c0cbaSBlaise Bourdin   CHKFORTRANNULLOBJECT(obj);
4795975b3b6SBarry Smith   *ierr = SNESViewFromOptions(*ao, obj, t);
4805975b3b6SBarry Smith   if (*ierr) return;
481fe2efc57SMark   FREECHAR(type, t);
482fe2efc57SMark }
48391f3e32bSBarry Smith 
48491f3e32bSBarry Smith PETSC_EXTERN void snesconvergedreasonview_(SNES *snes, PetscViewer *viewer, PetscErrorCode *ierr)
48591f3e32bSBarry Smith {
48691f3e32bSBarry Smith   PetscViewer v;
48791f3e32bSBarry Smith   PetscPatchDefaultViewers_Fortran(viewer, v);
48891f3e32bSBarry Smith   *ierr = SNESConvergedReasonView(*snes, v);
48991f3e32bSBarry Smith }
490c4421ceaSFande Kong 
491c4421ceaSFande Kong PETSC_EXTERN void snesgetconvergedreasonstring_(SNES *snes, char *strreason, PetscErrorCode *ierr, PETSC_FORTRAN_CHARLEN_T len)
492c4421ceaSFande Kong {
493c4421ceaSFande Kong   const char *tstrreason;
494c4421ceaSFande Kong   *ierr = SNESGetConvergedReasonString(*snes, &tstrreason);
4955975b3b6SBarry Smith   *ierr = PetscStrncpy(strreason, tstrreason, len);
4965975b3b6SBarry Smith   if (*ierr) return;
497c4421ceaSFande Kong   FIXRETURNCHAR(PETSC_TRUE, strreason, len);
498c4421ceaSFande Kong }
499