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