xref: /petsc/include/petscsnes.h (revision d32f9abdbc052d6e1fd06679b17a55415c3aae30)
1 /*
2     User interface for the nonlinear solvers package.
3 */
4 #if !defined(__PETSCSNES_H)
5 #define __PETSCSNES_H
6 #include "petscksp.h"
7 PETSC_EXTERN_CXX_BEGIN
8 
9 /*S
10      SNES - Abstract PETSc object that manages all nonlinear solves
11 
12    Level: beginner
13 
14   Concepts: nonlinear solvers
15 
16 .seealso:  SNESCreate(), SNESSetType(), SNESType, TS, KSP, KSP, PC
17 S*/
18 typedef struct _p_SNES* SNES;
19 
20 /*E
21     SNESType - String with the name of a PETSc SNES method or the creation function
22        with an optional dynamic library name, for example
23        http://www.mcs.anl.gov/petsc/lib.a:mysnescreate()
24 
25    Level: beginner
26 
27 .seealso: SNESSetType(), SNES
28 E*/
29 #define SNESType char*
30 #define SNESLS   "ls"
31 #define SNESTR   "tr"
32 #define SNESTEST "test"
33 
34 /* Logging support */
35 extern PetscCookie PETSCSNES_DLLEXPORT SNES_COOKIE;
36 
37 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESInitializePackage(const char[]);
38 
39 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESCreate(MPI_Comm,SNES*);
40 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESDestroy(SNES);
41 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESSetType(SNES,const SNESType);
42 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorSet(SNES,PetscErrorCode(*)(SNES,PetscInt,PetscReal,void*),void *,PetscErrorCode (*)(void*));
43 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorCancel(SNES);
44 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESSetConvergenceHistory(SNES,PetscReal[],PetscInt[],PetscInt,PetscTruth);
45 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESGetConvergenceHistory(SNES,PetscReal*[],PetscInt *[],PetscInt *);
46 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESSetUp(SNES);
47 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESSolve(SNES,Vec,Vec);
48 
49 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESAddOptionsChecker(PetscErrorCode (*)(SNES));
50 
51 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESSetUpdate(SNES, PetscErrorCode (*)(SNES, PetscInt));
52 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESDefaultUpdate(SNES, PetscInt);
53 
54 extern PetscFList SNESList;
55 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESRegisterDestroy(void);
56 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESRegisterAll(const char[]);
57 
58 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESRegister(const char[],const char[],const char[],PetscErrorCode (*)(SNES));
59 
60 /*MC
61    SNESRegisterDynamic - Adds a method to the nonlinear solver package.
62 
63    Synopsis:
64    PetscErrorCode SNESRegisterDynamic(char *name_solver,char *path,char *name_create,PetscErrorCode (*routine_create)(SNES))
65 
66    Not collective
67 
68    Input Parameters:
69 +  name_solver - name of a new user-defined solver
70 .  path - path (either absolute or relative) the library containing this solver
71 .  name_create - name of routine to create method context
72 -  routine_create - routine to create method context
73 
74    Notes:
75    SNESRegisterDynamic() may be called multiple times to add several user-defined solvers.
76 
77    If dynamic libraries are used, then the fourth input argument (routine_create)
78    is ignored.
79 
80    Environmental variables such as ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR},
81    and others of the form ${any_environmental_variable} occuring in pathname will be
82    replaced with appropriate values.
83 
84    Sample usage:
85 .vb
86    SNESRegisterDynamic("my_solver",/home/username/my_lib/lib/libg/solaris/mylib.a,
87                 "MySolverCreate",MySolverCreate);
88 .ve
89 
90    Then, your solver can be chosen with the procedural interface via
91 $     SNESSetType(snes,"my_solver")
92    or at runtime via the option
93 $     -snes_type my_solver
94 
95    Level: advanced
96 
97     Note: If your function is not being put into a shared library then use SNESRegister() instead
98 
99 .keywords: SNES, nonlinear, register
100 
101 .seealso: SNESRegisterAll(), SNESRegisterDestroy()
102 M*/
103 #if defined(PETSC_USE_DYNAMIC_LIBRARIES)
104 #define SNESRegisterDynamic(a,b,c,d) SNESRegister(a,b,c,0)
105 #else
106 #define SNESRegisterDynamic(a,b,c,d) SNESRegister(a,b,c,d)
107 #endif
108 
109 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESGetKSP(SNES,KSP*);
110 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESSetKSP(SNES,KSP);
111 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESGetSolution(SNES,Vec*);
112 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESGetSolutionUpdate(SNES,Vec*);
113 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESGetFunction(SNES,Vec*,PetscErrorCode(**)(SNES,Vec,Vec,void*),void**);
114 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESView(SNES,PetscViewer);
115 
116 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESSetOptionsPrefix(SNES,const char[]);
117 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESAppendOptionsPrefix(SNES,const char[]);
118 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESGetOptionsPrefix(SNES,const char*[]);
119 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESSetFromOptions(SNES);
120 
121 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT MatCreateSNESMF(SNES,Mat*);
122 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT MatMFFDComputeJacobian(SNES,Vec,Mat*,Mat*,MatStructure*,void*);
123 
124 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT MatDAADSetSNES(Mat,SNES);
125 
126 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESGetType(SNES,const SNESType*);
127 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorDefault(SNES,PetscInt,PetscReal,void *);
128 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorRatio(SNES,PetscInt,PetscReal,void *);
129 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorSetRatio(SNES,PetscViewerASCIIMonitor);
130 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorSolution(SNES,PetscInt,PetscReal,void *);
131 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorResidual(SNES,PetscInt,PetscReal,void *);
132 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorSolutionUpdate(SNES,PetscInt,PetscReal,void *);
133 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorDefaultShort(SNES,PetscInt,PetscReal,void *);
134 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESSetTolerances(SNES,PetscReal,PetscReal,PetscReal,PetscInt,PetscInt);
135 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESGetTolerances(SNES,PetscReal*,PetscReal*,PetscReal*,PetscInt*,PetscInt*);
136 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESSetTrustRegionTolerance(SNES,PetscReal);
137 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESGetFunctionNorm(SNES,PetscReal*);
138 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESGetIterationNumber(SNES,PetscInt*);
139 
140 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESGetNonlinearStepFailures(SNES,PetscInt*);
141 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESSetMaxNonlinearStepFailures(SNES,PetscInt);
142 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESGetMaxNonlinearStepFailures(SNES,PetscInt*);
143 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESGetNumberFunctionEvals(SNES,PetscInt*);
144 
145 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESSetLagPreconditioner(SNES,PetscInt);
146 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESGetLagPreconditioner(SNES,PetscInt*);
147 
148 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESGetLinearSolveIterations(SNES,PetscInt*);
149 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESGetLinearSolveFailures(SNES,PetscInt*);
150 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESSetMaxLinearSolveFailures(SNES,PetscInt);
151 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESGetMaxLinearSolveFailures(SNES,PetscInt*);
152 
153 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESKSPSetUseEW(SNES,PetscTruth);
154 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESKSPGetUseEW(SNES,PetscTruth*);
155 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESKSPSetParametersEW(SNES,PetscInt,PetscReal,PetscReal,PetscReal,PetscReal,PetscReal,PetscReal);
156 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESKSPGetParametersEW(SNES,PetscInt*,PetscReal*,PetscReal*,PetscReal*,PetscReal*,PetscReal*,PetscReal*);
157 
158 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorLGCreate(const char[],const char[],int,int,int,int,PetscDrawLG*);
159 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorLG(SNES,PetscInt,PetscReal,void*);
160 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESMonitorLGDestroy(PetscDrawLG);
161 
162 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESSetApplicationContext(SNES,void *);
163 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESGetApplicationContext(SNES,void **);
164 
165 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESSetFunctionDomainError(SNES);
166 /*E
167     SNESConvergedReason - reason a SNES method was said to
168          have converged or diverged
169 
170    Level: beginner
171 
172    Notes: this must match finclude/petscsnes.h
173 
174    The two most common reasons for divergence are
175 $   1) an incorrectly coded or computed Jacobian or
176 $   2) failure or lack of convergence in the linear system (in this case we recommend
177 $      testing with -pc_type lu to eliminate the linear solver as the cause of the problem).
178 
179    Diverged Reasons:
180 .    SNES_DIVERGED_LOCAL_MIN - this can only occur when using the line-search variant of SNES.
181        The line search wants to minimize Q(alpha) = 1/2 || F(x + alpha s) ||^2_2  this occurs
182        at Q'(alpha) = s^T F'(x+alpha s)^T F(x+alpha s) = 0. If s is the Newton direction - F'(x)^(-1)F(x) then
183        you get Q'(alpha) = -F(x)^T F'(x)^(-1)^T F'(x+alpha s)F(x+alpha s); when alpha = 0
184        Q'(0) = - ||F(x)||^2_2 which is always NEGATIVE if F'(x) is invertible. This means the Newton
185        direction is a descent direction and the line search should succeed if alpha is small enough.
186 
187        If F'(x) is NOT invertible AND F'(x)^T F(x) = 0 then Q'(0) = 0 and the Newton direction
188        is NOT a descent direction so the line search will fail. All one can do at this point
189        is change the initial guess and try again.
190 
191        An alternative explanation: Newton's method can be regarded as replacing the function with
192        its linear approximation and minimizing the 2-norm of that. That is F(x+s) approx F(x) + F'(x)s
193        so we minimize || F(x) + F'(x) s ||^2_2; do this using Least Squares. If F'(x) is invertible then
194        s = - F'(x)^(-1)F(x) otherwise F'(x)^T F'(x) s = -F'(x)^T F(x). If F'(x)^T F(x) is NOT zero then there
195        exists a nontrival (that is F'(x)s != 0) solution to the equation and this direction is
196        s = - [F'(x)^T F'(x)]^(-1) F'(x)^T F(x) so Q'(0) = - F(x)^T F'(x) [F'(x)^T F'(x)]^(-T) F'(x)^T F(x)
197        = - (F'(x)^T F(x)) [F'(x)^T F'(x)]^(-T) (F'(x)^T F(x)). Since we are assuming (F'(x)^T F(x)) != 0
198        and F'(x)^T F'(x) has no negative eigenvalues Q'(0) < 0 so s is a descent direction and the line
199        search should succeed for small enough alpha.
200 
201        Note that this RARELY happens in practice. Far more likely the linear system is not being solved
202        (well enough?) or the Jacobian is wrong.
203 
204 
205    Developer note: The string versions of these are in
206      src/snes/interface/snes.c called convergedreasons.
207      If these enums are changed you much change those.
208 
209 .seealso: SNESSolve(), SNESGetConvergedReason(), KSPConvergedReason, SNESSetConvergenceTest()
210 E*/
211 typedef enum {/* converged */
212               SNES_CONVERGED_FNORM_ABS         =  2, /* ||F|| < atol */
213               SNES_CONVERGED_FNORM_RELATIVE    =  3, /* ||F|| < rtol*||F_initial|| */
214               SNES_CONVERGED_PNORM_RELATIVE    =  4, /* Newton computed step size small || delta x || < tol */
215               SNES_CONVERGED_ITS               =  5, /* maximum iterations reached */
216               SNES_CONVERGED_TR_DELTA          =  7,
217               /* diverged */
218               SNES_DIVERGED_FUNCTION_DOMAIN    = -1,
219               SNES_DIVERGED_FUNCTION_COUNT     = -2,
220               SNES_DIVERGED_LINEAR_SOLVE       = -3,
221               SNES_DIVERGED_FNORM_NAN          = -4,
222               SNES_DIVERGED_MAX_IT             = -5,
223               SNES_DIVERGED_LS_FAILURE         = -6,
224               SNES_DIVERGED_LOCAL_MIN          = -8,  /* || J^T b || is small, implies converged to local minimum of F() */
225               SNES_CONVERGED_ITERATING         =  0} SNESConvergedReason;
226 extern const char **SNESConvergedReasons;
227 
228 /*MC
229      SNES_CONVERGED_FNORM_ABS - 2-norm(F) <= abstol
230 
231    Level: beginner
232 
233 .seealso:  SNESSolve(), SNESGetConvergedReason(), SNESConvergedReason, SNESSetTolerances()
234 
235 M*/
236 
237 /*MC
238      SNES_CONVERGED_FNORM_RELATIVE - 2-norm(F) <= rtol*2-norm(F(x_0)) where x_0 is the initial guess
239 
240    Level: beginner
241 
242 .seealso:  SNESSolve(), SNESGetConvergedReason(), SNESConvergedReason, SNESSetTolerances()
243 
244 M*/
245 
246 /*MC
247      SNES_CONVERGED_PNORM_RELATIVE - The 2-norm of the last step <= xtol * 2-norm(x) where x is the current
248           solution and xtol is the 4th argument to SNESSetTolerances()
249 
250    Level: beginner
251 
252 .seealso:  SNESSolve(), SNESGetConvergedReason(), SNESConvergedReason, SNESSetTolerances()
253 
254 M*/
255 
256 /*MC
257      SNES_DIVERGED_FUNCTION_COUNT - The user provided function has been called more times then the final
258          argument to SNESSetTolerances()
259 
260    Level: beginner
261 
262 .seealso:  SNESSolve(), SNESGetConvergedReason(), SNESConvergedReason, SNESSetTolerances()
263 
264 M*/
265 
266 /*MC
267      SNES_DIVERGED_FNORM_NAN - the 2-norm of the current function evaluation is not-a-number (NaN), this
268       is usually caused by a division of 0 by 0.
269 
270    Level: beginner
271 
272 .seealso:  SNESSolve(), SNESGetConvergedReason(), SNESConvergedReason, SNESSetTolerances()
273 
274 M*/
275 
276 /*MC
277      SNES_DIVERGED_MAX_IT - SNESSolve() has reached the maximum number of iterations requested
278 
279    Level: beginner
280 
281 .seealso:  SNESSolve(), SNESGetConvergedReason(), SNESConvergedReason, SNESSetTolerances()
282 
283 M*/
284 
285 /*MC
286      SNES_DIVERGED_LS_FAILURE - The line search has failed. This only occurs for a SNESType of SNESLS
287 
288    Level: beginner
289 
290 .seealso:  SNESSolve(), SNESGetConvergedReason(), SNESConvergedReason, SNESSetTolerances()
291 
292 M*/
293 
294 /*MC
295      SNES_DIVERGED_LOCAL_MIN - the algorithm seems to have stagnated at a local minimum that is not zero
296 
297    Level: beginner
298 
299 .seealso:  SNESSolve(), SNESGetConvergedReason(), SNESConvergedReason, SNESSetTolerances()
300 
301 M*/
302 
303 /*MC
304      SNES_CONERGED_ITERATING - this only occurs if SNESGetConvergedReason() is called during the SNESSolve()
305 
306    Level: beginner
307 
308 .seealso:  SNESSolve(), SNESGetConvergedReason(), SNESConvergedReason, SNESSetTolerances()
309 
310 M*/
311 
312 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESSetConvergenceTest(SNES,PetscErrorCode (*)(SNES,PetscInt,PetscReal,PetscReal,PetscReal,SNESConvergedReason*,void*),void*,PetscErrorCode (*)(void*));
313 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESDefaultConverged(SNES,PetscInt,PetscReal,PetscReal,PetscReal,SNESConvergedReason*,void*);
314 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESSkipConverged(SNES,PetscInt,PetscReal,PetscReal,PetscReal,SNESConvergedReason*,void*);
315 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESGetConvergedReason(SNES,SNESConvergedReason*);
316 
317 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESDAFormFunction(SNES,Vec,Vec,void*);
318 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESDAComputeJacobianWithAdic(SNES,Vec,Mat*,Mat*,MatStructure*,void*);
319 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESDAComputeJacobianWithAdifor(SNES,Vec,Mat*,Mat*,MatStructure*,void*);
320 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESDAComputeJacobian(SNES,Vec,Mat*,Mat*,MatStructure*,void*);
321 
322 /* --------- Solving systems of nonlinear equations --------------- */
323 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESSetFunction(SNES,Vec,PetscErrorCode(*)(SNES,Vec,Vec,void*),void *);
324 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESComputeFunction(SNES,Vec,Vec);
325 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESSetJacobian(SNES,Mat,Mat,PetscErrorCode(*)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void *);
326 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESGetJacobian(SNES,Mat*,Mat*,PetscErrorCode(**)(SNES,Vec,Mat*,Mat*,MatStructure*,void*),void **);
327 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESDefaultComputeJacobian(SNES,Vec,Mat*,Mat*,MatStructure*,void*);
328 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESDefaultComputeJacobianColor(SNES,Vec,Mat*,Mat*,MatStructure*,void*);
329 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESGetRhs(SNES,Vec*);
330 
331 /* --------- Routines specifically for line search methods --------------- */
332 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESLineSearchSet(SNES,PetscErrorCode(*)(SNES,void*,Vec,Vec,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal*,PetscReal*,PetscTruth*),void*);
333 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESLineSearchNo(SNES,void*,Vec,Vec,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal*,PetscReal*,PetscTruth*);
334 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESLineSearchNoNorms(SNES,void*,Vec,Vec,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal*,PetscReal*,PetscTruth*);
335 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESLineSearchCubic(SNES,void*,Vec,Vec,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal*,PetscReal*,PetscTruth*);
336 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESLineSearchQuadratic(SNES,void*,Vec,Vec,Vec,Vec,Vec,PetscReal,PetscReal,PetscReal*,PetscReal*,PetscTruth*);
337 
338 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESLineSearchSetPostCheck(SNES,PetscErrorCode(*)(SNES,Vec,Vec,Vec,void*,PetscTruth*,PetscTruth*),void*);
339 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESLineSearchSetPreCheck(SNES,PetscErrorCode(*)(SNES,Vec,Vec,void*,PetscTruth*),void*);
340 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESLineSearchSetParams(SNES,PetscReal,PetscReal);
341 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESLineSearchGetParams(SNES,PetscReal*,PetscReal*);
342 
343 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESTestLocalMin(SNES);
344 
345 /* Should this routine be private? */
346 EXTERN PetscErrorCode PETSCSNES_DLLEXPORT SNESComputeJacobian(SNES,Vec,Mat*,Mat*,MatStructure*);
347 
348 PETSC_EXTERN_CXX_END
349 #endif
350