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 /*J 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 J*/ 29 #define SNESType char* 30 #define SNESLS "ls" 31 #define SNESTR "tr" 32 #define SNESPYTHON "python" 33 #define SNESTEST "test" 34 #define SNESNRICHARDSON "nrichardson" 35 #define SNESKSPONLY "ksponly" 36 #define SNESVI "vi" 37 #define SNESNGMRES "ngmres" 38 #define SNESQN "qn" 39 #define SNESSHELL "shell" 40 #define SNESNCG "ncg" 41 #define SNESSORQN "sorqn" 42 #define SNESFAS "fas" 43 44 /* Logging support */ 45 extern PetscClassId SNES_CLASSID; 46 47 extern PetscErrorCode SNESInitializePackage(const char[]); 48 49 extern PetscErrorCode SNESCreate(MPI_Comm,SNES*); 50 extern PetscErrorCode SNESReset(SNES); 51 extern PetscErrorCode SNESDestroy(SNES*); 52 extern PetscErrorCode SNESSetType(SNES,const SNESType); 53 extern PetscErrorCode SNESMonitor(SNES,PetscInt,PetscReal); 54 extern PetscErrorCode SNESMonitorSet(SNES,PetscErrorCode(*)(SNES,PetscInt,PetscReal,void*),void *,PetscErrorCode (*)(void**)); 55 extern PetscErrorCode SNESMonitorCancel(SNES); 56 extern PetscErrorCode SNESSetConvergenceHistory(SNES,PetscReal[],PetscInt[],PetscInt,PetscBool ); 57 extern PetscErrorCode SNESGetConvergenceHistory(SNES,PetscReal*[],PetscInt *[],PetscInt *); 58 extern PetscErrorCode SNESSetUp(SNES); 59 extern PetscErrorCode SNESSolve(SNES,Vec,Vec); 60 extern PetscErrorCode SNESSetErrorIfNotConverged(SNES,PetscBool ); 61 extern PetscErrorCode SNESGetErrorIfNotConverged(SNES,PetscBool *); 62 63 64 extern PetscErrorCode SNESAddOptionsChecker(PetscErrorCode (*)(SNES)); 65 66 extern PetscErrorCode SNESSetUpdate(SNES, PetscErrorCode (*)(SNES, PetscInt)); 67 extern PetscErrorCode SNESDefaultUpdate(SNES, PetscInt); 68 69 extern PetscFList SNESList; 70 extern PetscErrorCode SNESRegisterDestroy(void); 71 extern PetscErrorCode SNESRegisterAll(const char[]); 72 73 extern PetscErrorCode SNESRegister(const char[],const char[],const char[],PetscErrorCode (*)(SNES)); 74 75 /*MC 76 SNESRegisterDynamic - Adds a method to the nonlinear solver package. 77 78 Synopsis: 79 PetscErrorCode SNESRegisterDynamic(const char *name_solver,const char *path,const char *name_create,PetscErrorCode (*routine_create)(SNES)) 80 81 Not collective 82 83 Input Parameters: 84 + name_solver - name of a new user-defined solver 85 . path - path (either absolute or relative) the library containing this solver 86 . name_create - name of routine to create method context 87 - routine_create - routine to create method context 88 89 Notes: 90 SNESRegisterDynamic() may be called multiple times to add several user-defined solvers. 91 92 If dynamic libraries are used, then the fourth input argument (routine_create) 93 is ignored. 94 95 Environmental variables such as ${PETSC_ARCH}, ${PETSC_DIR}, ${PETSC_LIB_DIR}, 96 and others of the form ${any_environmental_variable} occuring in pathname will be 97 replaced with appropriate values. 98 99 Sample usage: 100 .vb 101 SNESRegisterDynamic("my_solver",/home/username/my_lib/lib/libg/solaris/mylib.a, 102 "MySolverCreate",MySolverCreate); 103 .ve 104 105 Then, your solver can be chosen with the procedural interface via 106 $ SNESSetType(snes,"my_solver") 107 or at runtime via the option 108 $ -snes_type my_solver 109 110 Level: advanced 111 112 Note: If your function is not being put into a shared library then use SNESRegister() instead 113 114 .keywords: SNES, nonlinear, register 115 116 .seealso: SNESRegisterAll(), SNESRegisterDestroy() 117 M*/ 118 #if defined(PETSC_USE_DYNAMIC_LIBRARIES) 119 #define SNESRegisterDynamic(a,b,c,d) SNESRegister(a,b,c,0) 120 #else 121 #define SNESRegisterDynamic(a,b,c,d) SNESRegister(a,b,c,d) 122 #endif 123 124 extern PetscErrorCode SNESGetKSP(SNES,KSP*); 125 extern PetscErrorCode SNESSetKSP(SNES,KSP); 126 extern PetscErrorCode SNESGetSolution(SNES,Vec*); 127 extern PetscErrorCode SNESGetSolutionUpdate(SNES,Vec*); 128 extern PetscErrorCode SNESGetRhs(SNES,Vec*); 129 extern PetscErrorCode SNESView(SNES,PetscViewer); 130 131 extern PetscErrorCode SNESSetOptionsPrefix(SNES,const char[]); 132 extern PetscErrorCode SNESAppendOptionsPrefix(SNES,const char[]); 133 extern PetscErrorCode SNESGetOptionsPrefix(SNES,const char*[]); 134 extern PetscErrorCode SNESSetFromOptions(SNES); 135 extern PetscErrorCode SNESDefaultGetWork(SNES,PetscInt); 136 137 extern PetscErrorCode MatCreateSNESMF(SNES,Mat*); 138 extern PetscErrorCode MatMFFDComputeJacobian(SNES,Vec,Mat*,Mat*,MatStructure*,void*); 139 140 extern PetscErrorCode MatDAADSetSNES(Mat,SNES); 141 142 extern PetscErrorCode SNESGetType(SNES,const SNESType*); 143 extern PetscErrorCode SNESMonitorDefault(SNES,PetscInt,PetscReal,void *); 144 extern PetscErrorCode SNESMonitorRange(SNES,PetscInt,PetscReal,void *); 145 extern PetscErrorCode SNESMonitorRatio(SNES,PetscInt,PetscReal,void *); 146 extern PetscErrorCode SNESMonitorSetRatio(SNES,PetscViewer); 147 extern PetscErrorCode SNESMonitorSolution(SNES,PetscInt,PetscReal,void *); 148 extern PetscErrorCode SNESMonitorResidual(SNES,PetscInt,PetscReal,void *); 149 extern PetscErrorCode SNESMonitorSolutionUpdate(SNES,PetscInt,PetscReal,void *); 150 extern PetscErrorCode SNESMonitorDefaultShort(SNES,PetscInt,PetscReal,void *); 151 extern PetscErrorCode SNESSetTolerances(SNES,PetscReal,PetscReal,PetscReal,PetscInt,PetscInt); 152 extern PetscErrorCode SNESGetTolerances(SNES,PetscReal*,PetscReal*,PetscReal*,PetscInt*,PetscInt*); 153 extern PetscErrorCode SNESSetTrustRegionTolerance(SNES,PetscReal); 154 extern PetscErrorCode SNESGetFunctionNorm(SNES,PetscReal*); 155 extern PetscErrorCode SNESGetIterationNumber(SNES,PetscInt*); 156 157 extern PetscErrorCode SNESGetNonlinearStepFailures(SNES,PetscInt*); 158 extern PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES,PetscInt); 159 extern PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES,PetscInt*); 160 extern PetscErrorCode SNESGetNumberFunctionEvals(SNES,PetscInt*); 161 162 extern PetscErrorCode SNESSetLagPreconditioner(SNES,PetscInt); 163 extern PetscErrorCode SNESGetLagPreconditioner(SNES,PetscInt*); 164 extern PetscErrorCode SNESSetLagJacobian(SNES,PetscInt); 165 extern PetscErrorCode SNESGetLagJacobian(SNES,PetscInt*); 166 extern PetscErrorCode SNESSetGridSequence(SNES,PetscInt); 167 168 extern PetscErrorCode SNESGetLinearSolveIterations(SNES,PetscInt*); 169 extern PetscErrorCode SNESGetLinearSolveFailures(SNES,PetscInt*); 170 extern PetscErrorCode SNESSetMaxLinearSolveFailures(SNES,PetscInt); 171 extern PetscErrorCode SNESGetMaxLinearSolveFailures(SNES,PetscInt*); 172 173 extern PetscErrorCode SNESKSPSetUseEW(SNES,PetscBool ); 174 extern PetscErrorCode SNESKSPGetUseEW(SNES,PetscBool *); 175 extern PetscErrorCode SNESKSPSetParametersEW(SNES,PetscInt,PetscReal,PetscReal,PetscReal,PetscReal,PetscReal,PetscReal); 176 extern PetscErrorCode SNESKSPGetParametersEW(SNES,PetscInt*,PetscReal*,PetscReal*,PetscReal*,PetscReal*,PetscReal*,PetscReal*); 177 178 extern PetscErrorCode SNESMonitorLGCreate(const char[],const char[],int,int,int,int,PetscDrawLG*); 179 extern PetscErrorCode SNESMonitorLG(SNES,PetscInt,PetscReal,void*); 180 extern PetscErrorCode SNESMonitorLGDestroy(PetscDrawLG*); 181 extern PetscErrorCode SNESMonitorLGRangeCreate(const char[],const char[],int,int,int,int,PetscDrawLG*); 182 extern PetscErrorCode SNESMonitorLGRange(SNES,PetscInt,PetscReal,void*); 183 extern PetscErrorCode SNESMonitorLGRangeDestroy(PetscDrawLG*); 184 185 extern PetscErrorCode SNESSetApplicationContext(SNES,void *); 186 extern PetscErrorCode SNESGetApplicationContext(SNES,void *); 187 extern PetscErrorCode SNESSetComputeApplicationContext(SNES,PetscErrorCode (*)(SNES,void**),PetscErrorCode (*)(void**)); 188 189 extern PetscErrorCode SNESPythonSetType(SNES,const char[]); 190 191 extern PetscErrorCode SNESSetFunctionDomainError(SNES); 192 /*E 193 SNESConvergedReason - reason a SNES method was said to 194 have converged or diverged 195 196 Level: beginner 197 198 The two most common reasons for divergence are 199 $ 1) an incorrectly coded or computed Jacobian or 200 $ 2) failure or lack of convergence in the linear system (in this case we recommend 201 $ testing with -pc_type lu to eliminate the linear solver as the cause of the problem). 202 203 Diverged Reasons: 204 . SNES_DIVERGED_LOCAL_MIN - this can only occur when using the line-search variant of SNES. 205 The line search wants to minimize Q(alpha) = 1/2 || F(x + alpha s) ||^2_2 this occurs 206 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 207 you get Q'(alpha) = -F(x)^T F'(x)^(-1)^T F'(x+alpha s)F(x+alpha s); when alpha = 0 208 Q'(0) = - ||F(x)||^2_2 which is always NEGATIVE if F'(x) is invertible. This means the Newton 209 direction is a descent direction and the line search should succeed if alpha is small enough. 210 211 If F'(x) is NOT invertible AND F'(x)^T F(x) = 0 then Q'(0) = 0 and the Newton direction 212 is NOT a descent direction so the line search will fail. All one can do at this point 213 is change the initial guess and try again. 214 215 An alternative explanation: Newton's method can be regarded as replacing the function with 216 its linear approximation and minimizing the 2-norm of that. That is F(x+s) approx F(x) + F'(x)s 217 so we minimize || F(x) + F'(x) s ||^2_2; do this using Least Squares. If F'(x) is invertible then 218 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 219 exists a nontrival (that is F'(x)s != 0) solution to the equation and this direction is 220 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) 221 = - (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 222 and F'(x)^T F'(x) has no negative eigenvalues Q'(0) < 0 so s is a descent direction and the line 223 search should succeed for small enough alpha. 224 225 Note that this RARELY happens in practice. Far more likely the linear system is not being solved 226 (well enough?) or the Jacobian is wrong. 227 228 SNES_DIVERGED_MAX_IT means that the solver reached the maximum number of iterations without satisfying any 229 convergence criteria. SNES_CONVERGED_ITS means that SNESSkipConverged() was chosen as the convergence test; 230 thus the usual convergence criteria have not been checked and may or may not be satisfied. 231 232 Developer Notes: this must match finclude/petscsnes.h 233 234 The string versions of these are in SNESConvergedReason, if you change any value here you must 235 also adjust that array. 236 237 Each reason has its own manual page. 238 239 .seealso: SNESSolve(), SNESGetConvergedReason(), KSPConvergedReason, SNESSetConvergenceTest() 240 E*/ 241 typedef enum {/* converged */ 242 SNES_CONVERGED_FNORM_ABS = 2, /* ||F|| < atol */ 243 SNES_CONVERGED_FNORM_RELATIVE = 3, /* ||F|| < rtol*||F_initial|| */ 244 SNES_CONVERGED_PNORM_RELATIVE = 4, /* Newton computed step size small; || delta x || < stol */ 245 SNES_CONVERGED_ITS = 5, /* maximum iterations reached */ 246 SNES_CONVERGED_TR_DELTA = 7, 247 /* diverged */ 248 SNES_DIVERGED_FUNCTION_DOMAIN = -1, /* the new x location passed the function is not in the domain of F */ 249 SNES_DIVERGED_FUNCTION_COUNT = -2, 250 SNES_DIVERGED_LINEAR_SOLVE = -3, /* the linear solve failed */ 251 SNES_DIVERGED_FNORM_NAN = -4, 252 SNES_DIVERGED_MAX_IT = -5, 253 SNES_DIVERGED_LINE_SEARCH = -6, /* the line search failed */ 254 SNES_DIVERGED_INNER = -7, /* inner solve failed */ 255 SNES_DIVERGED_LOCAL_MIN = -8, /* || J^T b || is small, implies converged to local minimum of F() */ 256 SNES_CONVERGED_ITERATING = 0} SNESConvergedReason; 257 extern const char *const*SNESConvergedReasons; 258 259 /*MC 260 SNES_CONVERGED_FNORM_ABS - 2-norm(F) <= abstol 261 262 Level: beginner 263 264 .seealso: SNESSolve(), SNESGetConvergedReason(), SNESConvergedReason, SNESSetTolerances() 265 266 M*/ 267 268 /*MC 269 SNES_CONVERGED_FNORM_RELATIVE - 2-norm(F) <= rtol*2-norm(F(x_0)) where x_0 is the initial guess 270 271 Level: beginner 272 273 .seealso: SNESSolve(), SNESGetConvergedReason(), SNESConvergedReason, SNESSetTolerances() 274 275 M*/ 276 277 /*MC 278 SNES_CONVERGED_PNORM_RELATIVE - The 2-norm of the last step <= stol * 2-norm(x) where x is the current 279 solution and stol is the 4th argument to SNESSetTolerances() 280 281 Level: beginner 282 283 .seealso: SNESSolve(), SNESGetConvergedReason(), SNESConvergedReason, SNESSetTolerances() 284 285 M*/ 286 287 /*MC 288 SNES_DIVERGED_FUNCTION_COUNT - The user provided function has been called more times then the final 289 argument to SNESSetTolerances() 290 291 Level: beginner 292 293 .seealso: SNESSolve(), SNESGetConvergedReason(), SNESConvergedReason, SNESSetTolerances() 294 295 M*/ 296 297 /*MC 298 SNES_DIVERGED_FNORM_NAN - the 2-norm of the current function evaluation is not-a-number (NaN), this 299 is usually caused by a division of 0 by 0. 300 301 Level: beginner 302 303 .seealso: SNESSolve(), SNESGetConvergedReason(), SNESConvergedReason, SNESSetTolerances() 304 305 M*/ 306 307 /*MC 308 SNES_DIVERGED_MAX_IT - SNESSolve() has reached the maximum number of iterations requested 309 310 Level: beginner 311 312 .seealso: SNESSolve(), SNESGetConvergedReason(), SNESConvergedReason, SNESSetTolerances() 313 314 M*/ 315 316 /*MC 317 SNES_DIVERGED_LINE_SEARCH - The line search has failed. This only occurs for a SNESType of SNESLS 318 319 Level: beginner 320 321 .seealso: SNESSolve(), SNESGetConvergedReason(), SNESConvergedReason, SNESSetTolerances() 322 323 M*/ 324 325 /*MC 326 SNES_DIVERGED_LOCAL_MIN - the algorithm seems to have stagnated at a local minimum that is not zero. 327 See the manual page for SNESConvergedReason for more details 328 329 Level: beginner 330 331 .seealso: SNESSolve(), SNESGetConvergedReason(), SNESConvergedReason, SNESSetTolerances() 332 333 M*/ 334 335 /*MC 336 SNES_CONERGED_ITERATING - this only occurs if SNESGetConvergedReason() is called during the SNESSolve() 337 338 Level: beginner 339 340 .seealso: SNESSolve(), SNESGetConvergedReason(), SNESConvergedReason, SNESSetTolerances() 341 342 M*/ 343 344 extern PetscErrorCode SNESSetConvergenceTest(SNES,PetscErrorCode (*)(SNES,PetscInt,PetscReal,PetscReal,PetscReal,SNESConvergedReason*,void*),void*,PetscErrorCode (*)(void*)); 345 extern PetscErrorCode SNESDefaultConverged(SNES,PetscInt,PetscReal,PetscReal,PetscReal,SNESConvergedReason*,void*); 346 extern PetscErrorCode SNESSkipConverged(SNES,PetscInt,PetscReal,PetscReal,PetscReal,SNESConvergedReason*,void*); 347 extern PetscErrorCode SNESGetConvergedReason(SNES,SNESConvergedReason*); 348 349 extern PetscErrorCode SNESDAFormFunction(SNES,Vec,Vec,void*); 350 extern PetscErrorCode SNESDAComputeJacobianWithAdic(SNES,Vec,Mat*,Mat*,MatStructure*,void*); 351 extern PetscErrorCode SNESDAComputeJacobianWithAdifor(SNES,Vec,Mat*,Mat*,MatStructure*,void*); 352 extern PetscErrorCode SNESDAComputeJacobian(SNES,Vec,Mat*,Mat*,MatStructure*,void*); 353 354 extern PetscErrorCode SNESMeshFormFunction(SNES,Vec,Vec,void*); 355 extern PetscErrorCode SNESMeshFormJacobian(SNES,Vec,Mat*,Mat*,MatStructure*,void*); 356 357 /* --------- Solving systems of nonlinear equations --------------- */ 358 typedef PetscErrorCode (*SNESFunction)(SNES,Vec,Vec,void*); 359 typedef PetscErrorCode (*SNESJacobian)(SNES,Vec,Mat*,Mat*,MatStructure*,void*); 360 extern PetscErrorCode SNESSetFunction(SNES,Vec,SNESFunction,void*); 361 extern PetscErrorCode SNESGetFunction(SNES,Vec*,SNESFunction*,void**); 362 extern PetscErrorCode SNESComputeFunction(SNES,Vec,Vec); 363 extern PetscErrorCode SNESSetJacobian(SNES,Mat,Mat,SNESJacobian,void*); 364 extern PetscErrorCode SNESGetJacobian(SNES,Mat*,Mat*,SNESJacobian*,void**); 365 extern PetscErrorCode SNESDefaultComputeJacobian(SNES,Vec,Mat*,Mat*,MatStructure*,void*); 366 extern PetscErrorCode SNESDefaultComputeJacobianColor(SNES,Vec,Mat*,Mat*,MatStructure*,void*); 367 extern PetscErrorCode SNESSetComputeInitialGuess(SNES,PetscErrorCode (*)(SNES,Vec,void*),void*); 368 369 /* --------- Routines specifically for line search methods --------------- */ 370 /*E 371 SNESLineSearchType - type of line search used in Newton's method as well as VI solvers and Richardson solvers 372 373 Level: beginner 374 375 .seealso: SNESSetFromOptions(), SNESLineSearchSet() 376 E*/ 377 typedef enum {SNES_LS_BASIC, SNES_LS_BASIC_NONORMS, SNES_LS_QUADRATIC, SNES_LS_CUBIC} SNESLineSearchType; 378 extern const char *const SNESLineSearchTypes[]; 379 extern const char *SNESLineSearchTypeName(SNESLineSearchType); /* Does bounds checking, use this for viewing */ 380 381 extern PetscErrorCode SNESLineSearchSet(SNES,PetscErrorCode(*)(SNES,void*,Vec,Vec,Vec,PetscReal,PetscReal,Vec,Vec,PetscReal*,PetscReal*,PetscBool *),void*); 382 extern PetscErrorCode SNESLineSearchNo(SNES,void*,Vec,Vec,Vec,PetscReal,PetscReal,Vec,Vec,PetscReal*,PetscReal*,PetscBool *); 383 extern PetscErrorCode SNESLineSearchNoNorms(SNES,void*,Vec,Vec,Vec,PetscReal,PetscReal,Vec,Vec,PetscReal*,PetscReal*,PetscBool *); 384 extern PetscErrorCode SNESLineSearchCubic(SNES,void*,Vec,Vec,Vec,PetscReal,PetscReal,Vec,Vec,PetscReal*,PetscReal*,PetscBool *); 385 extern PetscErrorCode SNESLineSearchQuadratic(SNES,void*,Vec,Vec,Vec,PetscReal,PetscReal,Vec,Vec,PetscReal*,PetscReal*,PetscBool *); 386 387 extern PetscErrorCode SNESLineSearchSetPostCheck(SNES,PetscErrorCode(*)(SNES,Vec,Vec,Vec,void*,PetscBool *,PetscBool *),void*); 388 extern PetscErrorCode SNESLineSearchSetPreCheck(SNES,PetscErrorCode(*)(SNES,Vec,Vec,void*,PetscBool *),void*); 389 extern PetscErrorCode SNESLineSearchSetParams(SNES,PetscReal,PetscReal,PetscReal); 390 extern PetscErrorCode SNESLineSearchGetParams(SNES,PetscReal*,PetscReal*,PetscReal*); 391 extern PetscErrorCode SNESLineSearchSetMonitor(SNES,PetscBool ); 392 393 extern PetscErrorCode SNESShellGetContext(SNES,void**); 394 extern PetscErrorCode SNESShellSetContext(SNES,void*); 395 extern PetscErrorCode SNESShellSetSolve(SNES,PetscErrorCode (*)(SNES,Vec)); 396 397 /* Routines for VI solver */ 398 extern PetscErrorCode SNESVISetVariableBounds(SNES,Vec,Vec); 399 extern PetscErrorCode SNESVISetComputeVariableBounds(SNES, PetscErrorCode (*)(SNES,Vec,Vec)); 400 extern PetscErrorCode SNESVIGetInactiveSet(SNES,IS*); 401 extern PetscErrorCode SNESVISetRedundancyCheck(SNES,PetscErrorCode(*)(SNES,IS,IS*,void*),void*); 402 #define SNES_VI_INF 1.0e20 403 #define SNES_VI_NINF -1.0e20 404 405 extern PetscErrorCode SNESTestLocalMin(SNES); 406 407 /* Should this routine be private? */ 408 extern PetscErrorCode SNESComputeJacobian(SNES,Vec,Mat*,Mat*,MatStructure*); 409 410 extern PetscErrorCode SNESSetDM(SNES,DM); 411 extern PetscErrorCode SNESGetDM(SNES,DM*); 412 extern PetscErrorCode SNESSetPC(SNES,SNES); 413 extern PetscErrorCode SNESGetPC(SNES,SNES*); 414 415 /* Routines for Multiblock solver */ 416 PetscErrorCode SNESMultiblockSetFields(SNES, const char [], PetscInt, const PetscInt *); 417 PetscErrorCode SNESMultiblockSetIS(SNES, const char [], IS); 418 PetscErrorCode SNESMultiblockSetBlockSize(SNES, PetscInt); 419 PetscErrorCode SNESMultiblockSetType(SNES, PCCompositeType); 420 421 PETSC_EXTERN_CXX_END 422 #endif 423