1 #include <petsc/private/snesimpl.h> /*I "petscsnes.h" I*/ 2 #include <petscdmshell.h> 3 #include <petscdraw.h> 4 #include <petscds.h> 5 #include <petscdmadaptor.h> 6 #include <petscconvest.h> 7 8 PetscBool SNESRegisterAllCalled = PETSC_FALSE; 9 PetscFunctionList SNESList = NULL; 10 11 /* Logging support */ 12 PetscClassId SNES_CLASSID, DMSNES_CLASSID; 13 PetscLogEvent SNES_Solve, SNES_FunctionEval, SNES_JacobianEval, SNES_NGSEval, SNES_NGSFuncEval, SNES_NPCSolve, SNES_ObjectiveEval; 14 15 /*@ 16 SNESSetErrorIfNotConverged - Causes SNESSolve() to generate an error if the solver has not converged. 17 18 Logically Collective on SNES 19 20 Input Parameters: 21 + snes - iterative context obtained from SNESCreate() 22 - flg - PETSC_TRUE indicates you want the error generated 23 24 Options database keys: 25 . -snes_error_if_not_converged : this takes an optional truth value (0/1/no/yes/true/false) 26 27 Level: intermediate 28 29 Notes: 30 Normally PETSc continues if a linear solver fails to converge, you can call SNESGetConvergedReason() after a SNESSolve() 31 to determine if it has converged. 32 33 .keywords: SNES, set, initial guess, nonzero 34 35 .seealso: SNESGetErrorIfNotConverged(), KSPGetErrorIfNotConverged(), KSPSetErrorIFNotConverged() 36 @*/ 37 PetscErrorCode SNESSetErrorIfNotConverged(SNES snes,PetscBool flg) 38 { 39 PetscFunctionBegin; 40 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 41 PetscValidLogicalCollectiveBool(snes,flg,2); 42 snes->errorifnotconverged = flg; 43 PetscFunctionReturn(0); 44 } 45 46 /*@ 47 SNESGetErrorIfNotConverged - Will SNESSolve() generate an error if the solver does not converge? 48 49 Not Collective 50 51 Input Parameter: 52 . snes - iterative context obtained from SNESCreate() 53 54 Output Parameter: 55 . flag - PETSC_TRUE if it will generate an error, else PETSC_FALSE 56 57 Level: intermediate 58 59 .keywords: SNES, set, initial guess, nonzero 60 61 .seealso: SNESSetErrorIfNotConverged(), KSPGetErrorIfNotConverged(), KSPSetErrorIFNotConverged() 62 @*/ 63 PetscErrorCode SNESGetErrorIfNotConverged(SNES snes,PetscBool *flag) 64 { 65 PetscFunctionBegin; 66 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 67 PetscValidPointer(flag,2); 68 *flag = snes->errorifnotconverged; 69 PetscFunctionReturn(0); 70 } 71 72 /*@ 73 SNESSetAlwaysComputesFinalResidual - does the SNES always compute the residual at the final solution? 74 75 Logically Collective on SNES 76 77 Input Parameters: 78 + snes - the shell SNES 79 - flg - is the residual computed? 80 81 Level: advanced 82 83 .seealso: SNESGetAlwaysComputesFinalResidual() 84 @*/ 85 PetscErrorCode SNESSetAlwaysComputesFinalResidual(SNES snes, PetscBool flg) 86 { 87 PetscFunctionBegin; 88 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 89 snes->alwayscomputesfinalresidual = flg; 90 PetscFunctionReturn(0); 91 } 92 93 /*@ 94 SNESGetAlwaysComputesFinalResidual - does the SNES always compute the residual at the final solution? 95 96 Logically Collective on SNES 97 98 Input Parameter: 99 . snes - the shell SNES 100 101 Output Parameter: 102 . flg - is the residual computed? 103 104 Level: advanced 105 106 .seealso: SNESSetAlwaysComputesFinalResidual() 107 @*/ 108 PetscErrorCode SNESGetAlwaysComputesFinalResidual(SNES snes, PetscBool *flg) 109 { 110 PetscFunctionBegin; 111 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 112 *flg = snes->alwayscomputesfinalresidual; 113 PetscFunctionReturn(0); 114 } 115 116 /*@ 117 SNESSetFunctionDomainError - tells SNES that the input vector to your SNESFunction is not 118 in the functions domain. For example, negative pressure. 119 120 Logically Collective on SNES 121 122 Input Parameters: 123 . snes - the SNES context 124 125 Level: advanced 126 127 .keywords: SNES, view 128 129 .seealso: SNESCreate(), SNESSetFunction(), SNESFunction 130 @*/ 131 PetscErrorCode SNESSetFunctionDomainError(SNES snes) 132 { 133 PetscFunctionBegin; 134 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 135 if (snes->errorifnotconverged) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"User code indicates input vector is not in the function domain"); 136 snes->domainerror = PETSC_TRUE; 137 PetscFunctionReturn(0); 138 } 139 140 /*@ 141 SNESSetJacobianDomainError - tells SNES that computeJacobian does not make sense any more. For example there is a negative element transformation. 142 143 Logically Collective on SNES 144 145 Input Parameters: 146 . snes - the SNES context 147 148 Level: advanced 149 150 .keywords: SNES, view 151 152 .seealso: SNESCreate(), SNESSetFunction(), SNESFunction(), SNESSetFunctionDomainError() 153 @*/ 154 PetscErrorCode SNESSetJacobianDomainError(SNES snes) 155 { 156 PetscFunctionBegin; 157 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 158 if (snes->errorifnotconverged) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"User code indicates computeJacobian does not make sense"); 159 snes->jacobiandomainerror = PETSC_TRUE; 160 PetscFunctionReturn(0); 161 } 162 163 /*@ 164 SNESGetFunctionDomainError - Gets the status of the domain error after a call to SNESComputeFunction; 165 166 Logically Collective on SNES 167 168 Input Parameters: 169 . snes - the SNES context 170 171 Output Parameters: 172 . domainerror - Set to PETSC_TRUE if there's a domain error; PETSC_FALSE otherwise. 173 174 Level: advanced 175 176 .keywords: SNES, view 177 178 .seealso: SNESSetFunctionDomainError(), SNESComputeFunction() 179 @*/ 180 PetscErrorCode SNESGetFunctionDomainError(SNES snes, PetscBool *domainerror) 181 { 182 PetscFunctionBegin; 183 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 184 PetscValidPointer(domainerror, 2); 185 *domainerror = snes->domainerror; 186 PetscFunctionReturn(0); 187 } 188 189 /*@ 190 SNESGetJacobianDomainError - Gets the status of the Jacobian domain error after a call to SNESComputeJacobian; 191 192 Logically Collective on SNES 193 194 Input Parameters: 195 . snes - the SNES context 196 197 Output Parameters: 198 . domainerror - Set to PETSC_TRUE if there's a jacobian domain error; PETSC_FALSE otherwise. 199 200 Level: advanced 201 202 .keywords: SNES, view 203 204 .seealso: SNESSetFunctionDomainError(), SNESComputeFunction(),SNESGetFunctionDomainError() 205 @*/ 206 PetscErrorCode SNESGetJacobianDomainError(SNES snes, PetscBool *domainerror) 207 { 208 PetscFunctionBegin; 209 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 210 PetscValidPointer(domainerror, 2); 211 *domainerror = snes->jacobiandomainerror; 212 PetscFunctionReturn(0); 213 } 214 215 /*@C 216 SNESLoad - Loads a SNES that has been stored in binary with SNESView(). 217 218 Collective on PetscViewer 219 220 Input Parameters: 221 + newdm - the newly loaded SNES, this needs to have been created with SNESCreate() or 222 some related function before a call to SNESLoad(). 223 - viewer - binary file viewer, obtained from PetscViewerBinaryOpen() 224 225 Level: intermediate 226 227 Notes: 228 The type is determined by the data in the file, any type set into the SNES before this call is ignored. 229 230 Notes for advanced users: 231 Most users should not need to know the details of the binary storage 232 format, since SNESLoad() and TSView() completely hide these details. 233 But for anyone who's interested, the standard binary matrix storage 234 format is 235 .vb 236 has not yet been determined 237 .ve 238 239 .seealso: PetscViewerBinaryOpen(), SNESView(), MatLoad(), VecLoad() 240 @*/ 241 PetscErrorCode SNESLoad(SNES snes, PetscViewer viewer) 242 { 243 PetscErrorCode ierr; 244 PetscBool isbinary; 245 PetscInt classid; 246 char type[256]; 247 KSP ksp; 248 DM dm; 249 DMSNES dmsnes; 250 251 PetscFunctionBegin; 252 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 253 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 254 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 255 if (!isbinary) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Invalid viewer; open viewer with PetscViewerBinaryOpen()"); 256 257 ierr = PetscViewerBinaryRead(viewer,&classid,1,NULL,PETSC_INT);CHKERRQ(ierr); 258 if (classid != SNES_FILE_CLASSID) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_WRONG,"Not SNES next in file"); 259 ierr = PetscViewerBinaryRead(viewer,type,256,NULL,PETSC_CHAR);CHKERRQ(ierr); 260 ierr = SNESSetType(snes, type);CHKERRQ(ierr); 261 if (snes->ops->load) { 262 ierr = (*snes->ops->load)(snes,viewer);CHKERRQ(ierr); 263 } 264 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 265 ierr = DMGetDMSNES(dm,&dmsnes);CHKERRQ(ierr); 266 ierr = DMSNESLoad(dmsnes,viewer);CHKERRQ(ierr); 267 ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr); 268 ierr = KSPLoad(ksp,viewer);CHKERRQ(ierr); 269 PetscFunctionReturn(0); 270 } 271 272 #include <petscdraw.h> 273 #if defined(PETSC_HAVE_SAWS) 274 #include <petscviewersaws.h> 275 #endif 276 277 /*@C 278 SNESView - Prints the SNES data structure. 279 280 Collective on SNES 281 282 Input Parameters: 283 + SNES - the SNES context 284 - viewer - visualization context 285 286 Options Database Key: 287 . -snes_view - Calls SNESView() at end of SNESSolve() 288 289 Notes: 290 The available visualization contexts include 291 + PETSC_VIEWER_STDOUT_SELF - standard output (default) 292 - PETSC_VIEWER_STDOUT_WORLD - synchronized standard 293 output where only the first processor opens 294 the file. All other processors send their 295 data to the first processor to print. 296 297 The user can open an alternative visualization context with 298 PetscViewerASCIIOpen() - output to a specified file. 299 300 Level: beginner 301 302 .keywords: SNES, view 303 304 .seealso: PetscViewerASCIIOpen() 305 @*/ 306 PetscErrorCode SNESView(SNES snes,PetscViewer viewer) 307 { 308 SNESKSPEW *kctx; 309 PetscErrorCode ierr; 310 KSP ksp; 311 SNESLineSearch linesearch; 312 PetscBool iascii,isstring,isbinary,isdraw; 313 DMSNES dmsnes; 314 #if defined(PETSC_HAVE_SAWS) 315 PetscBool issaws; 316 #endif 317 318 PetscFunctionBegin; 319 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 320 if (!viewer) { 321 ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes),&viewer);CHKERRQ(ierr); 322 } 323 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2); 324 PetscCheckSameComm(snes,1,viewer,2); 325 326 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr); 327 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSTRING,&isstring);CHKERRQ(ierr); 328 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERBINARY,&isbinary);CHKERRQ(ierr); 329 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERDRAW,&isdraw);CHKERRQ(ierr); 330 #if defined(PETSC_HAVE_SAWS) 331 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERSAWS,&issaws);CHKERRQ(ierr); 332 #endif 333 if (iascii) { 334 SNESNormSchedule normschedule; 335 DM dm; 336 PetscErrorCode (*cJ)(SNES,Vec,Mat,Mat,void*); 337 void *ctx; 338 339 ierr = PetscObjectPrintClassNamePrefixType((PetscObject)snes,viewer);CHKERRQ(ierr); 340 if (!snes->setupcalled) { 341 ierr = PetscViewerASCIIPrintf(viewer," SNES has not been set up so information may be incomplete\n");CHKERRQ(ierr); 342 } 343 if (snes->ops->view) { 344 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 345 ierr = (*snes->ops->view)(snes,viewer);CHKERRQ(ierr); 346 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 347 } 348 ierr = PetscViewerASCIIPrintf(viewer," maximum iterations=%D, maximum function evaluations=%D\n",snes->max_its,snes->max_funcs);CHKERRQ(ierr); 349 ierr = PetscViewerASCIIPrintf(viewer," tolerances: relative=%g, absolute=%g, solution=%g\n",(double)snes->rtol,(double)snes->abstol,(double)snes->stol);CHKERRQ(ierr); 350 if (snes->usesksp) { 351 ierr = PetscViewerASCIIPrintf(viewer," total number of linear solver iterations=%D\n",snes->linear_its);CHKERRQ(ierr); 352 } 353 ierr = PetscViewerASCIIPrintf(viewer," total number of function evaluations=%D\n",snes->nfuncs);CHKERRQ(ierr); 354 ierr = SNESGetNormSchedule(snes, &normschedule);CHKERRQ(ierr); 355 if (normschedule > 0) {ierr = PetscViewerASCIIPrintf(viewer," norm schedule %s\n",SNESNormSchedules[normschedule]);CHKERRQ(ierr);} 356 if (snes->gridsequence) { 357 ierr = PetscViewerASCIIPrintf(viewer," total number of grid sequence refinements=%D\n",snes->gridsequence);CHKERRQ(ierr); 358 } 359 if (snes->ksp_ewconv) { 360 kctx = (SNESKSPEW*)snes->kspconvctx; 361 if (kctx) { 362 ierr = PetscViewerASCIIPrintf(viewer," Eisenstat-Walker computation of KSP relative tolerance (version %D)\n",kctx->version);CHKERRQ(ierr); 363 ierr = PetscViewerASCIIPrintf(viewer," rtol_0=%g, rtol_max=%g, threshold=%g\n",(double)kctx->rtol_0,(double)kctx->rtol_max,(double)kctx->threshold);CHKERRQ(ierr); 364 ierr = PetscViewerASCIIPrintf(viewer," gamma=%g, alpha=%g, alpha2=%g\n",(double)kctx->gamma,(double)kctx->alpha,(double)kctx->alpha2);CHKERRQ(ierr); 365 } 366 } 367 if (snes->lagpreconditioner == -1) { 368 ierr = PetscViewerASCIIPrintf(viewer," Preconditioned is never rebuilt\n");CHKERRQ(ierr); 369 } else if (snes->lagpreconditioner > 1) { 370 ierr = PetscViewerASCIIPrintf(viewer," Preconditioned is rebuilt every %D new Jacobians\n",snes->lagpreconditioner);CHKERRQ(ierr); 371 } 372 if (snes->lagjacobian == -1) { 373 ierr = PetscViewerASCIIPrintf(viewer," Jacobian is never rebuilt\n");CHKERRQ(ierr); 374 } else if (snes->lagjacobian > 1) { 375 ierr = PetscViewerASCIIPrintf(viewer," Jacobian is rebuilt every %D SNES iterations\n",snes->lagjacobian);CHKERRQ(ierr); 376 } 377 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 378 ierr = DMSNESGetJacobian(dm,&cJ,&ctx);CHKERRQ(ierr); 379 if (cJ == SNESComputeJacobianDefault) { 380 ierr = PetscViewerASCIIPrintf(viewer," Jacobian is built using finite differences one column at a time\n");CHKERRQ(ierr); 381 } else if (cJ == SNESComputeJacobianDefaultColor) { 382 ierr = PetscViewerASCIIPrintf(viewer," Jacobian is built using finite differences with coloring\n");CHKERRQ(ierr); 383 } 384 } else if (isstring) { 385 const char *type; 386 ierr = SNESGetType(snes,&type);CHKERRQ(ierr); 387 ierr = PetscViewerStringSPrintf(viewer," %-3.3s",type);CHKERRQ(ierr); 388 } else if (isbinary) { 389 PetscInt classid = SNES_FILE_CLASSID; 390 MPI_Comm comm; 391 PetscMPIInt rank; 392 char type[256]; 393 394 ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr); 395 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 396 if (!rank) { 397 ierr = PetscViewerBinaryWrite(viewer,&classid,1,PETSC_INT,PETSC_FALSE);CHKERRQ(ierr); 398 ierr = PetscStrncpy(type,((PetscObject)snes)->type_name,sizeof(type));CHKERRQ(ierr); 399 ierr = PetscViewerBinaryWrite(viewer,type,sizeof(type),PETSC_CHAR,PETSC_FALSE);CHKERRQ(ierr); 400 } 401 if (snes->ops->view) { 402 ierr = (*snes->ops->view)(snes,viewer);CHKERRQ(ierr); 403 } 404 } else if (isdraw) { 405 PetscDraw draw; 406 char str[36]; 407 PetscReal x,y,bottom,h; 408 409 ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 410 ierr = PetscDrawGetCurrentPoint(draw,&x,&y);CHKERRQ(ierr); 411 ierr = PetscStrncpy(str,"SNES: ",sizeof(str));CHKERRQ(ierr); 412 ierr = PetscStrlcat(str,((PetscObject)snes)->type_name,sizeof(str));CHKERRQ(ierr); 413 ierr = PetscDrawStringBoxed(draw,x,y,PETSC_DRAW_BLUE,PETSC_DRAW_BLACK,str,NULL,&h);CHKERRQ(ierr); 414 bottom = y - h; 415 ierr = PetscDrawPushCurrentPoint(draw,x,bottom);CHKERRQ(ierr); 416 if (snes->ops->view) { 417 ierr = (*snes->ops->view)(snes,viewer);CHKERRQ(ierr); 418 } 419 #if defined(PETSC_HAVE_SAWS) 420 } else if (issaws) { 421 PetscMPIInt rank; 422 const char *name; 423 424 ierr = PetscObjectGetName((PetscObject)snes,&name);CHKERRQ(ierr); 425 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&rank);CHKERRQ(ierr); 426 if (!((PetscObject)snes)->amsmem && !rank) { 427 char dir[1024]; 428 429 ierr = PetscObjectViewSAWs((PetscObject)snes,viewer);CHKERRQ(ierr); 430 ierr = PetscSNPrintf(dir,1024,"/PETSc/Objects/%s/its",name);CHKERRQ(ierr); 431 PetscStackCallSAWs(SAWs_Register,(dir,&snes->iter,1,SAWs_READ,SAWs_INT)); 432 if (!snes->conv_hist) { 433 ierr = SNESSetConvergenceHistory(snes,NULL,NULL,PETSC_DECIDE,PETSC_TRUE);CHKERRQ(ierr); 434 } 435 ierr = PetscSNPrintf(dir,1024,"/PETSc/Objects/%s/conv_hist",name);CHKERRQ(ierr); 436 PetscStackCallSAWs(SAWs_Register,(dir,snes->conv_hist,10,SAWs_READ,SAWs_DOUBLE)); 437 } 438 #endif 439 } 440 if (snes->linesearch) { 441 ierr = SNESGetLineSearch(snes, &linesearch);CHKERRQ(ierr); 442 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 443 ierr = SNESLineSearchView(linesearch, viewer);CHKERRQ(ierr); 444 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 445 } 446 if (snes->npc && snes->usesnpc) { 447 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 448 ierr = SNESView(snes->npc, viewer);CHKERRQ(ierr); 449 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 450 } 451 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 452 ierr = DMGetDMSNES(snes->dm,&dmsnes);CHKERRQ(ierr); 453 ierr = DMSNESView(dmsnes, viewer);CHKERRQ(ierr); 454 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 455 if (snes->usesksp) { 456 ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr); 457 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 458 ierr = KSPView(ksp,viewer);CHKERRQ(ierr); 459 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 460 } 461 if (isdraw) { 462 PetscDraw draw; 463 ierr = PetscViewerDrawGetDraw(viewer,0,&draw);CHKERRQ(ierr); 464 ierr = PetscDrawPopCurrentPoint(draw);CHKERRQ(ierr); 465 } 466 PetscFunctionReturn(0); 467 } 468 469 /* 470 We retain a list of functions that also take SNES command 471 line options. These are called at the end SNESSetFromOptions() 472 */ 473 #define MAXSETFROMOPTIONS 5 474 static PetscInt numberofsetfromoptions; 475 static PetscErrorCode (*othersetfromoptions[MAXSETFROMOPTIONS])(SNES); 476 477 /*@C 478 SNESAddOptionsChecker - Adds an additional function to check for SNES options. 479 480 Not Collective 481 482 Input Parameter: 483 . snescheck - function that checks for options 484 485 Level: developer 486 487 .seealso: SNESSetFromOptions() 488 @*/ 489 PetscErrorCode SNESAddOptionsChecker(PetscErrorCode (*snescheck)(SNES)) 490 { 491 PetscFunctionBegin; 492 if (numberofsetfromoptions >= MAXSETFROMOPTIONS) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Too many options checkers, only %D allowed", MAXSETFROMOPTIONS); 493 othersetfromoptions[numberofsetfromoptions++] = snescheck; 494 PetscFunctionReturn(0); 495 } 496 497 PETSC_INTERN PetscErrorCode SNESDefaultMatrixFreeCreate2(SNES,Vec,Mat*); 498 499 static PetscErrorCode SNESSetUpMatrixFree_Private(SNES snes, PetscBool hasOperator, PetscInt version) 500 { 501 Mat J; 502 KSP ksp; 503 PC pc; 504 PetscBool match; 505 PetscErrorCode ierr; 506 MatNullSpace nullsp; 507 508 PetscFunctionBegin; 509 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 510 511 if (!snes->vec_func && (snes->jacobian || snes->jacobian_pre)) { 512 Mat A = snes->jacobian, B = snes->jacobian_pre; 513 ierr = MatCreateVecs(A ? A : B, NULL,&snes->vec_func);CHKERRQ(ierr); 514 } 515 516 if (version == 1) { 517 ierr = MatCreateSNESMF(snes,&J);CHKERRQ(ierr); 518 ierr = MatMFFDSetOptionsPrefix(J,((PetscObject)snes)->prefix);CHKERRQ(ierr); 519 ierr = MatSetFromOptions(J);CHKERRQ(ierr); 520 } else if (version == 2) { 521 if (!snes->vec_func) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"SNESSetFunction() must be called first"); 522 #if !defined(PETSC_USE_COMPLEX) && !defined(PETSC_USE_REAL_SINGLE) && !defined(PETSC_USE_REAL___FLOAT128) && !defined(PETSC_USE_REAL___FP16) 523 ierr = SNESDefaultMatrixFreeCreate2(snes,snes->vec_func,&J);CHKERRQ(ierr); 524 #else 525 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP, "matrix-free operator rutines (version 2)"); 526 #endif 527 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "matrix-free operator rutines, only version 1 and 2"); 528 529 /* attach any user provided null space that was on Amat to the newly created matrix free matrix */ 530 if (snes->jacobian) { 531 ierr = MatGetNullSpace(snes->jacobian,&nullsp);CHKERRQ(ierr); 532 if (nullsp) { 533 ierr = MatSetNullSpace(J,nullsp);CHKERRQ(ierr); 534 } 535 } 536 537 ierr = PetscInfo1(snes,"Setting default matrix-free operator routines (version %D)\n", version);CHKERRQ(ierr); 538 if (hasOperator) { 539 540 /* This version replaces the user provided Jacobian matrix with a 541 matrix-free version but still employs the user-provided preconditioner matrix. */ 542 ierr = SNESSetJacobian(snes,J,0,0,0);CHKERRQ(ierr); 543 } else { 544 /* This version replaces both the user-provided Jacobian and the user- 545 provided preconditioner Jacobian with the default matrix free version. */ 546 if ((snes->npcside== PC_LEFT) && snes->npc) { 547 if (!snes->jacobian){ierr = SNESSetJacobian(snes,J,0,0,0);CHKERRQ(ierr);} 548 } else { 549 ierr = SNESSetJacobian(snes,J,J,MatMFFDComputeJacobian,0);CHKERRQ(ierr); 550 } 551 /* Force no preconditioner */ 552 ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr); 553 ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); 554 ierr = PetscObjectTypeCompare((PetscObject)pc,PCSHELL,&match);CHKERRQ(ierr); 555 if (!match) { 556 ierr = PetscInfo(snes,"Setting default matrix-free preconditioner routines\nThat is no preconditioner is being used\n");CHKERRQ(ierr); 557 ierr = PCSetType(pc,PCNONE);CHKERRQ(ierr); 558 } 559 } 560 ierr = MatDestroy(&J);CHKERRQ(ierr); 561 PetscFunctionReturn(0); 562 } 563 564 static PetscErrorCode DMRestrictHook_SNESVecSol(DM dmfine,Mat Restrict,Vec Rscale,Mat Inject,DM dmcoarse,void *ctx) 565 { 566 SNES snes = (SNES)ctx; 567 PetscErrorCode ierr; 568 Vec Xfine,Xfine_named = NULL,Xcoarse; 569 570 PetscFunctionBegin; 571 if (PetscLogPrintInfo) { 572 PetscInt finelevel,coarselevel,fineclevel,coarseclevel; 573 ierr = DMGetRefineLevel(dmfine,&finelevel);CHKERRQ(ierr); 574 ierr = DMGetCoarsenLevel(dmfine,&fineclevel);CHKERRQ(ierr); 575 ierr = DMGetRefineLevel(dmcoarse,&coarselevel);CHKERRQ(ierr); 576 ierr = DMGetCoarsenLevel(dmcoarse,&coarseclevel);CHKERRQ(ierr); 577 ierr = PetscInfo4(dmfine,"Restricting SNES solution vector from level %D-%D to level %D-%D\n",finelevel,fineclevel,coarselevel,coarseclevel);CHKERRQ(ierr); 578 } 579 if (dmfine == snes->dm) Xfine = snes->vec_sol; 580 else { 581 ierr = DMGetNamedGlobalVector(dmfine,"SNESVecSol",&Xfine_named);CHKERRQ(ierr); 582 Xfine = Xfine_named; 583 } 584 ierr = DMGetNamedGlobalVector(dmcoarse,"SNESVecSol",&Xcoarse);CHKERRQ(ierr); 585 if (Inject) { 586 ierr = MatRestrict(Inject,Xfine,Xcoarse);CHKERRQ(ierr); 587 } else { 588 ierr = MatRestrict(Restrict,Xfine,Xcoarse);CHKERRQ(ierr); 589 ierr = VecPointwiseMult(Xcoarse,Xcoarse,Rscale);CHKERRQ(ierr); 590 } 591 ierr = DMRestoreNamedGlobalVector(dmcoarse,"SNESVecSol",&Xcoarse);CHKERRQ(ierr); 592 if (Xfine_named) {ierr = DMRestoreNamedGlobalVector(dmfine,"SNESVecSol",&Xfine_named);CHKERRQ(ierr);} 593 PetscFunctionReturn(0); 594 } 595 596 static PetscErrorCode DMCoarsenHook_SNESVecSol(DM dm,DM dmc,void *ctx) 597 { 598 PetscErrorCode ierr; 599 600 PetscFunctionBegin; 601 ierr = DMCoarsenHookAdd(dmc,DMCoarsenHook_SNESVecSol,DMRestrictHook_SNESVecSol,ctx);CHKERRQ(ierr); 602 PetscFunctionReturn(0); 603 } 604 605 /* This may be called to rediscretize the operator on levels of linear multigrid. The DM shuffle is so the user can 606 * safely call SNESGetDM() in their residual evaluation routine. */ 607 static PetscErrorCode KSPComputeOperators_SNES(KSP ksp,Mat A,Mat B,void *ctx) 608 { 609 SNES snes = (SNES)ctx; 610 PetscErrorCode ierr; 611 Vec X,Xnamed = NULL; 612 DM dmsave; 613 void *ctxsave; 614 PetscErrorCode (*jac)(SNES,Vec,Mat,Mat,void*) = NULL; 615 616 PetscFunctionBegin; 617 dmsave = snes->dm; 618 ierr = KSPGetDM(ksp,&snes->dm);CHKERRQ(ierr); 619 if (dmsave == snes->dm) X = snes->vec_sol; /* We are on the finest level */ 620 else { /* We are on a coarser level, this vec was initialized using a DM restrict hook */ 621 ierr = DMGetNamedGlobalVector(snes->dm,"SNESVecSol",&Xnamed);CHKERRQ(ierr); 622 X = Xnamed; 623 ierr = SNESGetJacobian(snes,NULL,NULL,&jac,&ctxsave);CHKERRQ(ierr); 624 /* If the DM's don't match up, the MatFDColoring context needed for the jacobian won't match up either -- fixit. */ 625 if (jac == SNESComputeJacobianDefaultColor) { 626 ierr = SNESSetJacobian(snes,NULL,NULL,SNESComputeJacobianDefaultColor,0);CHKERRQ(ierr); 627 } 628 } 629 /* Make sure KSP DM has the Jacobian computation routine */ 630 { 631 DMSNES sdm; 632 633 ierr = DMGetDMSNES(snes->dm, &sdm);CHKERRQ(ierr); 634 if (!sdm->ops->computejacobian) { 635 ierr = DMCopyDMSNES(dmsave, snes->dm);CHKERRQ(ierr); 636 } 637 } 638 /* Compute the operators */ 639 ierr = SNESComputeJacobian(snes,X,A,B);CHKERRQ(ierr); 640 /* Put the previous context back */ 641 if (snes->dm != dmsave && jac == SNESComputeJacobianDefaultColor) { 642 ierr = SNESSetJacobian(snes,NULL,NULL,jac,ctxsave);CHKERRQ(ierr); 643 } 644 645 if (Xnamed) {ierr = DMRestoreNamedGlobalVector(snes->dm,"SNESVecSol",&Xnamed);CHKERRQ(ierr);} 646 snes->dm = dmsave; 647 PetscFunctionReturn(0); 648 } 649 650 /*@ 651 SNESSetUpMatrices - ensures that matrices are available for SNES, to be called by SNESSetUp_XXX() 652 653 Collective 654 655 Input Arguments: 656 . snes - snes to configure 657 658 Level: developer 659 660 .seealso: SNESSetUp() 661 @*/ 662 PetscErrorCode SNESSetUpMatrices(SNES snes) 663 { 664 PetscErrorCode ierr; 665 DM dm; 666 DMSNES sdm; 667 668 PetscFunctionBegin; 669 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 670 ierr = DMGetDMSNES(dm,&sdm);CHKERRQ(ierr); 671 if (!sdm->ops->computejacobian) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_PLIB,"DMSNES not properly configured"); 672 else if (!snes->jacobian && snes->mf) { 673 Mat J; 674 void *functx; 675 ierr = MatCreateSNESMF(snes,&J);CHKERRQ(ierr); 676 ierr = MatMFFDSetOptionsPrefix(J,((PetscObject)snes)->prefix);CHKERRQ(ierr); 677 ierr = MatSetFromOptions(J);CHKERRQ(ierr); 678 ierr = SNESGetFunction(snes,NULL,NULL,&functx);CHKERRQ(ierr); 679 ierr = SNESSetJacobian(snes,J,J,0,0);CHKERRQ(ierr); 680 ierr = MatDestroy(&J);CHKERRQ(ierr); 681 } else if (snes->mf_operator && !snes->jacobian_pre && !snes->jacobian) { 682 Mat J,B; 683 ierr = MatCreateSNESMF(snes,&J);CHKERRQ(ierr); 684 ierr = MatMFFDSetOptionsPrefix(J,((PetscObject)snes)->prefix);CHKERRQ(ierr); 685 ierr = MatSetFromOptions(J);CHKERRQ(ierr); 686 ierr = DMCreateMatrix(snes->dm,&B);CHKERRQ(ierr); 687 /* sdm->computejacobian was already set to reach here */ 688 ierr = SNESSetJacobian(snes,J,B,NULL,NULL);CHKERRQ(ierr); 689 ierr = MatDestroy(&J);CHKERRQ(ierr); 690 ierr = MatDestroy(&B);CHKERRQ(ierr); 691 } else if (!snes->jacobian_pre) { 692 PetscErrorCode (*nspconstr)(DM, PetscInt, MatNullSpace *); 693 PetscDS prob; 694 Mat J, B; 695 MatNullSpace nullspace = NULL; 696 PetscBool hasPrec = PETSC_FALSE; 697 PetscInt Nf; 698 699 J = snes->jacobian; 700 ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 701 if (prob) {ierr = PetscDSHasJacobianPreconditioner(prob, &hasPrec);CHKERRQ(ierr);} 702 if (J) {ierr = PetscObjectReference((PetscObject) J);CHKERRQ(ierr);} 703 else if (hasPrec) {ierr = DMCreateMatrix(snes->dm, &J);CHKERRQ(ierr);} 704 ierr = DMCreateMatrix(snes->dm, &B);CHKERRQ(ierr); 705 ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr); 706 ierr = DMGetNullSpaceConstructor(snes->dm, Nf, &nspconstr);CHKERRQ(ierr); 707 if (nspconstr) (*nspconstr)(snes->dm, -1, &nullspace); 708 ierr = MatSetNullSpace(B, nullspace);CHKERRQ(ierr); 709 ierr = MatNullSpaceDestroy(&nullspace);CHKERRQ(ierr); 710 ierr = SNESSetJacobian(snes, J ? J : B, B, NULL, NULL);CHKERRQ(ierr); 711 ierr = MatDestroy(&J);CHKERRQ(ierr); 712 ierr = MatDestroy(&B);CHKERRQ(ierr); 713 } 714 { 715 KSP ksp; 716 ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr); 717 ierr = KSPSetComputeOperators(ksp,KSPComputeOperators_SNES,snes);CHKERRQ(ierr); 718 ierr = DMCoarsenHookAdd(snes->dm,DMCoarsenHook_SNESVecSol,DMRestrictHook_SNESVecSol,snes);CHKERRQ(ierr); 719 } 720 PetscFunctionReturn(0); 721 } 722 723 /*@C 724 SNESMonitorSetFromOptions - Sets a monitor function and viewer appropriate for the type indicated by the user 725 726 Collective on SNES 727 728 Input Parameters: 729 + snes - SNES object you wish to monitor 730 . name - the monitor type one is seeking 731 . help - message indicating what monitoring is done 732 . manual - manual page for the monitor 733 . monitor - the monitor function 734 - monitorsetup - a function that is called once ONLY if the user selected this monitor that may set additional features of the SNES or PetscViewer objects 735 736 Level: developer 737 738 .seealso: PetscOptionsGetViewer(), PetscOptionsGetReal(), PetscOptionsHasName(), PetscOptionsGetString(), 739 PetscOptionsGetIntArray(), PetscOptionsGetRealArray(), PetscOptionsBool() 740 PetscOptionsInt(), PetscOptionsString(), PetscOptionsReal(), PetscOptionsBool(), 741 PetscOptionsName(), PetscOptionsBegin(), PetscOptionsEnd(), PetscOptionsHead(), 742 PetscOptionsStringArray(),PetscOptionsRealArray(), PetscOptionsScalar(), 743 PetscOptionsBoolGroupBegin(), PetscOptionsBoolGroup(), PetscOptionsBoolGroupEnd(), 744 PetscOptionsFList(), PetscOptionsEList() 745 @*/ 746 PetscErrorCode SNESMonitorSetFromOptions(SNES snes,const char name[],const char help[], const char manual[],PetscErrorCode (*monitor)(SNES,PetscInt,PetscReal,PetscViewerAndFormat*),PetscErrorCode (*monitorsetup)(SNES,PetscViewerAndFormat*)) 747 { 748 PetscErrorCode ierr; 749 PetscViewer viewer; 750 PetscViewerFormat format; 751 PetscBool flg; 752 753 PetscFunctionBegin; 754 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject) snes)->options,((PetscObject)snes)->prefix,name,&viewer,&format,&flg);CHKERRQ(ierr); 755 if (flg) { 756 PetscViewerAndFormat *vf; 757 ierr = PetscViewerAndFormatCreate(viewer,format,&vf);CHKERRQ(ierr); 758 ierr = PetscObjectDereference((PetscObject)viewer);CHKERRQ(ierr); 759 if (monitorsetup) { 760 ierr = (*monitorsetup)(snes,vf);CHKERRQ(ierr); 761 } 762 ierr = SNESMonitorSet(snes,(PetscErrorCode (*)(SNES,PetscInt,PetscReal,void*))monitor,vf,(PetscErrorCode (*)(void**))PetscViewerAndFormatDestroy);CHKERRQ(ierr); 763 } 764 PetscFunctionReturn(0); 765 } 766 767 /*@ 768 SNESSetFromOptions - Sets various SNES and KSP parameters from user options. 769 770 Collective on SNES 771 772 Input Parameter: 773 . snes - the SNES context 774 775 Options Database Keys: 776 + -snes_type <type> - newtonls, newtontr, ngmres, ncg, nrichardson, qn, vi, fas, SNESType for complete list 777 . -snes_stol - convergence tolerance in terms of the norm 778 of the change in the solution between steps 779 . -snes_atol <abstol> - absolute tolerance of residual norm 780 . -snes_rtol <rtol> - relative decrease in tolerance norm from initial 781 . -snes_divergence_tolerance <divtol> - if the residual goes above divtol*rnorm0, exit with divergence 782 . -snes_force_iteration <force> - force SNESSolve() to take at least one iteration 783 . -snes_max_it <max_it> - maximum number of iterations 784 . -snes_max_funcs <max_funcs> - maximum number of function evaluations 785 . -snes_max_fail <max_fail> - maximum number of line search failures allowed before stopping, default is none 786 . -snes_max_linear_solve_fail - number of linear solver failures before SNESSolve() stops 787 . -snes_lag_preconditioner <lag> - how often preconditioner is rebuilt (use -1 to never rebuild) 788 . -snes_lag_jacobian <lag> - how often Jacobian is rebuilt (use -1 to never rebuild) 789 . -snes_trtol <trtol> - trust region tolerance 790 . -snes_no_convergence_test - skip convergence test in nonlinear 791 solver; hence iterations will continue until max_it 792 or some other criterion is reached. Saves expense 793 of convergence test 794 . -snes_monitor [ascii][:filename][:viewer format] - prints residual norm at each iteration. if no filename given prints to stdout 795 . -snes_monitor_solution [ascii binary draw][:filename][:viewer format] - plots solution at each iteration 796 . -snes_monitor_residual [ascii binary draw][:filename][:viewer format] - plots residual (not its norm) at each iteration 797 . -snes_monitor_solution_update [ascii binary draw][:filename][:viewer format] - plots update to solution at each iteration 798 . -snes_monitor_lg_residualnorm - plots residual norm at each iteration 799 . -snes_monitor_lg_range - plots residual norm at each iteration 800 . -snes_fd - use finite differences to compute Jacobian; very slow, only for testing 801 . -snes_fd_color - use finite differences with coloring to compute Jacobian 802 . -snes_mf_ksp_monitor - if using matrix-free multiply then print h at each KSP iteration 803 - -snes_converged_reason - print the reason for convergence/divergence after each solve 804 805 Options Database for Eisenstat-Walker method: 806 + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence 807 . -snes_ksp_ew_version ver - version of Eisenstat-Walker method 808 . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0 809 . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax 810 . -snes_ksp_ew_gamma <gamma> - Sets gamma 811 . -snes_ksp_ew_alpha <alpha> - Sets alpha 812 . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2 813 - -snes_ksp_ew_threshold <threshold> - Sets threshold 814 815 Notes: 816 To see all options, run your program with the -help option or consult 817 Users-Manual: ch_snes 818 819 Level: beginner 820 821 .keywords: SNES, nonlinear, set, options, database 822 823 .seealso: SNESSetOptionsPrefix(), SNESResetFromOptions() 824 @*/ 825 PetscErrorCode SNESSetFromOptions(SNES snes) 826 { 827 PetscBool flg,pcset,persist,set; 828 PetscInt i,indx,lag,grids; 829 const char *deft = SNESNEWTONLS; 830 const char *convtests[] = {"default","skip"}; 831 SNESKSPEW *kctx = NULL; 832 char type[256], monfilename[PETSC_MAX_PATH_LEN]; 833 PetscErrorCode ierr; 834 PCSide pcside; 835 const char *optionsprefix; 836 837 PetscFunctionBegin; 838 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 839 ierr = SNESRegisterAll();CHKERRQ(ierr); 840 ierr = PetscObjectOptionsBegin((PetscObject)snes);CHKERRQ(ierr); 841 if (((PetscObject)snes)->type_name) deft = ((PetscObject)snes)->type_name; 842 ierr = PetscOptionsFList("-snes_type","Nonlinear solver method","SNESSetType",SNESList,deft,type,256,&flg);CHKERRQ(ierr); 843 if (flg) { 844 ierr = SNESSetType(snes,type);CHKERRQ(ierr); 845 } else if (!((PetscObject)snes)->type_name) { 846 ierr = SNESSetType(snes,deft);CHKERRQ(ierr); 847 } 848 ierr = PetscOptionsReal("-snes_stol","Stop if step length less than","SNESSetTolerances",snes->stol,&snes->stol,NULL);CHKERRQ(ierr); 849 ierr = PetscOptionsReal("-snes_atol","Stop if function norm less than","SNESSetTolerances",snes->abstol,&snes->abstol,NULL);CHKERRQ(ierr); 850 851 ierr = PetscOptionsReal("-snes_rtol","Stop if decrease in function norm less than","SNESSetTolerances",snes->rtol,&snes->rtol,NULL);CHKERRQ(ierr); 852 ierr = PetscOptionsReal("-snes_divergence_tolerance","Stop if residual norm increases by this factor","SNESSetDivergenceTolerance",snes->divtol,&snes->divtol,NULL);CHKERRQ(ierr); 853 ierr = PetscOptionsInt("-snes_max_it","Maximum iterations","SNESSetTolerances",snes->max_its,&snes->max_its,NULL);CHKERRQ(ierr); 854 ierr = PetscOptionsInt("-snes_max_funcs","Maximum function evaluations","SNESSetTolerances",snes->max_funcs,&snes->max_funcs,NULL);CHKERRQ(ierr); 855 ierr = PetscOptionsInt("-snes_max_fail","Maximum nonlinear step failures","SNESSetMaxNonlinearStepFailures",snes->maxFailures,&snes->maxFailures,NULL);CHKERRQ(ierr); 856 ierr = PetscOptionsInt("-snes_max_linear_solve_fail","Maximum failures in linear solves allowed","SNESSetMaxLinearSolveFailures",snes->maxLinearSolveFailures,&snes->maxLinearSolveFailures,NULL);CHKERRQ(ierr); 857 ierr = PetscOptionsBool("-snes_error_if_not_converged","Generate error if solver does not converge","SNESSetErrorIfNotConverged",snes->errorifnotconverged,&snes->errorifnotconverged,NULL);CHKERRQ(ierr); 858 ierr = PetscOptionsBool("-snes_force_iteration","Force SNESSolve() to take at least one iteration","SNESSetForceIteration",snes->forceiteration,&snes->forceiteration,NULL);CHKERRQ(ierr); 859 860 ierr = PetscOptionsInt("-snes_lag_preconditioner","How often to rebuild preconditioner","SNESSetLagPreconditioner",snes->lagpreconditioner,&lag,&flg);CHKERRQ(ierr); 861 if (flg) { 862 ierr = SNESSetLagPreconditioner(snes,lag);CHKERRQ(ierr); 863 } 864 ierr = PetscOptionsBool("-snes_lag_preconditioner_persists","Preconditioner lagging through multiple solves","SNESSetLagPreconditionerPersists",snes->lagjac_persist,&persist,&flg);CHKERRQ(ierr); 865 if (flg) { 866 ierr = SNESSetLagPreconditionerPersists(snes,persist);CHKERRQ(ierr); 867 } 868 ierr = PetscOptionsInt("-snes_lag_jacobian","How often to rebuild Jacobian","SNESSetLagJacobian",snes->lagjacobian,&lag,&flg);CHKERRQ(ierr); 869 if (flg) { 870 ierr = SNESSetLagJacobian(snes,lag);CHKERRQ(ierr); 871 } 872 ierr = PetscOptionsBool("-snes_lag_jacobian_persists","Jacobian lagging through multiple solves","SNESSetLagJacobianPersists",snes->lagjac_persist,&persist,&flg);CHKERRQ(ierr); 873 if (flg) { 874 ierr = SNESSetLagJacobianPersists(snes,persist);CHKERRQ(ierr); 875 } 876 877 ierr = PetscOptionsInt("-snes_grid_sequence","Use grid sequencing to generate initial guess","SNESSetGridSequence",snes->gridsequence,&grids,&flg);CHKERRQ(ierr); 878 if (flg) { 879 ierr = SNESSetGridSequence(snes,grids);CHKERRQ(ierr); 880 } 881 882 ierr = PetscOptionsEList("-snes_convergence_test","Convergence test","SNESSetConvergenceTest",convtests,2,"default",&indx,&flg);CHKERRQ(ierr); 883 if (flg) { 884 switch (indx) { 885 case 0: ierr = SNESSetConvergenceTest(snes,SNESConvergedDefault,NULL,NULL);CHKERRQ(ierr); break; 886 case 1: ierr = SNESSetConvergenceTest(snes,SNESConvergedSkip,NULL,NULL);CHKERRQ(ierr); break; 887 } 888 } 889 890 ierr = PetscOptionsEList("-snes_norm_schedule","SNES Norm schedule","SNESSetNormSchedule",SNESNormSchedules,5,"function",&indx,&flg);CHKERRQ(ierr); 891 if (flg) { ierr = SNESSetNormSchedule(snes,(SNESNormSchedule)indx);CHKERRQ(ierr); } 892 893 ierr = PetscOptionsEList("-snes_function_type","SNES Norm schedule","SNESSetFunctionType",SNESFunctionTypes,2,"unpreconditioned",&indx,&flg);CHKERRQ(ierr); 894 if (flg) { ierr = SNESSetFunctionType(snes,(SNESFunctionType)indx);CHKERRQ(ierr); } 895 896 kctx = (SNESKSPEW*)snes->kspconvctx; 897 898 ierr = PetscOptionsBool("-snes_ksp_ew","Use Eisentat-Walker linear system convergence test","SNESKSPSetUseEW",snes->ksp_ewconv,&snes->ksp_ewconv,NULL);CHKERRQ(ierr); 899 900 ierr = PetscOptionsInt("-snes_ksp_ew_version","Version 1, 2 or 3","SNESKSPSetParametersEW",kctx->version,&kctx->version,NULL);CHKERRQ(ierr); 901 ierr = PetscOptionsReal("-snes_ksp_ew_rtol0","0 <= rtol0 < 1","SNESKSPSetParametersEW",kctx->rtol_0,&kctx->rtol_0,NULL);CHKERRQ(ierr); 902 ierr = PetscOptionsReal("-snes_ksp_ew_rtolmax","0 <= rtolmax < 1","SNESKSPSetParametersEW",kctx->rtol_max,&kctx->rtol_max,NULL);CHKERRQ(ierr); 903 ierr = PetscOptionsReal("-snes_ksp_ew_gamma","0 <= gamma <= 1","SNESKSPSetParametersEW",kctx->gamma,&kctx->gamma,NULL);CHKERRQ(ierr); 904 ierr = PetscOptionsReal("-snes_ksp_ew_alpha","1 < alpha <= 2","SNESKSPSetParametersEW",kctx->alpha,&kctx->alpha,NULL);CHKERRQ(ierr); 905 ierr = PetscOptionsReal("-snes_ksp_ew_alpha2","alpha2","SNESKSPSetParametersEW",kctx->alpha2,&kctx->alpha2,NULL);CHKERRQ(ierr); 906 ierr = PetscOptionsReal("-snes_ksp_ew_threshold","0 < threshold < 1","SNESKSPSetParametersEW",kctx->threshold,&kctx->threshold,NULL);CHKERRQ(ierr); 907 908 flg = PETSC_FALSE; 909 ierr = PetscOptionsBool("-snes_monitor_cancel","Remove all monitors","SNESMonitorCancel",flg,&flg,&set);CHKERRQ(ierr); 910 if (set && flg) {ierr = SNESMonitorCancel(snes);CHKERRQ(ierr);} 911 912 ierr = SNESMonitorSetFromOptions(snes,"-snes_monitor","Monitor norm of function","SNESMonitorDefault",SNESMonitorDefault,NULL);CHKERRQ(ierr); 913 ierr = SNESMonitorSetFromOptions(snes,"-snes_monitor_short","Monitor norm of function with fewer digits","SNESMonitorDefaultShort",SNESMonitorDefaultShort,NULL);CHKERRQ(ierr); 914 ierr = SNESMonitorSetFromOptions(snes,"-snes_monitor_range","Monitor range of elements of function","SNESMonitorRange",SNESMonitorRange,NULL);CHKERRQ(ierr); 915 916 ierr = SNESMonitorSetFromOptions(snes,"-snes_monitor_ratio","Monitor ratios of the norm of function for consecutive steps","SNESMonitorRatio",SNESMonitorRatio,SNESMonitorRatioSetUp);CHKERRQ(ierr); 917 ierr = SNESMonitorSetFromOptions(snes,"-snes_monitor_field","Monitor norm of function (split into fields)","SNESMonitorDefaultField",SNESMonitorDefaultField,NULL);CHKERRQ(ierr); 918 ierr = SNESMonitorSetFromOptions(snes,"-snes_monitor_solution","View solution at each iteration","SNESMonitorSolution",SNESMonitorSolution,NULL);CHKERRQ(ierr); 919 ierr = SNESMonitorSetFromOptions(snes,"-snes_monitor_solution_update","View correction at each iteration","SNESMonitorSolutionUpdate",SNESMonitorSolutionUpdate,NULL);CHKERRQ(ierr); 920 ierr = SNESMonitorSetFromOptions(snes,"-snes_monitor_residual","View residual at each iteration","SNESMonitorResidual",SNESMonitorResidual,NULL);CHKERRQ(ierr); 921 ierr = SNESMonitorSetFromOptions(snes,"-snes_monitor_jacupdate_spectrum","Print the change in the spectrum of the Jacobian","SNESMonitorJacUpdateSpectrum",SNESMonitorJacUpdateSpectrum,NULL);CHKERRQ(ierr); 922 ierr = SNESMonitorSetFromOptions(snes,"-snes_monitor_fields","Monitor norm of function per field","SNESMonitorSet",SNESMonitorFields,NULL);CHKERRQ(ierr); 923 924 ierr = PetscOptionsString("-snes_monitor_python","Use Python function","SNESMonitorSet",0,monfilename,PETSC_MAX_PATH_LEN,&flg);CHKERRQ(ierr); 925 if (flg) {ierr = PetscPythonMonitorSet((PetscObject)snes,monfilename);CHKERRQ(ierr);} 926 927 928 flg = PETSC_FALSE; 929 ierr = PetscOptionsBool("-snes_monitor_lg_residualnorm","Plot function norm at each iteration","SNESMonitorLGResidualNorm",flg,&flg,NULL);CHKERRQ(ierr); 930 if (flg) { 931 PetscDrawLG ctx; 932 933 ierr = SNESMonitorLGCreate(PetscObjectComm((PetscObject)snes),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,&ctx);CHKERRQ(ierr); 934 ierr = SNESMonitorSet(snes,SNESMonitorLGResidualNorm,ctx,(PetscErrorCode (*)(void**))PetscDrawLGDestroy);CHKERRQ(ierr); 935 } 936 flg = PETSC_FALSE; 937 ierr = PetscOptionsBool("-snes_monitor_lg_range","Plot function range at each iteration","SNESMonitorLGRange",flg,&flg,NULL);CHKERRQ(ierr); 938 if (flg) { 939 PetscViewer ctx; 940 941 ierr = PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,400,300,&ctx);CHKERRQ(ierr); 942 ierr = SNESMonitorSet(snes,SNESMonitorLGRange,ctx,(PetscErrorCode (*)(void**))PetscViewerDestroy);CHKERRQ(ierr); 943 } 944 945 946 947 flg = PETSC_FALSE; 948 ierr = PetscOptionsBool("-snes_fd","Use finite differences (slow) to compute Jacobian","SNESComputeJacobianDefault",flg,&flg,NULL);CHKERRQ(ierr); 949 if (flg) { 950 void *functx; 951 DM dm; 952 DMSNES sdm; 953 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 954 ierr = DMGetDMSNES(dm,&sdm);CHKERRQ(ierr); 955 sdm->jacobianctx = NULL; 956 ierr = SNESGetFunction(snes,NULL,NULL,&functx);CHKERRQ(ierr); 957 ierr = SNESSetJacobian(snes,snes->jacobian,snes->jacobian_pre,SNESComputeJacobianDefault,functx);CHKERRQ(ierr); 958 ierr = PetscInfo(snes,"Setting default finite difference Jacobian matrix\n");CHKERRQ(ierr); 959 } 960 961 flg = PETSC_FALSE; 962 ierr = PetscOptionsBool("-snes_fd_function","Use finite differences (slow) to compute function from user objective","SNESObjectiveComputeFunctionDefaultFD",flg,&flg,NULL);CHKERRQ(ierr); 963 if (flg) { 964 ierr = SNESSetFunction(snes,NULL,SNESObjectiveComputeFunctionDefaultFD,NULL);CHKERRQ(ierr); 965 } 966 967 flg = PETSC_FALSE; 968 ierr = PetscOptionsBool("-snes_fd_color","Use finite differences with coloring to compute Jacobian","SNESComputeJacobianDefaultColor",flg,&flg,NULL);CHKERRQ(ierr); 969 if (flg) { 970 DM dm; 971 DMSNES sdm; 972 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 973 ierr = DMGetDMSNES(dm,&sdm);CHKERRQ(ierr); 974 sdm->jacobianctx = NULL; 975 ierr = SNESSetJacobian(snes,snes->jacobian,snes->jacobian_pre,SNESComputeJacobianDefaultColor,0);CHKERRQ(ierr); 976 ierr = PetscInfo(snes,"Setting default finite difference coloring Jacobian matrix\n");CHKERRQ(ierr); 977 } 978 979 flg = PETSC_FALSE; 980 ierr = PetscOptionsBool("-snes_mf_operator","Use a Matrix-Free Jacobian with user-provided preconditioner matrix","SNESSetUseMatrixFree",PETSC_FALSE,&snes->mf_operator,&flg);CHKERRQ(ierr); 981 if (flg && snes->mf_operator) { 982 snes->mf_operator = PETSC_TRUE; 983 snes->mf = PETSC_TRUE; 984 } 985 flg = PETSC_FALSE; 986 ierr = PetscOptionsBool("-snes_mf","Use a Matrix-Free Jacobian with no preconditioner matrix","SNESSetUseMatrixFree",PETSC_FALSE,&snes->mf,&flg);CHKERRQ(ierr); 987 if (!flg && snes->mf_operator) snes->mf = PETSC_TRUE; 988 ierr = PetscOptionsInt("-snes_mf_version","Matrix-Free routines version 1 or 2","None",snes->mf_version,&snes->mf_version,0);CHKERRQ(ierr); 989 990 flg = PETSC_FALSE; 991 ierr = SNESGetNPCSide(snes,&pcside);CHKERRQ(ierr); 992 ierr = PetscOptionsEnum("-snes_npc_side","SNES nonlinear preconditioner side","SNESSetNPCSide",PCSides,(PetscEnum)pcside,(PetscEnum*)&pcside,&flg);CHKERRQ(ierr); 993 if (flg) {ierr = SNESSetNPCSide(snes,pcside);CHKERRQ(ierr);} 994 995 #if defined(PETSC_HAVE_SAWS) 996 /* 997 Publish convergence information using SAWs 998 */ 999 flg = PETSC_FALSE; 1000 ierr = PetscOptionsBool("-snes_monitor_saws","Publish SNES progress using SAWs","SNESMonitorSet",flg,&flg,NULL);CHKERRQ(ierr); 1001 if (flg) { 1002 void *ctx; 1003 ierr = SNESMonitorSAWsCreate(snes,&ctx);CHKERRQ(ierr); 1004 ierr = SNESMonitorSet(snes,SNESMonitorSAWs,ctx,SNESMonitorSAWsDestroy);CHKERRQ(ierr); 1005 } 1006 #endif 1007 #if defined(PETSC_HAVE_SAWS) 1008 { 1009 PetscBool set; 1010 flg = PETSC_FALSE; 1011 ierr = PetscOptionsBool("-snes_saws_block","Block for SAWs at end of SNESSolve","PetscObjectSAWsBlock",((PetscObject)snes)->amspublishblock,&flg,&set);CHKERRQ(ierr); 1012 if (set) { 1013 ierr = PetscObjectSAWsSetBlock((PetscObject)snes,flg);CHKERRQ(ierr); 1014 } 1015 } 1016 #endif 1017 1018 for (i = 0; i < numberofsetfromoptions; i++) { 1019 ierr = (*othersetfromoptions[i])(snes);CHKERRQ(ierr); 1020 } 1021 1022 if (snes->ops->setfromoptions) { 1023 ierr = (*snes->ops->setfromoptions)(PetscOptionsObject,snes);CHKERRQ(ierr); 1024 } 1025 1026 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 1027 ierr = PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject)snes);CHKERRQ(ierr); 1028 ierr = PetscOptionsEnd();CHKERRQ(ierr); 1029 1030 if (!snes->linesearch) { 1031 ierr = SNESGetLineSearch(snes, &snes->linesearch);CHKERRQ(ierr); 1032 } 1033 ierr = SNESLineSearchSetFromOptions(snes->linesearch);CHKERRQ(ierr); 1034 1035 if (!snes->ksp) {ierr = SNESGetKSP(snes,&snes->ksp);CHKERRQ(ierr);} 1036 ierr = KSPSetOperators(snes->ksp,snes->jacobian,snes->jacobian_pre);CHKERRQ(ierr); 1037 ierr = KSPSetFromOptions(snes->ksp);CHKERRQ(ierr); 1038 1039 /* if someone has set the SNES NPC type, create it. */ 1040 ierr = SNESGetOptionsPrefix(snes, &optionsprefix);CHKERRQ(ierr); 1041 ierr = PetscOptionsHasName(((PetscObject)snes)->options,optionsprefix, "-npc_snes_type", &pcset);CHKERRQ(ierr); 1042 if (pcset && (!snes->npc)) { 1043 ierr = SNESGetNPC(snes, &snes->npc);CHKERRQ(ierr); 1044 } 1045 snes->setfromoptionscalled++; 1046 PetscFunctionReturn(0); 1047 } 1048 1049 /*@ 1050 SNESResetFromOptions - Sets various SNES and KSP parameters from user options ONLY if the SNES was previously set from options 1051 1052 Collective on SNES 1053 1054 Input Parameter: 1055 . snes - the SNES context 1056 1057 Level: beginner 1058 1059 .keywords: SNES, nonlinear, set, options, database 1060 1061 .seealso: SNESSetFromOptions(), SNESSetOptionsPrefix() 1062 @*/ 1063 PetscErrorCode SNESResetFromOptions(SNES snes) 1064 { 1065 PetscErrorCode ierr; 1066 1067 PetscFunctionBegin; 1068 if (snes->setfromoptionscalled) {ierr = SNESSetFromOptions(snes);CHKERRQ(ierr);} 1069 PetscFunctionReturn(0); 1070 } 1071 1072 /*@C 1073 SNESSetComputeApplicationContext - Sets an optional function to compute a user-defined context for 1074 the nonlinear solvers. 1075 1076 Logically Collective on SNES 1077 1078 Input Parameters: 1079 + snes - the SNES context 1080 . compute - function to compute the context 1081 - destroy - function to destroy the context 1082 1083 Level: intermediate 1084 1085 Notes: 1086 This function is currently not available from Fortran. 1087 1088 .keywords: SNES, nonlinear, set, application, context 1089 1090 .seealso: SNESGetApplicationContext(), SNESSetComputeApplicationContext(), SNESGetApplicationContext() 1091 @*/ 1092 PetscErrorCode SNESSetComputeApplicationContext(SNES snes,PetscErrorCode (*compute)(SNES,void**),PetscErrorCode (*destroy)(void**)) 1093 { 1094 PetscFunctionBegin; 1095 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1096 snes->ops->usercompute = compute; 1097 snes->ops->userdestroy = destroy; 1098 PetscFunctionReturn(0); 1099 } 1100 1101 /*@ 1102 SNESSetApplicationContext - Sets the optional user-defined context for 1103 the nonlinear solvers. 1104 1105 Logically Collective on SNES 1106 1107 Input Parameters: 1108 + snes - the SNES context 1109 - usrP - optional user context 1110 1111 Level: intermediate 1112 1113 Fortran Notes: 1114 To use this from Fortran you must write a Fortran interface definition for this 1115 function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument. 1116 1117 .keywords: SNES, nonlinear, set, application, context 1118 1119 .seealso: SNESGetApplicationContext() 1120 @*/ 1121 PetscErrorCode SNESSetApplicationContext(SNES snes,void *usrP) 1122 { 1123 PetscErrorCode ierr; 1124 KSP ksp; 1125 1126 PetscFunctionBegin; 1127 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1128 ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr); 1129 ierr = KSPSetApplicationContext(ksp,usrP);CHKERRQ(ierr); 1130 snes->user = usrP; 1131 PetscFunctionReturn(0); 1132 } 1133 1134 /*@ 1135 SNESGetApplicationContext - Gets the user-defined context for the 1136 nonlinear solvers. 1137 1138 Not Collective 1139 1140 Input Parameter: 1141 . snes - SNES context 1142 1143 Output Parameter: 1144 . usrP - user context 1145 1146 Fortran Notes: 1147 To use this from Fortran you must write a Fortran interface definition for this 1148 function that tells Fortran the Fortran derived data type that you are passing in as the ctx argument. 1149 1150 Level: intermediate 1151 1152 .keywords: SNES, nonlinear, get, application, context 1153 1154 .seealso: SNESSetApplicationContext() 1155 @*/ 1156 PetscErrorCode SNESGetApplicationContext(SNES snes,void *usrP) 1157 { 1158 PetscFunctionBegin; 1159 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1160 *(void**)usrP = snes->user; 1161 PetscFunctionReturn(0); 1162 } 1163 1164 /*@ 1165 SNESSetUseMatrixFree - indicates that SNES should use matrix free finite difference matrix vector products internally to apply 1166 the Jacobian. 1167 1168 Collective on SNES 1169 1170 Input Parameters: 1171 + snes - SNES context 1172 . mf - use matrix-free for both the Amat and Pmat used by SNESSetJacobian(), both the Amat and Pmat set in SNESSetJacobian() will be ignored 1173 - mf_operator - use matrix-free only for the Amat used by SNESSetJacobian(), this means the user provided Pmat will continue to be used 1174 1175 Options Database: 1176 + -snes_mf - use matrix free for both the mat and pmat operator 1177 - -snes_mf_operator - use matrix free only for the mat operator 1178 1179 Level: intermediate 1180 1181 .keywords: SNES, nonlinear, get, iteration, number, 1182 1183 .seealso: SNESGetUseMatrixFree(), MatCreateSNESMF() 1184 @*/ 1185 PetscErrorCode SNESSetUseMatrixFree(SNES snes,PetscBool mf_operator,PetscBool mf) 1186 { 1187 PetscFunctionBegin; 1188 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1189 PetscValidLogicalCollectiveBool(snes,mf_operator,2); 1190 PetscValidLogicalCollectiveBool(snes,mf,3); 1191 if (mf && !mf_operator) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_INCOMP,"If using mf must also use mf_operator"); 1192 snes->mf = mf; 1193 snes->mf_operator = mf_operator; 1194 PetscFunctionReturn(0); 1195 } 1196 1197 /*@ 1198 SNESGetUseMatrixFree - indicates if the SNES uses matrix free finite difference matrix vector products to apply 1199 the Jacobian. 1200 1201 Collective on SNES 1202 1203 Input Parameter: 1204 . snes - SNES context 1205 1206 Output Parameters: 1207 + mf - use matrix-free for both the Amat and Pmat used by SNESSetJacobian(), both the Amat and Pmat set in SNESSetJacobian() will be ignored 1208 - mf_operator - use matrix-free only for the Amat used by SNESSetJacobian(), this means the user provided Pmat will continue to be used 1209 1210 Options Database: 1211 + -snes_mf - use matrix free for both the mat and pmat operator 1212 - -snes_mf_operator - use matrix free only for the mat operator 1213 1214 Level: intermediate 1215 1216 .keywords: SNES, nonlinear, get, iteration, number, 1217 1218 .seealso: SNESSetUseMatrixFree(), MatCreateSNESMF() 1219 @*/ 1220 PetscErrorCode SNESGetUseMatrixFree(SNES snes,PetscBool *mf_operator,PetscBool *mf) 1221 { 1222 PetscFunctionBegin; 1223 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1224 if (mf) *mf = snes->mf; 1225 if (mf_operator) *mf_operator = snes->mf_operator; 1226 PetscFunctionReturn(0); 1227 } 1228 1229 /*@ 1230 SNESGetIterationNumber - Gets the number of nonlinear iterations completed 1231 at this time. 1232 1233 Not Collective 1234 1235 Input Parameter: 1236 . snes - SNES context 1237 1238 Output Parameter: 1239 . iter - iteration number 1240 1241 Notes: 1242 For example, during the computation of iteration 2 this would return 1. 1243 1244 This is useful for using lagged Jacobians (where one does not recompute the 1245 Jacobian at each SNES iteration). For example, the code 1246 .vb 1247 ierr = SNESGetIterationNumber(snes,&it); 1248 if (!(it % 2)) { 1249 [compute Jacobian here] 1250 } 1251 .ve 1252 can be used in your ComputeJacobian() function to cause the Jacobian to be 1253 recomputed every second SNES iteration. 1254 1255 After the SNES solve is complete this will return the number of nonlinear iterations used. 1256 1257 Level: intermediate 1258 1259 .keywords: SNES, nonlinear, get, iteration, number, 1260 1261 .seealso: SNESGetLinearSolveIterations() 1262 @*/ 1263 PetscErrorCode SNESGetIterationNumber(SNES snes,PetscInt *iter) 1264 { 1265 PetscFunctionBegin; 1266 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1267 PetscValidIntPointer(iter,2); 1268 *iter = snes->iter; 1269 PetscFunctionReturn(0); 1270 } 1271 1272 /*@ 1273 SNESSetIterationNumber - Sets the current iteration number. 1274 1275 Not Collective 1276 1277 Input Parameter: 1278 . snes - SNES context 1279 . iter - iteration number 1280 1281 Level: developer 1282 1283 .keywords: SNES, nonlinear, set, iteration, number, 1284 1285 .seealso: SNESGetLinearSolveIterations() 1286 @*/ 1287 PetscErrorCode SNESSetIterationNumber(SNES snes,PetscInt iter) 1288 { 1289 PetscErrorCode ierr; 1290 1291 PetscFunctionBegin; 1292 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1293 ierr = PetscObjectSAWsTakeAccess((PetscObject)snes);CHKERRQ(ierr); 1294 snes->iter = iter; 1295 ierr = PetscObjectSAWsGrantAccess((PetscObject)snes);CHKERRQ(ierr); 1296 PetscFunctionReturn(0); 1297 } 1298 1299 /*@ 1300 SNESGetNonlinearStepFailures - Gets the number of unsuccessful steps 1301 attempted by the nonlinear solver. 1302 1303 Not Collective 1304 1305 Input Parameter: 1306 . snes - SNES context 1307 1308 Output Parameter: 1309 . nfails - number of unsuccessful steps attempted 1310 1311 Notes: 1312 This counter is reset to zero for each successive call to SNESSolve(). 1313 1314 Level: intermediate 1315 1316 .keywords: SNES, nonlinear, get, number, unsuccessful, steps 1317 1318 .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures(), SNESGetLinearSolveFailures(), 1319 SNESSetMaxNonlinearStepFailures(), SNESGetMaxNonlinearStepFailures() 1320 @*/ 1321 PetscErrorCode SNESGetNonlinearStepFailures(SNES snes,PetscInt *nfails) 1322 { 1323 PetscFunctionBegin; 1324 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1325 PetscValidIntPointer(nfails,2); 1326 *nfails = snes->numFailures; 1327 PetscFunctionReturn(0); 1328 } 1329 1330 /*@ 1331 SNESSetMaxNonlinearStepFailures - Sets the maximum number of unsuccessful steps 1332 attempted by the nonlinear solver before it gives up. 1333 1334 Not Collective 1335 1336 Input Parameters: 1337 + snes - SNES context 1338 - maxFails - maximum of unsuccessful steps 1339 1340 Level: intermediate 1341 1342 .keywords: SNES, nonlinear, set, maximum, unsuccessful, steps 1343 1344 .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures(), SNESGetLinearSolveFailures(), 1345 SNESGetMaxNonlinearStepFailures(), SNESGetNonlinearStepFailures() 1346 @*/ 1347 PetscErrorCode SNESSetMaxNonlinearStepFailures(SNES snes, PetscInt maxFails) 1348 { 1349 PetscFunctionBegin; 1350 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1351 snes->maxFailures = maxFails; 1352 PetscFunctionReturn(0); 1353 } 1354 1355 /*@ 1356 SNESGetMaxNonlinearStepFailures - Gets the maximum number of unsuccessful steps 1357 attempted by the nonlinear solver before it gives up. 1358 1359 Not Collective 1360 1361 Input Parameter: 1362 . snes - SNES context 1363 1364 Output Parameter: 1365 . maxFails - maximum of unsuccessful steps 1366 1367 Level: intermediate 1368 1369 .keywords: SNES, nonlinear, get, maximum, unsuccessful, steps 1370 1371 .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures(), SNESGetLinearSolveFailures(), 1372 SNESSetMaxNonlinearStepFailures(), SNESGetNonlinearStepFailures() 1373 1374 @*/ 1375 PetscErrorCode SNESGetMaxNonlinearStepFailures(SNES snes, PetscInt *maxFails) 1376 { 1377 PetscFunctionBegin; 1378 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1379 PetscValidIntPointer(maxFails,2); 1380 *maxFails = snes->maxFailures; 1381 PetscFunctionReturn(0); 1382 } 1383 1384 /*@ 1385 SNESGetNumberFunctionEvals - Gets the number of user provided function evaluations 1386 done by SNES. 1387 1388 Not Collective 1389 1390 Input Parameter: 1391 . snes - SNES context 1392 1393 Output Parameter: 1394 . nfuncs - number of evaluations 1395 1396 Level: intermediate 1397 1398 Notes: 1399 Reset every time SNESSolve is called unless SNESSetCountersReset() is used. 1400 1401 .keywords: SNES, nonlinear, get, maximum, unsuccessful, steps 1402 1403 .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures(), SNESGetLinearSolveFailures(), SNESSetCountersReset() 1404 @*/ 1405 PetscErrorCode SNESGetNumberFunctionEvals(SNES snes, PetscInt *nfuncs) 1406 { 1407 PetscFunctionBegin; 1408 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1409 PetscValidIntPointer(nfuncs,2); 1410 *nfuncs = snes->nfuncs; 1411 PetscFunctionReturn(0); 1412 } 1413 1414 /*@ 1415 SNESGetLinearSolveFailures - Gets the number of failed (non-converged) 1416 linear solvers. 1417 1418 Not Collective 1419 1420 Input Parameter: 1421 . snes - SNES context 1422 1423 Output Parameter: 1424 . nfails - number of failed solves 1425 1426 Level: intermediate 1427 1428 Options Database Keys: 1429 . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated 1430 1431 Notes: 1432 This counter is reset to zero for each successive call to SNESSolve(). 1433 1434 .keywords: SNES, nonlinear, get, number, unsuccessful, steps 1435 1436 .seealso: SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures() 1437 @*/ 1438 PetscErrorCode SNESGetLinearSolveFailures(SNES snes,PetscInt *nfails) 1439 { 1440 PetscFunctionBegin; 1441 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1442 PetscValidIntPointer(nfails,2); 1443 *nfails = snes->numLinearSolveFailures; 1444 PetscFunctionReturn(0); 1445 } 1446 1447 /*@ 1448 SNESSetMaxLinearSolveFailures - the number of failed linear solve attempts 1449 allowed before SNES returns with a diverged reason of SNES_DIVERGED_LINEAR_SOLVE 1450 1451 Logically Collective on SNES 1452 1453 Input Parameters: 1454 + snes - SNES context 1455 - maxFails - maximum allowed linear solve failures 1456 1457 Level: intermediate 1458 1459 Options Database Keys: 1460 . -snes_max_linear_solve_fail <num> - The number of failures before the solve is terminated 1461 1462 Notes: 1463 By default this is 0; that is SNES returns on the first failed linear solve 1464 1465 .keywords: SNES, nonlinear, set, maximum, unsuccessful, steps 1466 1467 .seealso: SNESGetLinearSolveFailures(), SNESGetMaxLinearSolveFailures(), SNESGetLinearSolveIterations() 1468 @*/ 1469 PetscErrorCode SNESSetMaxLinearSolveFailures(SNES snes, PetscInt maxFails) 1470 { 1471 PetscFunctionBegin; 1472 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1473 PetscValidLogicalCollectiveInt(snes,maxFails,2); 1474 snes->maxLinearSolveFailures = maxFails; 1475 PetscFunctionReturn(0); 1476 } 1477 1478 /*@ 1479 SNESGetMaxLinearSolveFailures - gets the maximum number of linear solve failures that 1480 are allowed before SNES terminates 1481 1482 Not Collective 1483 1484 Input Parameter: 1485 . snes - SNES context 1486 1487 Output Parameter: 1488 . maxFails - maximum of unsuccessful solves allowed 1489 1490 Level: intermediate 1491 1492 Notes: 1493 By default this is 1; that is SNES returns on the first failed linear solve 1494 1495 .keywords: SNES, nonlinear, get, maximum, unsuccessful, steps 1496 1497 .seealso: SNESGetLinearSolveFailures(), SNESGetLinearSolveIterations(), SNESSetMaxLinearSolveFailures(), 1498 @*/ 1499 PetscErrorCode SNESGetMaxLinearSolveFailures(SNES snes, PetscInt *maxFails) 1500 { 1501 PetscFunctionBegin; 1502 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1503 PetscValidIntPointer(maxFails,2); 1504 *maxFails = snes->maxLinearSolveFailures; 1505 PetscFunctionReturn(0); 1506 } 1507 1508 /*@ 1509 SNESGetLinearSolveIterations - Gets the total number of linear iterations 1510 used by the nonlinear solver. 1511 1512 Not Collective 1513 1514 Input Parameter: 1515 . snes - SNES context 1516 1517 Output Parameter: 1518 . lits - number of linear iterations 1519 1520 Notes: 1521 This counter is reset to zero for each successive call to SNESSolve() unless SNESSetCountersReset() is used. 1522 1523 If the linear solver fails inside the SNESSolve() the iterations for that call to the linear solver are not included. If you wish to count them 1524 then call KSPGetIterationNumber() after the failed solve. 1525 1526 Level: intermediate 1527 1528 .keywords: SNES, nonlinear, get, number, linear, iterations 1529 1530 .seealso: SNESGetIterationNumber(), SNESGetLinearSolveFailures(), SNESGetMaxLinearSolveFailures(), SNESSetCountersReset() 1531 @*/ 1532 PetscErrorCode SNESGetLinearSolveIterations(SNES snes,PetscInt *lits) 1533 { 1534 PetscFunctionBegin; 1535 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1536 PetscValidIntPointer(lits,2); 1537 *lits = snes->linear_its; 1538 PetscFunctionReturn(0); 1539 } 1540 1541 /*@ 1542 SNESSetCountersReset - Sets whether or not the counters for linear iterations and function evaluations 1543 are reset every time SNESSolve() is called. 1544 1545 Logically Collective on SNES 1546 1547 Input Parameter: 1548 + snes - SNES context 1549 - reset - whether to reset the counters or not 1550 1551 Notes: 1552 This defaults to PETSC_TRUE 1553 1554 Level: developer 1555 1556 .keywords: SNES, nonlinear, set, reset, number, linear, iterations 1557 1558 .seealso: SNESGetNumberFunctionEvals(), SNESGetLinearSolveIterations(), SNESGetNPC() 1559 @*/ 1560 PetscErrorCode SNESSetCountersReset(SNES snes,PetscBool reset) 1561 { 1562 PetscFunctionBegin; 1563 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1564 PetscValidLogicalCollectiveBool(snes,reset,2); 1565 snes->counters_reset = reset; 1566 PetscFunctionReturn(0); 1567 } 1568 1569 1570 /*@ 1571 SNESSetKSP - Sets a KSP context for the SNES object to use 1572 1573 Not Collective, but the SNES and KSP objects must live on the same MPI_Comm 1574 1575 Input Parameters: 1576 + snes - the SNES context 1577 - ksp - the KSP context 1578 1579 Notes: 1580 The SNES object already has its KSP object, you can obtain with SNESGetKSP() 1581 so this routine is rarely needed. 1582 1583 The KSP object that is already in the SNES object has its reference count 1584 decreased by one. 1585 1586 Level: developer 1587 1588 .keywords: SNES, nonlinear, get, KSP, context 1589 1590 .seealso: KSPGetPC(), SNESCreate(), KSPCreate(), SNESSetKSP() 1591 @*/ 1592 PetscErrorCode SNESSetKSP(SNES snes,KSP ksp) 1593 { 1594 PetscErrorCode ierr; 1595 1596 PetscFunctionBegin; 1597 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1598 PetscValidHeaderSpecific(ksp,KSP_CLASSID,2); 1599 PetscCheckSameComm(snes,1,ksp,2); 1600 ierr = PetscObjectReference((PetscObject)ksp);CHKERRQ(ierr); 1601 if (snes->ksp) {ierr = PetscObjectDereference((PetscObject)snes->ksp);CHKERRQ(ierr);} 1602 snes->ksp = ksp; 1603 PetscFunctionReturn(0); 1604 } 1605 1606 /* -----------------------------------------------------------*/ 1607 /*@ 1608 SNESCreate - Creates a nonlinear solver context. 1609 1610 Collective on MPI_Comm 1611 1612 Input Parameters: 1613 . comm - MPI communicator 1614 1615 Output Parameter: 1616 . outsnes - the new SNES context 1617 1618 Options Database Keys: 1619 + -snes_mf - Activates default matrix-free Jacobian-vector products, 1620 and no preconditioning matrix 1621 . -snes_mf_operator - Activates default matrix-free Jacobian-vector 1622 products, and a user-provided preconditioning matrix 1623 as set by SNESSetJacobian() 1624 - -snes_fd - Uses (slow!) finite differences to compute Jacobian 1625 1626 Level: beginner 1627 1628 Developer Notes: 1629 SNES always creates a KSP object even though many SNES methods do not use it. This is 1630 unfortunate and should be fixed at some point. The flag snes->usesksp indicates if the 1631 particular method does use KSP and regulates if the information about the KSP is printed 1632 in SNESView(). TSSetFromOptions() does call SNESSetFromOptions() which can lead to users being confused 1633 by help messages about meaningless SNES options. 1634 1635 SNES always creates the snes->kspconvctx even though it is used by only one type. This should 1636 be fixed. 1637 1638 .keywords: SNES, nonlinear, create, context 1639 1640 .seealso: SNESSolve(), SNESDestroy(), SNES, SNESSetLagPreconditioner() 1641 1642 @*/ 1643 PetscErrorCode SNESCreate(MPI_Comm comm,SNES *outsnes) 1644 { 1645 PetscErrorCode ierr; 1646 SNES snes; 1647 SNESKSPEW *kctx; 1648 1649 PetscFunctionBegin; 1650 PetscValidPointer(outsnes,2); 1651 *outsnes = NULL; 1652 ierr = SNESInitializePackage();CHKERRQ(ierr); 1653 1654 ierr = PetscHeaderCreate(snes,SNES_CLASSID,"SNES","Nonlinear solver","SNES",comm,SNESDestroy,SNESView);CHKERRQ(ierr); 1655 1656 snes->ops->converged = SNESConvergedDefault; 1657 snes->usesksp = PETSC_TRUE; 1658 snes->tolerancesset = PETSC_FALSE; 1659 snes->max_its = 50; 1660 snes->max_funcs = 10000; 1661 snes->norm = 0.0; 1662 snes->xnorm = 0.0; 1663 snes->ynorm = 0.0; 1664 snes->normschedule = SNES_NORM_ALWAYS; 1665 snes->functype = SNES_FUNCTION_DEFAULT; 1666 #if defined(PETSC_USE_REAL_SINGLE) 1667 snes->rtol = 1.e-5; 1668 #else 1669 snes->rtol = 1.e-8; 1670 #endif 1671 snes->ttol = 0.0; 1672 #if defined(PETSC_USE_REAL_SINGLE) 1673 snes->abstol = 1.e-25; 1674 #else 1675 snes->abstol = 1.e-50; 1676 #endif 1677 #if defined(PETSC_USE_REAL_SINGLE) 1678 snes->stol = 1.e-5; 1679 #else 1680 snes->stol = 1.e-8; 1681 #endif 1682 #if defined(PETSC_USE_REAL_SINGLE) 1683 snes->deltatol = 1.e-6; 1684 #else 1685 snes->deltatol = 1.e-12; 1686 #endif 1687 snes->divtol = 1.e4; 1688 snes->rnorm0 = 0; 1689 snes->nfuncs = 0; 1690 snes->numFailures = 0; 1691 snes->maxFailures = 1; 1692 snes->linear_its = 0; 1693 snes->lagjacobian = 1; 1694 snes->jac_iter = 0; 1695 snes->lagjac_persist = PETSC_FALSE; 1696 snes->lagpreconditioner = 1; 1697 snes->pre_iter = 0; 1698 snes->lagpre_persist = PETSC_FALSE; 1699 snes->numbermonitors = 0; 1700 snes->data = 0; 1701 snes->setupcalled = PETSC_FALSE; 1702 snes->ksp_ewconv = PETSC_FALSE; 1703 snes->nwork = 0; 1704 snes->work = 0; 1705 snes->nvwork = 0; 1706 snes->vwork = 0; 1707 snes->conv_hist_len = 0; 1708 snes->conv_hist_max = 0; 1709 snes->conv_hist = NULL; 1710 snes->conv_hist_its = NULL; 1711 snes->conv_hist_reset = PETSC_TRUE; 1712 snes->counters_reset = PETSC_TRUE; 1713 snes->vec_func_init_set = PETSC_FALSE; 1714 snes->reason = SNES_CONVERGED_ITERATING; 1715 snes->npcside = PC_RIGHT; 1716 snes->setfromoptionscalled = 0; 1717 1718 snes->mf = PETSC_FALSE; 1719 snes->mf_operator = PETSC_FALSE; 1720 snes->mf_version = 1; 1721 1722 snes->numLinearSolveFailures = 0; 1723 snes->maxLinearSolveFailures = 1; 1724 1725 snes->vizerotolerance = 1.e-8; 1726 1727 /* Set this to true if the implementation of SNESSolve_XXX does compute the residual at the final solution. */ 1728 snes->alwayscomputesfinalresidual = PETSC_FALSE; 1729 1730 /* Create context to compute Eisenstat-Walker relative tolerance for KSP */ 1731 ierr = PetscNewLog(snes,&kctx);CHKERRQ(ierr); 1732 1733 snes->kspconvctx = (void*)kctx; 1734 kctx->version = 2; 1735 kctx->rtol_0 = .3; /* Eisenstat and Walker suggest rtol_0=.5, but 1736 this was too large for some test cases */ 1737 kctx->rtol_last = 0.0; 1738 kctx->rtol_max = .9; 1739 kctx->gamma = 1.0; 1740 kctx->alpha = .5*(1.0 + PetscSqrtReal(5.0)); 1741 kctx->alpha2 = kctx->alpha; 1742 kctx->threshold = .1; 1743 kctx->lresid_last = 0.0; 1744 kctx->norm_last = 0.0; 1745 1746 *outsnes = snes; 1747 PetscFunctionReturn(0); 1748 } 1749 1750 /*MC 1751 SNESFunction - Functional form used to convey the nonlinear function to be solved by SNES 1752 1753 Synopsis: 1754 #include "petscsnes.h" 1755 PetscErrorCode SNESFunction(SNES snes,Vec x,Vec f,void *ctx); 1756 1757 Input Parameters: 1758 + snes - the SNES context 1759 . x - state at which to evaluate residual 1760 - ctx - optional user-defined function context, passed in with SNESSetFunction() 1761 1762 Output Parameter: 1763 . f - vector to put residual (function value) 1764 1765 Level: intermediate 1766 1767 .seealso: SNESSetFunction(), SNESGetFunction() 1768 M*/ 1769 1770 /*@C 1771 SNESSetFunction - Sets the function evaluation routine and function 1772 vector for use by the SNES routines in solving systems of nonlinear 1773 equations. 1774 1775 Logically Collective on SNES 1776 1777 Input Parameters: 1778 + snes - the SNES context 1779 . r - vector to store function value 1780 . f - function evaluation routine; see SNESFunction for calling sequence details 1781 - ctx - [optional] user-defined context for private data for the 1782 function evaluation routine (may be NULL) 1783 1784 Notes: 1785 The Newton-like methods typically solve linear systems of the form 1786 $ f'(x) x = -f(x), 1787 where f'(x) denotes the Jacobian matrix and f(x) is the function. 1788 1789 Level: beginner 1790 1791 .keywords: SNES, nonlinear, set, function 1792 1793 .seealso: SNESGetFunction(), SNESComputeFunction(), SNESSetJacobian(), SNESSetPicard(), SNESFunction 1794 @*/ 1795 PetscErrorCode SNESSetFunction(SNES snes,Vec r,PetscErrorCode (*f)(SNES,Vec,Vec,void*),void *ctx) 1796 { 1797 PetscErrorCode ierr; 1798 DM dm; 1799 1800 PetscFunctionBegin; 1801 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1802 if (r) { 1803 PetscValidHeaderSpecific(r,VEC_CLASSID,2); 1804 PetscCheckSameComm(snes,1,r,2); 1805 ierr = PetscObjectReference((PetscObject)r);CHKERRQ(ierr); 1806 ierr = VecDestroy(&snes->vec_func);CHKERRQ(ierr); 1807 1808 snes->vec_func = r; 1809 } 1810 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 1811 ierr = DMSNESSetFunction(dm,f,ctx);CHKERRQ(ierr); 1812 PetscFunctionReturn(0); 1813 } 1814 1815 1816 /*@C 1817 SNESSetInitialFunction - Sets the function vector to be used as the 1818 function norm at the initialization of the method. In some 1819 instances, the user has precomputed the function before calling 1820 SNESSolve. This function allows one to avoid a redundant call 1821 to SNESComputeFunction in that case. 1822 1823 Logically Collective on SNES 1824 1825 Input Parameters: 1826 + snes - the SNES context 1827 - f - vector to store function value 1828 1829 Notes: 1830 This should not be modified during the solution procedure. 1831 1832 This is used extensively in the SNESFAS hierarchy and in nonlinear preconditioning. 1833 1834 Level: developer 1835 1836 .keywords: SNES, nonlinear, set, function 1837 1838 .seealso: SNESSetFunction(), SNESComputeFunction(), SNESSetInitialFunctionNorm() 1839 @*/ 1840 PetscErrorCode SNESSetInitialFunction(SNES snes, Vec f) 1841 { 1842 PetscErrorCode ierr; 1843 Vec vec_func; 1844 1845 PetscFunctionBegin; 1846 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1847 PetscValidHeaderSpecific(f,VEC_CLASSID,2); 1848 PetscCheckSameComm(snes,1,f,2); 1849 if (snes->npcside== PC_LEFT && snes->functype == SNES_FUNCTION_PRECONDITIONED) { 1850 snes->vec_func_init_set = PETSC_FALSE; 1851 PetscFunctionReturn(0); 1852 } 1853 ierr = SNESGetFunction(snes,&vec_func,NULL,NULL);CHKERRQ(ierr); 1854 ierr = VecCopy(f, vec_func);CHKERRQ(ierr); 1855 1856 snes->vec_func_init_set = PETSC_TRUE; 1857 PetscFunctionReturn(0); 1858 } 1859 1860 /*@ 1861 SNESSetNormSchedule - Sets the SNESNormSchedule used in covergence and monitoring 1862 of the SNES method. 1863 1864 Logically Collective on SNES 1865 1866 Input Parameters: 1867 + snes - the SNES context 1868 - normschedule - the frequency of norm computation 1869 1870 Options Database Key: 1871 . -snes_norm_schedule <none, always, initialonly, finalonly, initalfinalonly> 1872 1873 Notes: 1874 Only certain SNES methods support certain SNESNormSchedules. Most require evaluation 1875 of the nonlinear function and the taking of its norm at every iteration to 1876 even ensure convergence at all. However, methods such as custom Gauss-Seidel methods 1877 (SNESNGS) and the like do not require the norm of the function to be computed, and therfore 1878 may either be monitored for convergence or not. As these are often used as nonlinear 1879 preconditioners, monitoring the norm of their error is not a useful enterprise within 1880 their solution. 1881 1882 Level: developer 1883 1884 .keywords: SNES, nonlinear, set, function, norm, type 1885 1886 .seealso: SNESGetNormSchedule(), SNESComputeFunction(), VecNorm(), SNESSetFunction(), SNESSetInitialFunction(), SNESNormSchedule 1887 @*/ 1888 PetscErrorCode SNESSetNormSchedule(SNES snes, SNESNormSchedule normschedule) 1889 { 1890 PetscFunctionBegin; 1891 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1892 snes->normschedule = normschedule; 1893 PetscFunctionReturn(0); 1894 } 1895 1896 1897 /*@ 1898 SNESGetNormSchedule - Gets the SNESNormSchedule used in covergence and monitoring 1899 of the SNES method. 1900 1901 Logically Collective on SNES 1902 1903 Input Parameters: 1904 + snes - the SNES context 1905 - normschedule - the type of the norm used 1906 1907 Level: advanced 1908 1909 .keywords: SNES, nonlinear, set, function, norm, type 1910 1911 .seealso: SNESSetNormSchedule(), SNESComputeFunction(), VecNorm(), SNESSetFunction(), SNESSetInitialFunction(), SNESNormSchedule 1912 @*/ 1913 PetscErrorCode SNESGetNormSchedule(SNES snes, SNESNormSchedule *normschedule) 1914 { 1915 PetscFunctionBegin; 1916 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1917 *normschedule = snes->normschedule; 1918 PetscFunctionReturn(0); 1919 } 1920 1921 1922 /*@ 1923 SNESSetFunctionNorm - Sets the last computed residual norm. 1924 1925 Logically Collective on SNES 1926 1927 Input Parameters: 1928 + snes - the SNES context 1929 1930 - normschedule - the frequency of norm computation 1931 1932 Level: developer 1933 1934 .keywords: SNES, nonlinear, set, function, norm, type 1935 .seealso: SNESGetNormSchedule(), SNESComputeFunction(), VecNorm(), SNESSetFunction(), SNESSetInitialFunction(), SNESNormSchedule 1936 @*/ 1937 PetscErrorCode SNESSetFunctionNorm(SNES snes, PetscReal norm) 1938 { 1939 PetscFunctionBegin; 1940 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1941 snes->norm = norm; 1942 PetscFunctionReturn(0); 1943 } 1944 1945 /*@ 1946 SNESGetFunctionNorm - Gets the last computed norm of the residual 1947 1948 Not Collective 1949 1950 Input Parameter: 1951 . snes - the SNES context 1952 1953 Output Parameter: 1954 . norm - the last computed residual norm 1955 1956 Level: developer 1957 1958 .keywords: SNES, nonlinear, set, function, norm, type 1959 .seealso: SNESSetNormSchedule(), SNESComputeFunction(), VecNorm(), SNESSetFunction(), SNESSetInitialFunction(), SNESNormSchedule 1960 @*/ 1961 PetscErrorCode SNESGetFunctionNorm(SNES snes, PetscReal *norm) 1962 { 1963 PetscFunctionBegin; 1964 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1965 PetscValidPointer(norm, 2); 1966 *norm = snes->norm; 1967 PetscFunctionReturn(0); 1968 } 1969 1970 /*@ 1971 SNESGetUpdateNorm - Gets the last computed norm of the Newton update 1972 1973 Not Collective 1974 1975 Input Parameter: 1976 . snes - the SNES context 1977 1978 Output Parameter: 1979 . ynorm - the last computed update norm 1980 1981 Level: developer 1982 1983 .keywords: SNES, nonlinear, set, function, norm, type 1984 .seealso: SNESSetNormSchedule(), SNESComputeFunction(), SNESGetFunctionNorm() 1985 @*/ 1986 PetscErrorCode SNESGetUpdateNorm(SNES snes, PetscReal *ynorm) 1987 { 1988 PetscFunctionBegin; 1989 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 1990 PetscValidPointer(ynorm, 2); 1991 *ynorm = snes->ynorm; 1992 PetscFunctionReturn(0); 1993 } 1994 1995 /*@ 1996 SNESGetSolutionNorm - Gets the last computed norm of the solution 1997 1998 Not Collective 1999 2000 Input Parameter: 2001 . snes - the SNES context 2002 2003 Output Parameter: 2004 . xnorm - the last computed solution norm 2005 2006 Level: developer 2007 2008 .keywords: SNES, nonlinear, set, function, norm, type 2009 .seealso: SNESSetNormSchedule(), SNESComputeFunction(), SNESGetFunctionNorm(), SNESGetUpdateNorm() 2010 @*/ 2011 PetscErrorCode SNESGetSolutionNorm(SNES snes, PetscReal *xnorm) 2012 { 2013 PetscFunctionBegin; 2014 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 2015 PetscValidPointer(xnorm, 2); 2016 *xnorm = snes->xnorm; 2017 PetscFunctionReturn(0); 2018 } 2019 2020 /*@C 2021 SNESSetFunctionType - Sets the SNESNormSchedule used in covergence and monitoring 2022 of the SNES method. 2023 2024 Logically Collective on SNES 2025 2026 Input Parameters: 2027 + snes - the SNES context 2028 - normschedule - the frequency of norm computation 2029 2030 Notes: 2031 Only certain SNES methods support certain SNESNormSchedules. Most require evaluation 2032 of the nonlinear function and the taking of its norm at every iteration to 2033 even ensure convergence at all. However, methods such as custom Gauss-Seidel methods 2034 (SNESNGS) and the like do not require the norm of the function to be computed, and therfore 2035 may either be monitored for convergence or not. As these are often used as nonlinear 2036 preconditioners, monitoring the norm of their error is not a useful enterprise within 2037 their solution. 2038 2039 Level: developer 2040 2041 .keywords: SNES, nonlinear, set, function, norm, type 2042 2043 .seealso: SNESGetNormSchedule(), SNESComputeFunction(), VecNorm(), SNESSetFunction(), SNESSetInitialFunction(), SNESNormSchedule 2044 @*/ 2045 PetscErrorCode SNESSetFunctionType(SNES snes, SNESFunctionType type) 2046 { 2047 PetscFunctionBegin; 2048 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 2049 snes->functype = type; 2050 PetscFunctionReturn(0); 2051 } 2052 2053 2054 /*@C 2055 SNESGetFunctionType - Gets the SNESNormSchedule used in covergence and monitoring 2056 of the SNES method. 2057 2058 Logically Collective on SNES 2059 2060 Input Parameters: 2061 + snes - the SNES context 2062 - normschedule - the type of the norm used 2063 2064 Level: advanced 2065 2066 .keywords: SNES, nonlinear, set, function, norm, type 2067 2068 .seealso: SNESSetNormSchedule(), SNESComputeFunction(), VecNorm(), SNESSetFunction(), SNESSetInitialFunction(), SNESNormSchedule 2069 @*/ 2070 PetscErrorCode SNESGetFunctionType(SNES snes, SNESFunctionType *type) 2071 { 2072 PetscFunctionBegin; 2073 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 2074 *type = snes->functype; 2075 PetscFunctionReturn(0); 2076 } 2077 2078 /*MC 2079 SNESNGSFunction - function used to convey a Gauss-Seidel sweep on the nonlinear function 2080 2081 Synopsis: 2082 #include <petscsnes.h> 2083 $ SNESNGSFunction(SNES snes,Vec x,Vec b,void *ctx); 2084 2085 + X - solution vector 2086 . B - RHS vector 2087 - ctx - optional user-defined Gauss-Seidel context 2088 2089 Level: intermediate 2090 2091 .seealso: SNESSetNGS(), SNESGetNGS() 2092 M*/ 2093 2094 /*@C 2095 SNESSetNGS - Sets the user nonlinear Gauss-Seidel routine for 2096 use with composed nonlinear solvers. 2097 2098 Input Parameters: 2099 + snes - the SNES context 2100 . f - function evaluation routine to apply Gauss-Seidel see SNESNGSFunction 2101 - ctx - [optional] user-defined context for private data for the 2102 smoother evaluation routine (may be NULL) 2103 2104 Notes: 2105 The NGS routines are used by the composed nonlinear solver to generate 2106 a problem appropriate update to the solution, particularly FAS. 2107 2108 Level: intermediate 2109 2110 .keywords: SNES, nonlinear, set, Gauss-Seidel 2111 2112 .seealso: SNESGetFunction(), SNESComputeNGS() 2113 @*/ 2114 PetscErrorCode SNESSetNGS(SNES snes,PetscErrorCode (*f)(SNES,Vec,Vec,void*),void *ctx) 2115 { 2116 PetscErrorCode ierr; 2117 DM dm; 2118 2119 PetscFunctionBegin; 2120 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 2121 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 2122 ierr = DMSNESSetNGS(dm,f,ctx);CHKERRQ(ierr); 2123 PetscFunctionReturn(0); 2124 } 2125 2126 PetscErrorCode SNESPicardComputeFunction(SNES snes,Vec x,Vec f,void *ctx) 2127 { 2128 PetscErrorCode ierr; 2129 DM dm; 2130 DMSNES sdm; 2131 2132 PetscFunctionBegin; 2133 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 2134 ierr = DMGetDMSNES(dm,&sdm);CHKERRQ(ierr); 2135 if (!sdm->ops->computepfunction) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetPicard() to provide Picard function."); 2136 if (!sdm->ops->computepjacobian) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetPicard() to provide Picard Jacobian."); 2137 /* A(x)*x - b(x) */ 2138 PetscStackPush("SNES Picard user function"); 2139 ierr = (*sdm->ops->computepfunction)(snes,x,f,sdm->pctx);CHKERRQ(ierr); 2140 PetscStackPop; 2141 PetscStackPush("SNES Picard user Jacobian"); 2142 ierr = (*sdm->ops->computepjacobian)(snes,x,snes->jacobian,snes->jacobian_pre,sdm->pctx);CHKERRQ(ierr); 2143 PetscStackPop; 2144 ierr = VecScale(f,-1.0);CHKERRQ(ierr); 2145 ierr = MatMultAdd(snes->jacobian,x,f,f);CHKERRQ(ierr); 2146 PetscFunctionReturn(0); 2147 } 2148 2149 PetscErrorCode SNESPicardComputeJacobian(SNES snes,Vec x1,Mat J,Mat B,void *ctx) 2150 { 2151 PetscFunctionBegin; 2152 /* the jacobian matrix should be pre-filled in SNESPicardComputeFunction */ 2153 PetscFunctionReturn(0); 2154 } 2155 2156 /*@C 2157 SNESSetPicard - Use SNES to solve the semilinear-system A(x) x = b(x) via a Picard type iteration (Picard linearization) 2158 2159 Logically Collective on SNES 2160 2161 Input Parameters: 2162 + snes - the SNES context 2163 . r - vector to store function value 2164 . b - function evaluation routine 2165 . Amat - matrix with which A(x) x - b(x) is to be computed 2166 . Pmat - matrix from which preconditioner is computed (usually the same as Amat) 2167 . J - function to compute matrix value, see SNESJacobianFunction for details on its calling sequence 2168 - ctx - [optional] user-defined context for private data for the 2169 function evaluation routine (may be NULL) 2170 2171 Notes: 2172 We do not recomemend using this routine. It is far better to provide the nonlinear function F() and some approximation to the Jacobian and use 2173 an approximate Newton solver. This interface is provided to allow porting/testing a previous Picard based code in PETSc before converting it to approximate Newton. 2174 2175 One can call SNESSetPicard() or SNESSetFunction() (and possibly SNESSetJacobian()) but cannot call both 2176 2177 $ Solves the equation A(x) x = b(x) via the defect correction algorithm A(x^{n}) (x^{n+1} - x^{n}) = b(x^{n}) - A(x^{n})x^{n} 2178 $ Note that when an exact solver is used this corresponds to the "classic" Picard A(x^{n}) x^{n+1} = b(x^{n}) iteration. 2179 2180 Run with -snes_mf_operator to solve the system with Newton's method using A(x^{n}) to construct the preconditioner. 2181 2182 We implement the defect correction form of the Picard iteration because it converges much more generally when inexact linear solvers are used then 2183 the direct Picard iteration A(x^n) x^{n+1} = b(x^n) 2184 2185 There is some controversity over the definition of a Picard iteration for nonlinear systems but almost everyone agrees that it involves a linear solve and some 2186 believe it is the iteration A(x^{n}) x^{n+1} = b(x^{n}) hence we use the name Picard. If anyone has an authoritative reference that defines the Picard iteration 2187 different please contact us at petsc-dev@mcs.anl.gov and we'll have an entirely new argument :-). 2188 2189 Level: intermediate 2190 2191 .keywords: SNES, nonlinear, set, function 2192 2193 .seealso: SNESGetFunction(), SNESSetFunction(), SNESComputeFunction(), SNESSetJacobian(), SNESGetPicard(), SNESLineSearchPreCheckPicard(), SNESJacobianFunction 2194 @*/ 2195 PetscErrorCode SNESSetPicard(SNES snes,Vec r,PetscErrorCode (*b)(SNES,Vec,Vec,void*),Mat Amat, Mat Pmat, PetscErrorCode (*J)(SNES,Vec,Mat,Mat,void*),void *ctx) 2196 { 2197 PetscErrorCode ierr; 2198 DM dm; 2199 2200 PetscFunctionBegin; 2201 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 2202 ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr); 2203 ierr = DMSNESSetPicard(dm,b,J,ctx);CHKERRQ(ierr); 2204 ierr = SNESSetFunction(snes,r,SNESPicardComputeFunction,ctx);CHKERRQ(ierr); 2205 ierr = SNESSetJacobian(snes,Amat,Pmat,SNESPicardComputeJacobian,ctx);CHKERRQ(ierr); 2206 PetscFunctionReturn(0); 2207 } 2208 2209 /*@C 2210 SNESGetPicard - Returns the context for the Picard iteration 2211 2212 Not Collective, but Vec is parallel if SNES is parallel. Collective if Vec is requested, but has not been created yet. 2213 2214 Input Parameter: 2215 . snes - the SNES context 2216 2217 Output Parameter: 2218 + r - the function (or NULL) 2219 . f - the function (or NULL); see SNESFunction for calling sequence details 2220 . Amat - the matrix used to defined the operation A(x) x - b(x) (or NULL) 2221 . Pmat - the matrix from which the preconditioner will be constructed (or NULL) 2222 . J - the function for matrix evaluation (or NULL); see SNESJacobianFunction for calling sequence details 2223 - ctx - the function context (or NULL) 2224 2225 Level: advanced 2226 2227 .keywords: SNES, nonlinear, get, function 2228 2229 .seealso: SNESSetPicard(), SNESGetFunction(), SNESGetJacobian(), SNESGetDM(), SNESFunction, SNESJacobianFunction 2230 @*/ 2231 PetscErrorCode SNESGetPicard(SNES snes,Vec *r,PetscErrorCode (**f)(SNES,Vec,Vec,void*),Mat *Amat, Mat *Pmat, PetscErrorCode (**J)(SNES,Vec,Mat,Mat,void*),void **ctx) 2232 { 2233 PetscErrorCode ierr; 2234 DM dm; 2235 2236 PetscFunctionBegin; 2237 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 2238 ierr = SNESGetFunction(snes,r,NULL,NULL);CHKERRQ(ierr); 2239 ierr = SNESGetJacobian(snes,Amat,Pmat,NULL,NULL);CHKERRQ(ierr); 2240 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 2241 ierr = DMSNESGetPicard(dm,f,J,ctx);CHKERRQ(ierr); 2242 PetscFunctionReturn(0); 2243 } 2244 2245 /*@C 2246 SNESSetComputeInitialGuess - Sets a routine used to compute an initial guess for the problem 2247 2248 Logically Collective on SNES 2249 2250 Input Parameters: 2251 + snes - the SNES context 2252 . func - function evaluation routine 2253 - ctx - [optional] user-defined context for private data for the 2254 function evaluation routine (may be NULL) 2255 2256 Calling sequence of func: 2257 $ func (SNES snes,Vec x,void *ctx); 2258 2259 . f - function vector 2260 - ctx - optional user-defined function context 2261 2262 Level: intermediate 2263 2264 .keywords: SNES, nonlinear, set, function 2265 2266 .seealso: SNESGetFunction(), SNESComputeFunction(), SNESSetJacobian() 2267 @*/ 2268 PetscErrorCode SNESSetComputeInitialGuess(SNES snes,PetscErrorCode (*func)(SNES,Vec,void*),void *ctx) 2269 { 2270 PetscFunctionBegin; 2271 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 2272 if (func) snes->ops->computeinitialguess = func; 2273 if (ctx) snes->initialguessP = ctx; 2274 PetscFunctionReturn(0); 2275 } 2276 2277 /* --------------------------------------------------------------- */ 2278 /*@C 2279 SNESGetRhs - Gets the vector for solving F(x) = rhs. If rhs is not set 2280 it assumes a zero right hand side. 2281 2282 Logically Collective on SNES 2283 2284 Input Parameter: 2285 . snes - the SNES context 2286 2287 Output Parameter: 2288 . rhs - the right hand side vector or NULL if the right hand side vector is null 2289 2290 Level: intermediate 2291 2292 .keywords: SNES, nonlinear, get, function, right hand side 2293 2294 .seealso: SNESGetSolution(), SNESGetFunction(), SNESComputeFunction(), SNESSetJacobian(), SNESSetFunction() 2295 @*/ 2296 PetscErrorCode SNESGetRhs(SNES snes,Vec *rhs) 2297 { 2298 PetscFunctionBegin; 2299 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 2300 PetscValidPointer(rhs,2); 2301 *rhs = snes->vec_rhs; 2302 PetscFunctionReturn(0); 2303 } 2304 2305 /*@ 2306 SNESComputeFunction - Calls the function that has been set with SNESSetFunction(). 2307 2308 Collective on SNES 2309 2310 Input Parameters: 2311 + snes - the SNES context 2312 - x - input vector 2313 2314 Output Parameter: 2315 . y - function vector, as set by SNESSetFunction() 2316 2317 Notes: 2318 SNESComputeFunction() is typically used within nonlinear solvers 2319 implementations, so most users would not generally call this routine 2320 themselves. 2321 2322 Level: developer 2323 2324 .keywords: SNES, nonlinear, compute, function 2325 2326 .seealso: SNESSetFunction(), SNESGetFunction() 2327 @*/ 2328 PetscErrorCode SNESComputeFunction(SNES snes,Vec x,Vec y) 2329 { 2330 PetscErrorCode ierr; 2331 DM dm; 2332 DMSNES sdm; 2333 2334 PetscFunctionBegin; 2335 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 2336 PetscValidHeaderSpecific(x,VEC_CLASSID,2); 2337 PetscValidHeaderSpecific(y,VEC_CLASSID,3); 2338 PetscCheckSameComm(snes,1,x,2); 2339 PetscCheckSameComm(snes,1,y,3); 2340 ierr = VecValidValues(x,2,PETSC_TRUE);CHKERRQ(ierr); 2341 2342 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 2343 ierr = DMGetDMSNES(dm,&sdm);CHKERRQ(ierr); 2344 if (sdm->ops->computefunction) { 2345 if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) { 2346 ierr = PetscLogEventBegin(SNES_FunctionEval,snes,x,y,0);CHKERRQ(ierr); 2347 } 2348 ierr = VecLockPush(x);CHKERRQ(ierr); 2349 PetscStackPush("SNES user function"); 2350 ierr = (*sdm->ops->computefunction)(snes,x,y,sdm->functionctx);CHKERRQ(ierr); 2351 PetscStackPop; 2352 ierr = VecLockPop(x);CHKERRQ(ierr); 2353 if (sdm->ops->computefunction != SNESObjectiveComputeFunctionDefaultFD) { 2354 ierr = PetscLogEventEnd(SNES_FunctionEval,snes,x,y,0);CHKERRQ(ierr); 2355 } 2356 } else if (snes->vec_rhs) { 2357 ierr = MatMult(snes->jacobian, x, y);CHKERRQ(ierr); 2358 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetFunction() or SNESSetDM() before SNESComputeFunction(), likely called from SNESSolve()."); 2359 if (snes->vec_rhs) { 2360 ierr = VecAXPY(y,-1.0,snes->vec_rhs);CHKERRQ(ierr); 2361 } 2362 snes->nfuncs++; 2363 /* 2364 domainerror might not be set on all processes; so we tag vector locally with Inf and the next inner product or norm will 2365 propagate the value to all processes 2366 */ 2367 if (snes->domainerror) { 2368 ierr = VecSetInf(y);CHKERRQ(ierr); 2369 } 2370 PetscFunctionReturn(0); 2371 } 2372 2373 /*@ 2374 SNESComputeNGS - Calls the Gauss-Seidel function that has been set with SNESSetNGS(). 2375 2376 Collective on SNES 2377 2378 Input Parameters: 2379 + snes - the SNES context 2380 . x - input vector 2381 - b - rhs vector 2382 2383 Output Parameter: 2384 . x - new solution vector 2385 2386 Notes: 2387 SNESComputeNGS() is typically used within composed nonlinear solver 2388 implementations, so most users would not generally call this routine 2389 themselves. 2390 2391 Level: developer 2392 2393 .keywords: SNES, nonlinear, compute, function 2394 2395 .seealso: SNESSetNGS(), SNESComputeFunction() 2396 @*/ 2397 PetscErrorCode SNESComputeNGS(SNES snes,Vec b,Vec x) 2398 { 2399 PetscErrorCode ierr; 2400 DM dm; 2401 DMSNES sdm; 2402 2403 PetscFunctionBegin; 2404 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 2405 PetscValidHeaderSpecific(x,VEC_CLASSID,2); 2406 if (b) PetscValidHeaderSpecific(b,VEC_CLASSID,3); 2407 PetscCheckSameComm(snes,1,x,2); 2408 if (b) PetscCheckSameComm(snes,1,b,3); 2409 if (b) {ierr = VecValidValues(b,2,PETSC_TRUE);CHKERRQ(ierr);} 2410 ierr = PetscLogEventBegin(SNES_NGSEval,snes,x,b,0);CHKERRQ(ierr); 2411 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 2412 ierr = DMGetDMSNES(dm,&sdm);CHKERRQ(ierr); 2413 if (sdm->ops->computegs) { 2414 if (b) {ierr = VecLockPush(b);CHKERRQ(ierr);} 2415 PetscStackPush("SNES user NGS"); 2416 ierr = (*sdm->ops->computegs)(snes,x,b,sdm->gsctx);CHKERRQ(ierr); 2417 PetscStackPop; 2418 if (b) {ierr = VecLockPop(b);CHKERRQ(ierr);} 2419 } else SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE, "Must call SNESSetNGS() before SNESComputeNGS(), likely called from SNESSolve()."); 2420 ierr = PetscLogEventEnd(SNES_NGSEval,snes,x,b,0);CHKERRQ(ierr); 2421 PetscFunctionReturn(0); 2422 } 2423 2424 PetscErrorCode SNESTestJacobian(SNES snes) 2425 { 2426 Mat A,B,C,D,jacobian; 2427 Vec x = snes->vec_sol,f = snes->vec_func; 2428 PetscErrorCode ierr; 2429 PetscReal nrm,gnorm; 2430 PetscReal threshold = 1.e-5; 2431 PetscInt m,n,M,N; 2432 void *functx; 2433 PetscBool complete_print = PETSC_FALSE,threshold_print = PETSC_FALSE,test = PETSC_FALSE,flg; 2434 PetscViewer viewer,mviewer; 2435 MPI_Comm comm; 2436 PetscInt tabs; 2437 static PetscBool directionsprinted = PETSC_FALSE; 2438 PetscViewerFormat format; 2439 2440 PetscFunctionBegin; 2441 ierr = PetscObjectOptionsBegin((PetscObject)snes);CHKERRQ(ierr); 2442 ierr = PetscOptionsName("-snes_test_jacobian","Compare hand-coded and finite difference Jacobians","None",&test);CHKERRQ(ierr); 2443 ierr = PetscOptionsReal("-snes_test_jacobian", "Threshold for element difference between hand-coded and finite difference being meaningful", "None", threshold, &threshold,NULL);CHKERRQ(ierr); 2444 ierr = PetscOptionsViewer("-snes_test_jacobian_view","View difference between hand-coded and finite difference Jacobians element entries","None",&mviewer,&format,&complete_print);CHKERRQ(ierr); 2445 if (!complete_print) { 2446 ierr = PetscOptionsViewer("-snes_test_jacobian_display","Display difference between hand-coded and finite difference Jacobians","None",&mviewer,&format,&complete_print);CHKERRQ(ierr); 2447 } 2448 /* for compatibility with PETSc 3.9 and older. */ 2449 ierr = PetscOptionsReal("-snes_test_jacobian_display_threshold", "Display difference between hand-coded and finite difference Jacobians which exceed input threshold", "None", threshold, &threshold, &threshold_print);CHKERRQ(ierr); 2450 ierr = PetscOptionsEnd();CHKERRQ(ierr); 2451 if (!test) PetscFunctionReturn(0); 2452 2453 ierr = PetscObjectGetComm((PetscObject)snes,&comm);CHKERRQ(ierr); 2454 ierr = PetscViewerASCIIGetStdout(comm,&viewer);CHKERRQ(ierr); 2455 ierr = PetscViewerASCIIGetTab(viewer, &tabs);CHKERRQ(ierr); 2456 ierr = PetscViewerASCIISetTab(viewer, ((PetscObject)snes)->tablevel);CHKERRQ(ierr); 2457 ierr = PetscViewerASCIIPrintf(viewer," ---------- Testing Jacobian -------------\n");CHKERRQ(ierr); 2458 if (!complete_print && !directionsprinted) { 2459 ierr = PetscViewerASCIIPrintf(viewer," Run with -snes_test_jacobian_view and optionally -snes_test_jacobian <threshold> to show difference\n");CHKERRQ(ierr); 2460 ierr = PetscViewerASCIIPrintf(viewer," of hand-coded and finite difference Jacobian entries greater than <threshold>.\n");CHKERRQ(ierr); 2461 } 2462 if (!directionsprinted) { 2463 ierr = PetscViewerASCIIPrintf(viewer," Testing hand-coded Jacobian, if (for double precision runs) ||J - Jfd||_F/||J||_F is\n");CHKERRQ(ierr); 2464 ierr = PetscViewerASCIIPrintf(viewer," O(1.e-8), the hand-coded Jacobian is probably correct.\n");CHKERRQ(ierr); 2465 directionsprinted = PETSC_TRUE; 2466 } 2467 if (complete_print) { 2468 ierr = PetscViewerPushFormat(mviewer,format);CHKERRQ(ierr); 2469 } 2470 2471 /* evaluate the function at this point because SNESComputeJacobianDefault() assumes that the function has been evaluated and put into snes->vec_func */ 2472 ierr = SNESComputeFunction(snes,x,f);CHKERRQ(ierr); 2473 2474 ierr = PetscObjectTypeCompare((PetscObject)snes->jacobian,MATMFFD,&flg);CHKERRQ(ierr); 2475 if (!flg) jacobian = snes->jacobian; 2476 else jacobian = snes->jacobian_pre; 2477 2478 while (jacobian) { 2479 ierr = PetscObjectTypeCompareAny((PetscObject)jacobian,&flg,MATSEQAIJ,MATMPIAIJ,MATSEQDENSE,MATMPIDENSE,MATSEQBAIJ,MATMPIBAIJ,MATSEQSBAIJ,MATMPIBAIJ,"");CHKERRQ(ierr); 2480 if (flg) { 2481 A = jacobian; 2482 ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr); 2483 } else { 2484 ierr = MatComputeExplicitOperator(jacobian,&A);CHKERRQ(ierr); 2485 } 2486 2487 ierr = MatCreate(PetscObjectComm((PetscObject)A),&B);CHKERRQ(ierr); 2488 ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr); 2489 ierr = MatGetLocalSize(A,&m,&n);CHKERRQ(ierr); 2490 ierr = MatSetSizes(B,m,n,M,N);CHKERRQ(ierr); 2491 ierr = MatSetType(B,((PetscObject)A)->type_name);CHKERRQ(ierr); 2492 ierr = MatSetUp(B);CHKERRQ(ierr); 2493 ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr); 2494 2495 ierr = SNESGetFunction(snes,NULL,NULL,&functx);CHKERRQ(ierr); 2496 ierr = SNESComputeJacobianDefault(snes,x,B,B,functx);CHKERRQ(ierr); 2497 2498 ierr = MatDuplicate(B,MAT_COPY_VALUES,&D);CHKERRQ(ierr); 2499 ierr = MatAYPX(D,-1.0,A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); 2500 ierr = MatNorm(D,NORM_FROBENIUS,&nrm);CHKERRQ(ierr); 2501 ierr = MatNorm(A,NORM_FROBENIUS,&gnorm);CHKERRQ(ierr); 2502 ierr = MatDestroy(&D);CHKERRQ(ierr); 2503 if (!gnorm) gnorm = 1; /* just in case */ 2504 ierr = PetscViewerASCIIPrintf(viewer," ||J - Jfd||_F/||J||_F = %g, ||J - Jfd||_F = %g\n",(double)(nrm/gnorm),(double)nrm);CHKERRQ(ierr); 2505 2506 if (complete_print) { 2507 ierr = PetscViewerASCIIPrintf(viewer," Hand-coded Jacobian ----------\n");CHKERRQ(ierr); 2508 ierr = MatView(jacobian,mviewer);CHKERRQ(ierr); 2509 ierr = PetscViewerASCIIPrintf(viewer," Finite difference Jacobian ----------\n");CHKERRQ(ierr); 2510 ierr = MatView(B,mviewer);CHKERRQ(ierr); 2511 } 2512 2513 if (threshold_print || complete_print) { 2514 PetscInt Istart, Iend, *ccols, bncols, cncols, j, row; 2515 PetscScalar *cvals; 2516 const PetscInt *bcols; 2517 const PetscScalar *bvals; 2518 2519 ierr = MatAYPX(B,-1.0,A,DIFFERENT_NONZERO_PATTERN);CHKERRQ(ierr); 2520 ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr); 2521 ierr = MatSetSizes(C,m,n,M,N);CHKERRQ(ierr); 2522 ierr = MatSetType(C,((PetscObject)A)->type_name);CHKERRQ(ierr); 2523 ierr = MatSetUp(C);CHKERRQ(ierr); 2524 ierr = MatSetOption(C,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_FALSE);CHKERRQ(ierr); 2525 ierr = MatGetOwnershipRange(B,&Istart,&Iend);CHKERRQ(ierr); 2526 2527 for (row = Istart; row < Iend; row++) { 2528 ierr = MatGetRow(B,row,&bncols,&bcols,&bvals);CHKERRQ(ierr); 2529 ierr = PetscMalloc2(bncols,&ccols,bncols,&cvals);CHKERRQ(ierr); 2530 for (j = 0, cncols = 0; j < bncols; j++) { 2531 if (PetscAbsScalar(bvals[j]) > threshold) { 2532 ccols[cncols] = bcols[j]; 2533 cvals[cncols] = bvals[j]; 2534 cncols += 1; 2535 } 2536 } 2537 if (cncols) { 2538 ierr = MatSetValues(C,1,&row,cncols,ccols,cvals,INSERT_VALUES);CHKERRQ(ierr); 2539 } 2540 ierr = MatRestoreRow(B,row,&bncols,&bcols,&bvals);CHKERRQ(ierr); 2541 ierr = PetscFree2(ccols,cvals);CHKERRQ(ierr); 2542 } 2543 ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2544 ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2545 ierr = PetscViewerASCIIPrintf(viewer," Hand-coded minus finite-difference Jacobian with tolerance %g ----------\n",(double)threshold);CHKERRQ(ierr); 2546 ierr = MatView(C,complete_print ? mviewer : viewer);CHKERRQ(ierr); 2547 ierr = MatDestroy(&C);CHKERRQ(ierr); 2548 } 2549 ierr = MatDestroy(&A);CHKERRQ(ierr); 2550 ierr = MatDestroy(&B);CHKERRQ(ierr); 2551 2552 if (jacobian != snes->jacobian_pre) { 2553 jacobian = snes->jacobian_pre; 2554 ierr = PetscViewerASCIIPrintf(viewer," ---------- Testing Jacobian for preconditioner -------------\n");CHKERRQ(ierr); 2555 } 2556 else jacobian = NULL; 2557 } 2558 if (complete_print) { 2559 ierr = PetscViewerPopFormat(mviewer);CHKERRQ(ierr); 2560 } 2561 if (mviewer) { ierr = PetscViewerDestroy(&mviewer);CHKERRQ(ierr); } 2562 ierr = PetscViewerASCIISetTab(viewer,tabs);CHKERRQ(ierr); 2563 PetscFunctionReturn(0); 2564 } 2565 2566 /*@ 2567 SNESComputeJacobian - Computes the Jacobian matrix that has been set with SNESSetJacobian(). 2568 2569 Collective on SNES and Mat 2570 2571 Input Parameters: 2572 + snes - the SNES context 2573 - x - input vector 2574 2575 Output Parameters: 2576 + A - Jacobian matrix 2577 - B - optional preconditioning matrix 2578 2579 Options Database Keys: 2580 + -snes_lag_preconditioner <lag> 2581 . -snes_lag_jacobian <lag> 2582 . -snes_test_jacobian - compare the user provided Jacobian with one compute via finite differences to check for errors 2583 . -snes_test_jacobian_display - display the user provided Jacobian, the finite difference Jacobian and the difference between them to help users detect the location of errors in the user provided Jacobian 2584 . -snes_test_jacobian_display_threshold <numerical value> - display entries in the difference between the user provided Jacobian and finite difference Jacobian that are greater than a certain value to help users detect errors 2585 . -snes_compare_explicit - Compare the computed Jacobian to the finite difference Jacobian and output the differences 2586 . -snes_compare_explicit_draw - Compare the computed Jacobian to the finite difference Jacobian and draw the result 2587 . -snes_compare_explicit_contour - Compare the computed Jacobian to the finite difference Jacobian and draw a contour plot with the result 2588 . -snes_compare_operator - Make the comparison options above use the operator instead of the preconditioning matrix 2589 . -snes_compare_coloring - Compute the finite difference Jacobian using coloring and display norms of difference 2590 . -snes_compare_coloring_display - Compute the finite differece Jacobian using coloring and display verbose differences 2591 . -snes_compare_coloring_threshold - Display only those matrix entries that differ by more than a given threshold 2592 . -snes_compare_coloring_threshold_atol - Absolute tolerance for difference in matrix entries to be displayed by -snes_compare_coloring_threshold 2593 . -snes_compare_coloring_threshold_rtol - Relative tolerance for difference in matrix entries to be displayed by -snes_compare_coloring_threshold 2594 . -snes_compare_coloring_draw - Compute the finite differece Jacobian using coloring and draw differences 2595 - -snes_compare_coloring_draw_contour - Compute the finite differece Jacobian using coloring and show contours of matrices and differences 2596 2597 2598 Notes: 2599 Most users should not need to explicitly call this routine, as it 2600 is used internally within the nonlinear solvers. 2601 2602 Developer Notes: 2603 This has duplicative ways of checking the accuracy of the user provided Jacobian (see the options above). This is for historical reasons, the routine SNESTestJacobian() use to used 2604 for with the SNESType of test that has been removed. 2605 2606 Level: developer 2607 2608 .keywords: SNES, compute, Jacobian, matrix 2609 2610 .seealso: SNESSetJacobian(), KSPSetOperators(), MatStructure, SNESSetLagPreconditioner(), SNESSetLagJacobian() 2611 @*/ 2612 PetscErrorCode SNESComputeJacobian(SNES snes,Vec X,Mat A,Mat B) 2613 { 2614 PetscErrorCode ierr; 2615 PetscBool flag; 2616 DM dm; 2617 DMSNES sdm; 2618 KSP ksp; 2619 2620 PetscFunctionBegin; 2621 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 2622 PetscValidHeaderSpecific(X,VEC_CLASSID,2); 2623 PetscCheckSameComm(snes,1,X,2); 2624 ierr = VecValidValues(X,2,PETSC_TRUE);CHKERRQ(ierr); 2625 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 2626 ierr = DMGetDMSNES(dm,&sdm);CHKERRQ(ierr); 2627 2628 if (!sdm->ops->computejacobian) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_USER,"Must call SNESSetJacobian(), DMSNESSetJacobian(), DMDASNESSetJacobianLocal(), etc"); 2629 2630 /* make sure that MatAssemblyBegin/End() is called on A matrix if it is matrix free */ 2631 2632 if (snes->lagjacobian == -2) { 2633 snes->lagjacobian = -1; 2634 2635 ierr = PetscInfo(snes,"Recomputing Jacobian/preconditioner because lag is -2 (means compute Jacobian, but then never again) \n");CHKERRQ(ierr); 2636 } else if (snes->lagjacobian == -1) { 2637 ierr = PetscInfo(snes,"Reusing Jacobian/preconditioner because lag is -1\n");CHKERRQ(ierr); 2638 ierr = PetscObjectTypeCompare((PetscObject)A,MATMFFD,&flag);CHKERRQ(ierr); 2639 if (flag) { 2640 ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2641 ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2642 } 2643 PetscFunctionReturn(0); 2644 } else if (snes->lagjacobian > 1 && (snes->iter + snes->jac_iter) % snes->lagjacobian) { 2645 ierr = PetscInfo2(snes,"Reusing Jacobian/preconditioner because lag is %D and SNES iteration is %D\n",snes->lagjacobian,snes->iter);CHKERRQ(ierr); 2646 ierr = PetscObjectTypeCompare((PetscObject)A,MATMFFD,&flag);CHKERRQ(ierr); 2647 if (flag) { 2648 ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2649 ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2650 } 2651 PetscFunctionReturn(0); 2652 } 2653 if (snes->npc && snes->npcside== PC_LEFT) { 2654 ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2655 ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 2656 PetscFunctionReturn(0); 2657 } 2658 2659 ierr = PetscLogEventBegin(SNES_JacobianEval,snes,X,A,B);CHKERRQ(ierr); 2660 ierr = VecLockPush(X);CHKERRQ(ierr); 2661 PetscStackPush("SNES user Jacobian function"); 2662 ierr = (*sdm->ops->computejacobian)(snes,X,A,B,sdm->jacobianctx);CHKERRQ(ierr); 2663 PetscStackPop; 2664 ierr = VecLockPop(X);CHKERRQ(ierr); 2665 ierr = PetscLogEventEnd(SNES_JacobianEval,snes,X,A,B);CHKERRQ(ierr); 2666 2667 /* the next line ensures that snes->ksp exists */ 2668 ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr); 2669 if (snes->lagpreconditioner == -2) { 2670 ierr = PetscInfo(snes,"Rebuilding preconditioner exactly once since lag is -2\n");CHKERRQ(ierr); 2671 ierr = KSPSetReusePreconditioner(snes->ksp,PETSC_FALSE);CHKERRQ(ierr); 2672 snes->lagpreconditioner = -1; 2673 } else if (snes->lagpreconditioner == -1) { 2674 ierr = PetscInfo(snes,"Reusing preconditioner because lag is -1\n");CHKERRQ(ierr); 2675 ierr = KSPSetReusePreconditioner(snes->ksp,PETSC_TRUE);CHKERRQ(ierr); 2676 } else if (snes->lagpreconditioner > 1 && (snes->iter + snes->pre_iter) % snes->lagpreconditioner) { 2677 ierr = PetscInfo2(snes,"Reusing preconditioner because lag is %D and SNES iteration is %D\n",snes->lagpreconditioner,snes->iter);CHKERRQ(ierr); 2678 ierr = KSPSetReusePreconditioner(snes->ksp,PETSC_TRUE);CHKERRQ(ierr); 2679 } else { 2680 ierr = PetscInfo(snes,"Rebuilding preconditioner\n");CHKERRQ(ierr); 2681 ierr = KSPSetReusePreconditioner(snes->ksp,PETSC_FALSE);CHKERRQ(ierr); 2682 } 2683 2684 ierr = SNESTestJacobian(snes);CHKERRQ(ierr); 2685 /* make sure user returned a correct Jacobian and preconditioner */ 2686 /* PetscValidHeaderSpecific(A,MAT_CLASSID,3); 2687 PetscValidHeaderSpecific(B,MAT_CLASSID,4); */ 2688 { 2689 PetscBool flag = PETSC_FALSE,flag_draw = PETSC_FALSE,flag_contour = PETSC_FALSE,flag_operator = PETSC_FALSE; 2690 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject) snes)->options,((PetscObject)snes)->prefix,"-snes_compare_explicit",NULL,NULL,&flag);CHKERRQ(ierr); 2691 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject) snes)->options,((PetscObject)snes)->prefix,"-snes_compare_explicit_draw",NULL,NULL,&flag_draw);CHKERRQ(ierr); 2692 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject) snes)->options,((PetscObject)snes)->prefix,"-snes_compare_explicit_draw_contour",NULL,NULL,&flag_contour);CHKERRQ(ierr); 2693 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject) snes)->options,((PetscObject)snes)->prefix,"-snes_compare_operator",NULL,NULL,&flag_operator);CHKERRQ(ierr); 2694 if (flag || flag_draw || flag_contour) { 2695 Mat Bexp_mine = NULL,Bexp,FDexp; 2696 PetscViewer vdraw,vstdout; 2697 PetscBool flg; 2698 if (flag_operator) { 2699 ierr = MatComputeExplicitOperator(A,&Bexp_mine);CHKERRQ(ierr); 2700 Bexp = Bexp_mine; 2701 } else { 2702 /* See if the preconditioning matrix can be viewed and added directly */ 2703 ierr = PetscObjectTypeCompareAny((PetscObject)B,&flg,MATSEQAIJ,MATMPIAIJ,MATSEQDENSE,MATMPIDENSE,MATSEQBAIJ,MATMPIBAIJ,MATSEQSBAIJ,MATMPIBAIJ,"");CHKERRQ(ierr); 2704 if (flg) Bexp = B; 2705 else { 2706 /* If the "preconditioning" matrix is itself MATSHELL or some other type without direct support */ 2707 ierr = MatComputeExplicitOperator(B,&Bexp_mine);CHKERRQ(ierr); 2708 Bexp = Bexp_mine; 2709 } 2710 } 2711 ierr = MatConvert(Bexp,MATSAME,MAT_INITIAL_MATRIX,&FDexp);CHKERRQ(ierr); 2712 ierr = SNESComputeJacobianDefault(snes,X,FDexp,FDexp,NULL);CHKERRQ(ierr); 2713 ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes),&vstdout);CHKERRQ(ierr); 2714 if (flag_draw || flag_contour) { 2715 ierr = PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes),0,"Explicit Jacobians",PETSC_DECIDE,PETSC_DECIDE,300,300,&vdraw);CHKERRQ(ierr); 2716 if (flag_contour) {ierr = PetscViewerPushFormat(vdraw,PETSC_VIEWER_DRAW_CONTOUR);CHKERRQ(ierr);} 2717 } else vdraw = NULL; 2718 ierr = PetscViewerASCIIPrintf(vstdout,"Explicit %s\n",flag_operator ? "Jacobian" : "preconditioning Jacobian");CHKERRQ(ierr); 2719 if (flag) {ierr = MatView(Bexp,vstdout);CHKERRQ(ierr);} 2720 if (vdraw) {ierr = MatView(Bexp,vdraw);CHKERRQ(ierr);} 2721 ierr = PetscViewerASCIIPrintf(vstdout,"Finite difference Jacobian\n");CHKERRQ(ierr); 2722 if (flag) {ierr = MatView(FDexp,vstdout);CHKERRQ(ierr);} 2723 if (vdraw) {ierr = MatView(FDexp,vdraw);CHKERRQ(ierr);} 2724 ierr = MatAYPX(FDexp,-1.0,Bexp,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 2725 ierr = PetscViewerASCIIPrintf(vstdout,"User-provided matrix minus finite difference Jacobian\n");CHKERRQ(ierr); 2726 if (flag) {ierr = MatView(FDexp,vstdout);CHKERRQ(ierr);} 2727 if (vdraw) { /* Always use contour for the difference */ 2728 ierr = PetscViewerPushFormat(vdraw,PETSC_VIEWER_DRAW_CONTOUR);CHKERRQ(ierr); 2729 ierr = MatView(FDexp,vdraw);CHKERRQ(ierr); 2730 ierr = PetscViewerPopFormat(vdraw);CHKERRQ(ierr); 2731 } 2732 if (flag_contour) {ierr = PetscViewerPopFormat(vdraw);CHKERRQ(ierr);} 2733 ierr = PetscViewerDestroy(&vdraw);CHKERRQ(ierr); 2734 ierr = MatDestroy(&Bexp_mine);CHKERRQ(ierr); 2735 ierr = MatDestroy(&FDexp);CHKERRQ(ierr); 2736 } 2737 } 2738 { 2739 PetscBool flag = PETSC_FALSE,flag_display = PETSC_FALSE,flag_draw = PETSC_FALSE,flag_contour = PETSC_FALSE,flag_threshold = PETSC_FALSE; 2740 PetscReal threshold_atol = PETSC_SQRT_MACHINE_EPSILON,threshold_rtol = 10*PETSC_SQRT_MACHINE_EPSILON; 2741 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-snes_compare_coloring",NULL,NULL,&flag);CHKERRQ(ierr); 2742 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-snes_compare_coloring_display",NULL,NULL,&flag_display);CHKERRQ(ierr); 2743 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-snes_compare_coloring_draw",NULL,NULL,&flag_draw);CHKERRQ(ierr); 2744 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-snes_compare_coloring_draw_contour",NULL,NULL,&flag_contour);CHKERRQ(ierr); 2745 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-snes_compare_coloring_threshold",NULL,NULL,&flag_threshold);CHKERRQ(ierr); 2746 if (flag_threshold) { 2747 ierr = PetscOptionsGetReal(((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-snes_compare_coloring_threshold_rtol",&threshold_rtol,NULL);CHKERRQ(ierr); 2748 ierr = PetscOptionsGetReal(((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-snes_compare_coloring_threshold_atol",&threshold_atol,NULL);CHKERRQ(ierr); 2749 } 2750 if (flag || flag_display || flag_draw || flag_contour || flag_threshold) { 2751 Mat Bfd; 2752 PetscViewer vdraw,vstdout; 2753 MatColoring coloring; 2754 ISColoring iscoloring; 2755 MatFDColoring matfdcoloring; 2756 PetscErrorCode (*func)(SNES,Vec,Vec,void*); 2757 void *funcctx; 2758 PetscReal norm1,norm2,normmax; 2759 2760 ierr = MatDuplicate(B,MAT_DO_NOT_COPY_VALUES,&Bfd);CHKERRQ(ierr); 2761 ierr = MatColoringCreate(Bfd,&coloring);CHKERRQ(ierr); 2762 ierr = MatColoringSetType(coloring,MATCOLORINGSL);CHKERRQ(ierr); 2763 ierr = MatColoringSetFromOptions(coloring);CHKERRQ(ierr); 2764 ierr = MatColoringApply(coloring,&iscoloring);CHKERRQ(ierr); 2765 ierr = MatColoringDestroy(&coloring);CHKERRQ(ierr); 2766 ierr = MatFDColoringCreate(Bfd,iscoloring,&matfdcoloring);CHKERRQ(ierr); 2767 ierr = MatFDColoringSetFromOptions(matfdcoloring);CHKERRQ(ierr); 2768 ierr = MatFDColoringSetUp(Bfd,iscoloring,matfdcoloring);CHKERRQ(ierr); 2769 ierr = ISColoringDestroy(&iscoloring);CHKERRQ(ierr); 2770 2771 /* This method of getting the function is currently unreliable since it doesn't work for DM local functions. */ 2772 ierr = SNESGetFunction(snes,NULL,&func,&funcctx);CHKERRQ(ierr); 2773 ierr = MatFDColoringSetFunction(matfdcoloring,(PetscErrorCode (*)(void))func,funcctx);CHKERRQ(ierr); 2774 ierr = PetscObjectSetOptionsPrefix((PetscObject)matfdcoloring,((PetscObject)snes)->prefix);CHKERRQ(ierr); 2775 ierr = PetscObjectAppendOptionsPrefix((PetscObject)matfdcoloring,"coloring_");CHKERRQ(ierr); 2776 ierr = MatFDColoringSetFromOptions(matfdcoloring);CHKERRQ(ierr); 2777 ierr = MatFDColoringApply(Bfd,matfdcoloring,X,snes);CHKERRQ(ierr); 2778 ierr = MatFDColoringDestroy(&matfdcoloring);CHKERRQ(ierr); 2779 2780 ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)snes),&vstdout);CHKERRQ(ierr); 2781 if (flag_draw || flag_contour) { 2782 ierr = PetscViewerDrawOpen(PetscObjectComm((PetscObject)snes),0,"Colored Jacobians",PETSC_DECIDE,PETSC_DECIDE,300,300,&vdraw);CHKERRQ(ierr); 2783 if (flag_contour) {ierr = PetscViewerPushFormat(vdraw,PETSC_VIEWER_DRAW_CONTOUR);CHKERRQ(ierr);} 2784 } else vdraw = NULL; 2785 ierr = PetscViewerASCIIPrintf(vstdout,"Explicit preconditioning Jacobian\n");CHKERRQ(ierr); 2786 if (flag_display) {ierr = MatView(B,vstdout);CHKERRQ(ierr);} 2787 if (vdraw) {ierr = MatView(B,vdraw);CHKERRQ(ierr);} 2788 ierr = PetscViewerASCIIPrintf(vstdout,"Colored Finite difference Jacobian\n");CHKERRQ(ierr); 2789 if (flag_display) {ierr = MatView(Bfd,vstdout);CHKERRQ(ierr);} 2790 if (vdraw) {ierr = MatView(Bfd,vdraw);CHKERRQ(ierr);} 2791 ierr = MatAYPX(Bfd,-1.0,B,SAME_NONZERO_PATTERN);CHKERRQ(ierr); 2792 ierr = MatNorm(Bfd,NORM_1,&norm1);CHKERRQ(ierr); 2793 ierr = MatNorm(Bfd,NORM_FROBENIUS,&norm2);CHKERRQ(ierr); 2794 ierr = MatNorm(Bfd,NORM_MAX,&normmax);CHKERRQ(ierr); 2795 ierr = PetscViewerASCIIPrintf(vstdout,"User-provided matrix minus finite difference Jacobian, norm1=%g normFrob=%g normmax=%g\n",(double)norm1,(double)norm2,(double)normmax);CHKERRQ(ierr); 2796 if (flag_display) {ierr = MatView(Bfd,vstdout);CHKERRQ(ierr);} 2797 if (vdraw) { /* Always use contour for the difference */ 2798 ierr = PetscViewerPushFormat(vdraw,PETSC_VIEWER_DRAW_CONTOUR);CHKERRQ(ierr); 2799 ierr = MatView(Bfd,vdraw);CHKERRQ(ierr); 2800 ierr = PetscViewerPopFormat(vdraw);CHKERRQ(ierr); 2801 } 2802 if (flag_contour) {ierr = PetscViewerPopFormat(vdraw);CHKERRQ(ierr);} 2803 2804 if (flag_threshold) { 2805 PetscInt bs,rstart,rend,i; 2806 ierr = MatGetBlockSize(B,&bs);CHKERRQ(ierr); 2807 ierr = MatGetOwnershipRange(B,&rstart,&rend);CHKERRQ(ierr); 2808 for (i=rstart; i<rend; i++) { 2809 const PetscScalar *ba,*ca; 2810 const PetscInt *bj,*cj; 2811 PetscInt bn,cn,j,maxentrycol = -1,maxdiffcol = -1,maxrdiffcol = -1; 2812 PetscReal maxentry = 0,maxdiff = 0,maxrdiff = 0; 2813 ierr = MatGetRow(B,i,&bn,&bj,&ba);CHKERRQ(ierr); 2814 ierr = MatGetRow(Bfd,i,&cn,&cj,&ca);CHKERRQ(ierr); 2815 if (bn != cn) SETERRQ(((PetscObject)A)->comm,PETSC_ERR_PLIB,"Unexpected different nonzero pattern in -snes_compare_coloring_threshold"); 2816 for (j=0; j<bn; j++) { 2817 PetscReal rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol*PetscAbsScalar(ba[j])); 2818 if (PetscAbsScalar(ba[j]) > PetscAbs(maxentry)) { 2819 maxentrycol = bj[j]; 2820 maxentry = PetscRealPart(ba[j]); 2821 } 2822 if (PetscAbsScalar(ca[j]) > PetscAbs(maxdiff)) { 2823 maxdiffcol = bj[j]; 2824 maxdiff = PetscRealPart(ca[j]); 2825 } 2826 if (rdiff > maxrdiff) { 2827 maxrdiffcol = bj[j]; 2828 maxrdiff = rdiff; 2829 } 2830 } 2831 if (maxrdiff > 1) { 2832 ierr = PetscViewerASCIIPrintf(vstdout,"row %D (maxentry=%g at %D, maxdiff=%g at %D, maxrdiff=%g at %D):",i,(double)maxentry,maxentrycol,(double)maxdiff,maxdiffcol,(double)maxrdiff,maxrdiffcol);CHKERRQ(ierr); 2833 for (j=0; j<bn; j++) { 2834 PetscReal rdiff; 2835 rdiff = PetscAbsScalar(ca[j]) / (threshold_atol + threshold_rtol*PetscAbsScalar(ba[j])); 2836 if (rdiff > 1) { 2837 ierr = PetscViewerASCIIPrintf(vstdout," (%D,%g:%g)",bj[j],(double)PetscRealPart(ba[j]),(double)PetscRealPart(ca[j]));CHKERRQ(ierr); 2838 } 2839 } 2840 ierr = PetscViewerASCIIPrintf(vstdout,"\n",i,maxentry,maxdiff,maxrdiff);CHKERRQ(ierr); 2841 } 2842 ierr = MatRestoreRow(B,i,&bn,&bj,&ba);CHKERRQ(ierr); 2843 ierr = MatRestoreRow(Bfd,i,&cn,&cj,&ca);CHKERRQ(ierr); 2844 } 2845 } 2846 ierr = PetscViewerDestroy(&vdraw);CHKERRQ(ierr); 2847 ierr = MatDestroy(&Bfd);CHKERRQ(ierr); 2848 } 2849 } 2850 PetscFunctionReturn(0); 2851 } 2852 2853 /*MC 2854 SNESJacobianFunction - Function used to convey the nonlinear Jacobian of the function to be solved by SNES 2855 2856 Synopsis: 2857 #include "petscsnes.h" 2858 PetscErrorCode SNESJacobianFunction(SNES snes,Vec x,Mat Amat,Mat Pmat,void *ctx); 2859 2860 + x - input vector 2861 . Amat - the matrix that defines the (approximate) Jacobian 2862 . Pmat - the matrix to be used in constructing the preconditioner, usually the same as Amat. 2863 - ctx - [optional] user-defined Jacobian context 2864 2865 Level: intermediate 2866 2867 .seealso: SNESSetFunction(), SNESGetFunction(), SNESSetJacobian(), SNESGetJacobian() 2868 M*/ 2869 2870 /*@C 2871 SNESSetJacobian - Sets the function to compute Jacobian as well as the 2872 location to store the matrix. 2873 2874 Logically Collective on SNES and Mat 2875 2876 Input Parameters: 2877 + snes - the SNES context 2878 . Amat - the matrix that defines the (approximate) Jacobian 2879 . Pmat - the matrix to be used in constructing the preconditioner, usually the same as Amat. 2880 . J - Jacobian evaluation routine (if NULL then SNES retains any previously set value), see SNESJacobianFunction for details 2881 - ctx - [optional] user-defined context for private data for the 2882 Jacobian evaluation routine (may be NULL) (if NULL then SNES retains any previously set value) 2883 2884 Notes: 2885 If the Amat matrix and Pmat matrix are different you must call MatAssemblyBegin/End() on 2886 each matrix. 2887 2888 If you know the operator Amat has a null space you can use MatSetNullSpace() and MatSetTransposeNullSpace() to supply the null 2889 space to Amat and the KSP solvers will automatically use that null space as needed during the solution process. 2890 2891 If using SNESComputeJacobianDefaultColor() to assemble a Jacobian, the ctx argument 2892 must be a MatFDColoring. 2893 2894 Other defect-correction schemes can be used by computing a different matrix in place of the Jacobian. One common 2895 example is to use the "Picard linearization" which only differentiates through the highest order parts of each term. 2896 2897 Level: beginner 2898 2899 .keywords: SNES, nonlinear, set, Jacobian, matrix 2900 2901 .seealso: KSPSetOperators(), SNESSetFunction(), MatMFFDComputeJacobian(), SNESComputeJacobianDefaultColor(), MatStructure, J, 2902 SNESSetPicard(), SNESJacobianFunction 2903 @*/ 2904 PetscErrorCode SNESSetJacobian(SNES snes,Mat Amat,Mat Pmat,PetscErrorCode (*J)(SNES,Vec,Mat,Mat,void*),void *ctx) 2905 { 2906 PetscErrorCode ierr; 2907 DM dm; 2908 2909 PetscFunctionBegin; 2910 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 2911 if (Amat) PetscValidHeaderSpecific(Amat,MAT_CLASSID,2); 2912 if (Pmat) PetscValidHeaderSpecific(Pmat,MAT_CLASSID,3); 2913 if (Amat) PetscCheckSameComm(snes,1,Amat,2); 2914 if (Pmat) PetscCheckSameComm(snes,1,Pmat,3); 2915 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 2916 ierr = DMSNESSetJacobian(dm,J,ctx);CHKERRQ(ierr); 2917 if (Amat) { 2918 ierr = PetscObjectReference((PetscObject)Amat);CHKERRQ(ierr); 2919 ierr = MatDestroy(&snes->jacobian);CHKERRQ(ierr); 2920 2921 snes->jacobian = Amat; 2922 } 2923 if (Pmat) { 2924 ierr = PetscObjectReference((PetscObject)Pmat);CHKERRQ(ierr); 2925 ierr = MatDestroy(&snes->jacobian_pre);CHKERRQ(ierr); 2926 2927 snes->jacobian_pre = Pmat; 2928 } 2929 PetscFunctionReturn(0); 2930 } 2931 2932 /*@C 2933 SNESGetJacobian - Returns the Jacobian matrix and optionally the user 2934 provided context for evaluating the Jacobian. 2935 2936 Not Collective, but Mat object will be parallel if SNES object is 2937 2938 Input Parameter: 2939 . snes - the nonlinear solver context 2940 2941 Output Parameters: 2942 + Amat - location to stash (approximate) Jacobian matrix (or NULL) 2943 . Pmat - location to stash matrix used to compute the preconditioner (or NULL) 2944 . J - location to put Jacobian function (or NULL), see SNESJacobianFunction for details on its calling sequence 2945 - ctx - location to stash Jacobian ctx (or NULL) 2946 2947 Level: advanced 2948 2949 .seealso: SNESSetJacobian(), SNESComputeJacobian(), SNESJacobianFunction, SNESGetFunction() 2950 @*/ 2951 PetscErrorCode SNESGetJacobian(SNES snes,Mat *Amat,Mat *Pmat,PetscErrorCode (**J)(SNES,Vec,Mat,Mat,void*),void **ctx) 2952 { 2953 PetscErrorCode ierr; 2954 DM dm; 2955 DMSNES sdm; 2956 2957 PetscFunctionBegin; 2958 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 2959 if (Amat) *Amat = snes->jacobian; 2960 if (Pmat) *Pmat = snes->jacobian_pre; 2961 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 2962 ierr = DMGetDMSNES(dm,&sdm);CHKERRQ(ierr); 2963 if (J) *J = sdm->ops->computejacobian; 2964 if (ctx) *ctx = sdm->jacobianctx; 2965 PetscFunctionReturn(0); 2966 } 2967 2968 /*@ 2969 SNESSetUp - Sets up the internal data structures for the later use 2970 of a nonlinear solver. 2971 2972 Collective on SNES 2973 2974 Input Parameters: 2975 . snes - the SNES context 2976 2977 Notes: 2978 For basic use of the SNES solvers the user need not explicitly call 2979 SNESSetUp(), since these actions will automatically occur during 2980 the call to SNESSolve(). However, if one wishes to control this 2981 phase separately, SNESSetUp() should be called after SNESCreate() 2982 and optional routines of the form SNESSetXXX(), but before SNESSolve(). 2983 2984 Level: advanced 2985 2986 .keywords: SNES, nonlinear, setup 2987 2988 .seealso: SNESCreate(), SNESSolve(), SNESDestroy() 2989 @*/ 2990 PetscErrorCode SNESSetUp(SNES snes) 2991 { 2992 PetscErrorCode ierr; 2993 DM dm; 2994 DMSNES sdm; 2995 SNESLineSearch linesearch, pclinesearch; 2996 void *lsprectx,*lspostctx; 2997 PetscErrorCode (*precheck)(SNESLineSearch,Vec,Vec,PetscBool*,void*); 2998 PetscErrorCode (*postcheck)(SNESLineSearch,Vec,Vec,Vec,PetscBool*,PetscBool*,void*); 2999 PetscErrorCode (*func)(SNES,Vec,Vec,void*); 3000 Vec f,fpc; 3001 void *funcctx; 3002 PetscErrorCode (*jac)(SNES,Vec,Mat,Mat,void*); 3003 void *jacctx,*appctx; 3004 Mat j,jpre; 3005 3006 PetscFunctionBegin; 3007 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3008 if (snes->setupcalled) PetscFunctionReturn(0); 3009 3010 if (!((PetscObject)snes)->type_name) { 3011 ierr = SNESSetType(snes,SNESNEWTONLS);CHKERRQ(ierr); 3012 } 3013 3014 ierr = SNESGetFunction(snes,&snes->vec_func,NULL,NULL);CHKERRQ(ierr); 3015 3016 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 3017 ierr = DMGetDMSNES(dm,&sdm);CHKERRQ(ierr); 3018 if (!sdm->ops->computefunction) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_ARG_WRONGSTATE,"Function never provided to SNES object"); 3019 if (!sdm->ops->computejacobian) { 3020 ierr = DMSNESSetJacobian(dm,SNESComputeJacobianDefaultColor,NULL);CHKERRQ(ierr); 3021 } 3022 if (!snes->vec_func) { 3023 ierr = DMCreateGlobalVector(dm,&snes->vec_func);CHKERRQ(ierr); 3024 } 3025 3026 if (!snes->ksp) { 3027 ierr = SNESGetKSP(snes, &snes->ksp);CHKERRQ(ierr); 3028 } 3029 3030 if (!snes->linesearch) { 3031 ierr = SNESGetLineSearch(snes, &snes->linesearch);CHKERRQ(ierr); 3032 } 3033 ierr = SNESLineSearchSetFunction(snes->linesearch,SNESComputeFunction);CHKERRQ(ierr); 3034 3035 if (snes->npc && (snes->npcside== PC_LEFT)) { 3036 snes->mf = PETSC_TRUE; 3037 snes->mf_operator = PETSC_FALSE; 3038 } 3039 3040 if (snes->npc) { 3041 /* copy the DM over */ 3042 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 3043 ierr = SNESSetDM(snes->npc,dm);CHKERRQ(ierr); 3044 3045 ierr = SNESGetFunction(snes,&f,&func,&funcctx);CHKERRQ(ierr); 3046 ierr = VecDuplicate(f,&fpc);CHKERRQ(ierr); 3047 ierr = SNESSetFunction(snes->npc,fpc,func,funcctx);CHKERRQ(ierr); 3048 ierr = SNESGetJacobian(snes,&j,&jpre,&jac,&jacctx);CHKERRQ(ierr); 3049 ierr = SNESSetJacobian(snes->npc,j,jpre,jac,jacctx);CHKERRQ(ierr); 3050 ierr = SNESGetApplicationContext(snes,&appctx);CHKERRQ(ierr); 3051 ierr = SNESSetApplicationContext(snes->npc,appctx);CHKERRQ(ierr); 3052 ierr = VecDestroy(&fpc);CHKERRQ(ierr); 3053 3054 /* copy the function pointers over */ 3055 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)snes,(PetscObject)snes->npc);CHKERRQ(ierr); 3056 3057 /* default to 1 iteration */ 3058 ierr = SNESSetTolerances(snes->npc,0.0,0.0,0.0,1,snes->npc->max_funcs);CHKERRQ(ierr); 3059 if (snes->npcside==PC_RIGHT) { 3060 ierr = SNESSetNormSchedule(snes->npc,SNES_NORM_FINAL_ONLY);CHKERRQ(ierr); 3061 } else { 3062 ierr = SNESSetNormSchedule(snes->npc,SNES_NORM_NONE);CHKERRQ(ierr); 3063 } 3064 ierr = SNESSetFromOptions(snes->npc);CHKERRQ(ierr); 3065 3066 /* copy the line search context over */ 3067 ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr); 3068 ierr = SNESGetLineSearch(snes->npc,&pclinesearch);CHKERRQ(ierr); 3069 ierr = SNESLineSearchGetPreCheck(linesearch,&precheck,&lsprectx);CHKERRQ(ierr); 3070 ierr = SNESLineSearchGetPostCheck(linesearch,&postcheck,&lspostctx);CHKERRQ(ierr); 3071 ierr = SNESLineSearchSetPreCheck(pclinesearch,precheck,lsprectx);CHKERRQ(ierr); 3072 ierr = SNESLineSearchSetPostCheck(pclinesearch,postcheck,lspostctx);CHKERRQ(ierr); 3073 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch);CHKERRQ(ierr); 3074 } 3075 if (snes->mf) { 3076 ierr = SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version);CHKERRQ(ierr); 3077 } 3078 if (snes->ops->usercompute && !snes->user) { 3079 ierr = (*snes->ops->usercompute)(snes,(void**)&snes->user);CHKERRQ(ierr); 3080 } 3081 3082 snes->jac_iter = 0; 3083 snes->pre_iter = 0; 3084 3085 if (snes->ops->setup) { 3086 ierr = (*snes->ops->setup)(snes);CHKERRQ(ierr); 3087 } 3088 3089 if (snes->npc && (snes->npcside== PC_LEFT)) { 3090 if (snes->functype == SNES_FUNCTION_PRECONDITIONED) { 3091 ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr); 3092 ierr = SNESLineSearchSetFunction(linesearch,SNESComputeFunctionDefaultNPC);CHKERRQ(ierr); 3093 } 3094 } 3095 3096 snes->setupcalled = PETSC_TRUE; 3097 PetscFunctionReturn(0); 3098 } 3099 3100 /*@ 3101 SNESReset - Resets a SNES context to the snessetupcalled = 0 state and removes any allocated Vecs and Mats 3102 3103 Collective on SNES 3104 3105 Input Parameter: 3106 . snes - iterative context obtained from SNESCreate() 3107 3108 Level: intermediate 3109 3110 Notes: 3111 Also calls the application context destroy routine set with SNESSetComputeApplicationContext() 3112 3113 .keywords: SNES, destroy 3114 3115 .seealso: SNESCreate(), SNESSetUp(), SNESSolve() 3116 @*/ 3117 PetscErrorCode SNESReset(SNES snes) 3118 { 3119 PetscErrorCode ierr; 3120 3121 PetscFunctionBegin; 3122 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3123 if (snes->ops->userdestroy && snes->user) { 3124 ierr = (*snes->ops->userdestroy)((void**)&snes->user);CHKERRQ(ierr); 3125 snes->user = NULL; 3126 } 3127 if (snes->npc) { 3128 ierr = SNESReset(snes->npc);CHKERRQ(ierr); 3129 } 3130 3131 if (snes->ops->reset) { 3132 ierr = (*snes->ops->reset)(snes);CHKERRQ(ierr); 3133 } 3134 if (snes->ksp) { 3135 ierr = KSPReset(snes->ksp);CHKERRQ(ierr); 3136 } 3137 3138 if (snes->linesearch) { 3139 ierr = SNESLineSearchReset(snes->linesearch);CHKERRQ(ierr); 3140 } 3141 3142 ierr = VecDestroy(&snes->vec_rhs);CHKERRQ(ierr); 3143 ierr = VecDestroy(&snes->vec_sol);CHKERRQ(ierr); 3144 ierr = VecDestroy(&snes->vec_sol_update);CHKERRQ(ierr); 3145 ierr = VecDestroy(&snes->vec_func);CHKERRQ(ierr); 3146 ierr = MatDestroy(&snes->jacobian);CHKERRQ(ierr); 3147 ierr = MatDestroy(&snes->jacobian_pre);CHKERRQ(ierr); 3148 ierr = VecDestroyVecs(snes->nwork,&snes->work);CHKERRQ(ierr); 3149 ierr = VecDestroyVecs(snes->nvwork,&snes->vwork);CHKERRQ(ierr); 3150 3151 snes->alwayscomputesfinalresidual = PETSC_FALSE; 3152 3153 snes->nwork = snes->nvwork = 0; 3154 snes->setupcalled = PETSC_FALSE; 3155 PetscFunctionReturn(0); 3156 } 3157 3158 /*@ 3159 SNESDestroy - Destroys the nonlinear solver context that was created 3160 with SNESCreate(). 3161 3162 Collective on SNES 3163 3164 Input Parameter: 3165 . snes - the SNES context 3166 3167 Level: beginner 3168 3169 .keywords: SNES, nonlinear, destroy 3170 3171 .seealso: SNESCreate(), SNESSolve() 3172 @*/ 3173 PetscErrorCode SNESDestroy(SNES *snes) 3174 { 3175 PetscErrorCode ierr; 3176 3177 PetscFunctionBegin; 3178 if (!*snes) PetscFunctionReturn(0); 3179 PetscValidHeaderSpecific((*snes),SNES_CLASSID,1); 3180 if (--((PetscObject)(*snes))->refct > 0) {*snes = 0; PetscFunctionReturn(0);} 3181 3182 ierr = SNESReset((*snes));CHKERRQ(ierr); 3183 ierr = SNESDestroy(&(*snes)->npc);CHKERRQ(ierr); 3184 3185 /* if memory was published with SAWs then destroy it */ 3186 ierr = PetscObjectSAWsViewOff((PetscObject)*snes);CHKERRQ(ierr); 3187 if ((*snes)->ops->destroy) {ierr = (*((*snes))->ops->destroy)((*snes));CHKERRQ(ierr);} 3188 3189 if ((*snes)->dm) {ierr = DMCoarsenHookRemove((*snes)->dm,DMCoarsenHook_SNESVecSol,DMRestrictHook_SNESVecSol,*snes);CHKERRQ(ierr);} 3190 ierr = DMDestroy(&(*snes)->dm);CHKERRQ(ierr); 3191 ierr = KSPDestroy(&(*snes)->ksp);CHKERRQ(ierr); 3192 ierr = SNESLineSearchDestroy(&(*snes)->linesearch);CHKERRQ(ierr); 3193 3194 ierr = PetscFree((*snes)->kspconvctx);CHKERRQ(ierr); 3195 if ((*snes)->ops->convergeddestroy) { 3196 ierr = (*(*snes)->ops->convergeddestroy)((*snes)->cnvP);CHKERRQ(ierr); 3197 } 3198 if ((*snes)->conv_malloc) { 3199 ierr = PetscFree((*snes)->conv_hist);CHKERRQ(ierr); 3200 ierr = PetscFree((*snes)->conv_hist_its);CHKERRQ(ierr); 3201 } 3202 ierr = SNESMonitorCancel((*snes));CHKERRQ(ierr); 3203 ierr = PetscHeaderDestroy(snes);CHKERRQ(ierr); 3204 PetscFunctionReturn(0); 3205 } 3206 3207 /* ----------- Routines to set solver parameters ---------- */ 3208 3209 /*@ 3210 SNESSetLagPreconditioner - Determines when the preconditioner is rebuilt in the nonlinear solve. 3211 3212 Logically Collective on SNES 3213 3214 Input Parameters: 3215 + snes - the SNES context 3216 - lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 3217 the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3218 3219 Options Database Keys: 3220 . -snes_lag_preconditioner <lag> 3221 3222 Notes: 3223 The default is 1 3224 The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3225 If -1 is used before the very first nonlinear solve the preconditioner is still built because there is no previous preconditioner to use 3226 3227 Level: intermediate 3228 3229 .keywords: SNES, nonlinear, set, convergence, tolerances 3230 3231 .seealso: SNESSetTrustRegionTolerance(), SNESGetLagPreconditioner(), SNESSetLagJacobian(), SNESGetLagJacobian() 3232 3233 @*/ 3234 PetscErrorCode SNESSetLagPreconditioner(SNES snes,PetscInt lag) 3235 { 3236 PetscFunctionBegin; 3237 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3238 if (lag < -2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Lag must be -2, -1, 1 or greater"); 3239 if (!lag) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Lag cannot be 0"); 3240 PetscValidLogicalCollectiveInt(snes,lag,2); 3241 snes->lagpreconditioner = lag; 3242 PetscFunctionReturn(0); 3243 } 3244 3245 /*@ 3246 SNESSetGridSequence - sets the number of steps of grid sequencing that SNES does 3247 3248 Logically Collective on SNES 3249 3250 Input Parameters: 3251 + snes - the SNES context 3252 - steps - the number of refinements to do, defaults to 0 3253 3254 Options Database Keys: 3255 . -snes_grid_sequence <steps> 3256 3257 Level: intermediate 3258 3259 Notes: 3260 Use SNESGetSolution() to extract the fine grid solution after grid sequencing. 3261 3262 .keywords: SNES, nonlinear, set, convergence, tolerances 3263 3264 .seealso: SNESSetTrustRegionTolerance(), SNESGetLagPreconditioner(), SNESSetLagJacobian(), SNESGetLagJacobian(), SNESGetGridSequence() 3265 3266 @*/ 3267 PetscErrorCode SNESSetGridSequence(SNES snes,PetscInt steps) 3268 { 3269 PetscFunctionBegin; 3270 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3271 PetscValidLogicalCollectiveInt(snes,steps,2); 3272 snes->gridsequence = steps; 3273 PetscFunctionReturn(0); 3274 } 3275 3276 /*@ 3277 SNESGetGridSequence - gets the number of steps of grid sequencing that SNES does 3278 3279 Logically Collective on SNES 3280 3281 Input Parameter: 3282 . snes - the SNES context 3283 3284 Output Parameter: 3285 . steps - the number of refinements to do, defaults to 0 3286 3287 Options Database Keys: 3288 . -snes_grid_sequence <steps> 3289 3290 Level: intermediate 3291 3292 Notes: 3293 Use SNESGetSolution() to extract the fine grid solution after grid sequencing. 3294 3295 .keywords: SNES, nonlinear, set, convergence, tolerances 3296 3297 .seealso: SNESSetTrustRegionTolerance(), SNESGetLagPreconditioner(), SNESSetLagJacobian(), SNESGetLagJacobian(), SNESSetGridSequence() 3298 3299 @*/ 3300 PetscErrorCode SNESGetGridSequence(SNES snes,PetscInt *steps) 3301 { 3302 PetscFunctionBegin; 3303 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3304 *steps = snes->gridsequence; 3305 PetscFunctionReturn(0); 3306 } 3307 3308 /*@ 3309 SNESGetLagPreconditioner - Indicates how often the preconditioner is rebuilt 3310 3311 Not Collective 3312 3313 Input Parameter: 3314 . snes - the SNES context 3315 3316 Output Parameter: 3317 . lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 3318 the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3319 3320 Options Database Keys: 3321 . -snes_lag_preconditioner <lag> 3322 3323 Notes: 3324 The default is 1 3325 The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3326 3327 Level: intermediate 3328 3329 .keywords: SNES, nonlinear, set, convergence, tolerances 3330 3331 .seealso: SNESSetTrustRegionTolerance(), SNESSetLagPreconditioner() 3332 3333 @*/ 3334 PetscErrorCode SNESGetLagPreconditioner(SNES snes,PetscInt *lag) 3335 { 3336 PetscFunctionBegin; 3337 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3338 *lag = snes->lagpreconditioner; 3339 PetscFunctionReturn(0); 3340 } 3341 3342 /*@ 3343 SNESSetLagJacobian - Determines when the Jacobian is rebuilt in the nonlinear solve. See SNESSetLagPreconditioner() for determining how 3344 often the preconditioner is rebuilt. 3345 3346 Logically Collective on SNES 3347 3348 Input Parameters: 3349 + snes - the SNES context 3350 - lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 3351 the Jacobian is built etc. -2 means rebuild at next chance but then never again 3352 3353 Options Database Keys: 3354 . -snes_lag_jacobian <lag> 3355 3356 Notes: 3357 The default is 1 3358 The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3359 If -1 is used before the very first nonlinear solve the CODE WILL FAIL! because no Jacobian is used, use -2 to indicate you want it recomputed 3360 at the next Newton step but never again (unless it is reset to another value) 3361 3362 Level: intermediate 3363 3364 .keywords: SNES, nonlinear, set, convergence, tolerances 3365 3366 .seealso: SNESSetTrustRegionTolerance(), SNESGetLagPreconditioner(), SNESSetLagPreconditioner(), SNESGetLagJacobian() 3367 3368 @*/ 3369 PetscErrorCode SNESSetLagJacobian(SNES snes,PetscInt lag) 3370 { 3371 PetscFunctionBegin; 3372 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3373 if (lag < -2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Lag must be -2, -1, 1 or greater"); 3374 if (!lag) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Lag cannot be 0"); 3375 PetscValidLogicalCollectiveInt(snes,lag,2); 3376 snes->lagjacobian = lag; 3377 PetscFunctionReturn(0); 3378 } 3379 3380 /*@ 3381 SNESGetLagJacobian - Indicates how often the Jacobian is rebuilt. See SNESGetLagPreconditioner() to determine when the preconditioner is rebuilt 3382 3383 Not Collective 3384 3385 Input Parameter: 3386 . snes - the SNES context 3387 3388 Output Parameter: 3389 . lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 3390 the Jacobian is built etc. 3391 3392 Options Database Keys: 3393 . -snes_lag_jacobian <lag> 3394 3395 Notes: 3396 The default is 1 3397 The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3398 3399 Level: intermediate 3400 3401 .keywords: SNES, nonlinear, set, convergence, tolerances 3402 3403 .seealso: SNESSetTrustRegionTolerance(), SNESSetLagJacobian(), SNESSetLagPreconditioner(), SNESGetLagPreconditioner() 3404 3405 @*/ 3406 PetscErrorCode SNESGetLagJacobian(SNES snes,PetscInt *lag) 3407 { 3408 PetscFunctionBegin; 3409 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3410 *lag = snes->lagjacobian; 3411 PetscFunctionReturn(0); 3412 } 3413 3414 /*@ 3415 SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple solves 3416 3417 Logically collective on SNES 3418 3419 Input Parameter: 3420 + snes - the SNES context 3421 - flg - jacobian lagging persists if true 3422 3423 Options Database Keys: 3424 . -snes_lag_jacobian_persists <flg> 3425 3426 Notes: 3427 This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by 3428 several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several 3429 timesteps may present huge efficiency gains. 3430 3431 Level: developer 3432 3433 .keywords: SNES, nonlinear, lag 3434 3435 .seealso: SNESSetLagPreconditionerPersists(), SNESSetLagJacobian(), SNESGetLagJacobian(), SNESGetNPC() 3436 3437 @*/ 3438 PetscErrorCode SNESSetLagJacobianPersists(SNES snes,PetscBool flg) 3439 { 3440 PetscFunctionBegin; 3441 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3442 PetscValidLogicalCollectiveBool(snes,flg,2); 3443 snes->lagjac_persist = flg; 3444 PetscFunctionReturn(0); 3445 } 3446 3447 /*@ 3448 SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple solves 3449 3450 Logically Collective on SNES 3451 3452 Input Parameter: 3453 + snes - the SNES context 3454 - flg - preconditioner lagging persists if true 3455 3456 Options Database Keys: 3457 . -snes_lag_jacobian_persists <flg> 3458 3459 Notes: 3460 This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale 3461 by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over 3462 several timesteps may present huge efficiency gains. 3463 3464 Level: developer 3465 3466 .keywords: SNES, nonlinear, lag 3467 3468 .seealso: SNESSetLagJacobianPersists(), SNESSetLagJacobian(), SNESGetLagJacobian(), SNESGetNPC() 3469 3470 @*/ 3471 PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes,PetscBool flg) 3472 { 3473 PetscFunctionBegin; 3474 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3475 PetscValidLogicalCollectiveBool(snes,flg,2); 3476 snes->lagpre_persist = flg; 3477 PetscFunctionReturn(0); 3478 } 3479 3480 /*@ 3481 SNESSetForceIteration - force SNESSolve() to take at least one iteration regardless of the initial residual norm 3482 3483 Logically Collective on SNES 3484 3485 Input Parameters: 3486 + snes - the SNES context 3487 - force - PETSC_TRUE require at least one iteration 3488 3489 Options Database Keys: 3490 . -snes_force_iteration <force> - Sets forcing an iteration 3491 3492 Notes: 3493 This is used sometimes with TS to prevent TS from detecting a false steady state solution 3494 3495 Level: intermediate 3496 3497 .keywords: SNES, nonlinear, set, convergence, tolerances 3498 3499 .seealso: SNESSetTrustRegionTolerance(), SNESSetDivergenceTolerance() 3500 @*/ 3501 PetscErrorCode SNESSetForceIteration(SNES snes,PetscBool force) 3502 { 3503 PetscFunctionBegin; 3504 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3505 snes->forceiteration = force; 3506 PetscFunctionReturn(0); 3507 } 3508 3509 /*@ 3510 SNESGetForceIteration - Whether or not to force SNESSolve() take at least one iteration regardless of the initial residual norm 3511 3512 Logically Collective on SNES 3513 3514 Input Parameters: 3515 . snes - the SNES context 3516 3517 Output Parameter: 3518 . force - PETSC_TRUE requires at least one iteration. 3519 3520 .keywords: SNES, nonlinear, set, convergence, tolerances 3521 3522 Level: intermediate 3523 3524 .seealso: SNESSetForceIteration(), SNESSetTrustRegionTolerance(), SNESSetDivergenceTolerance() 3525 @*/ 3526 PetscErrorCode SNESGetForceIteration(SNES snes,PetscBool *force) 3527 { 3528 PetscFunctionBegin; 3529 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3530 *force = snes->forceiteration; 3531 PetscFunctionReturn(0); 3532 } 3533 3534 /*@ 3535 SNESSetTolerances - Sets various parameters used in convergence tests. 3536 3537 Logically Collective on SNES 3538 3539 Input Parameters: 3540 + snes - the SNES context 3541 . abstol - absolute convergence tolerance 3542 . rtol - relative convergence tolerance 3543 . stol - convergence tolerance in terms of the norm of the change in the solution between steps, || delta x || < stol*|| x || 3544 . maxit - maximum number of iterations 3545 - maxf - maximum number of function evaluations (-1 indicates no limit) 3546 3547 Options Database Keys: 3548 + -snes_atol <abstol> - Sets abstol 3549 . -snes_rtol <rtol> - Sets rtol 3550 . -snes_stol <stol> - Sets stol 3551 . -snes_max_it <maxit> - Sets maxit 3552 - -snes_max_funcs <maxf> - Sets maxf 3553 3554 Notes: 3555 The default maximum number of iterations is 50. 3556 The default maximum number of function evaluations is 1000. 3557 3558 Level: intermediate 3559 3560 .keywords: SNES, nonlinear, set, convergence, tolerances 3561 3562 .seealso: SNESSetTrustRegionTolerance(), SNESSetDivergenceTolerance(), SNESSetForceIteration() 3563 @*/ 3564 PetscErrorCode SNESSetTolerances(SNES snes,PetscReal abstol,PetscReal rtol,PetscReal stol,PetscInt maxit,PetscInt maxf) 3565 { 3566 PetscFunctionBegin; 3567 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3568 PetscValidLogicalCollectiveReal(snes,abstol,2); 3569 PetscValidLogicalCollectiveReal(snes,rtol,3); 3570 PetscValidLogicalCollectiveReal(snes,stol,4); 3571 PetscValidLogicalCollectiveInt(snes,maxit,5); 3572 PetscValidLogicalCollectiveInt(snes,maxf,6); 3573 3574 if (abstol != PETSC_DEFAULT) { 3575 if (abstol < 0.0) SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_OUTOFRANGE,"Absolute tolerance %g must be non-negative",(double)abstol); 3576 snes->abstol = abstol; 3577 } 3578 if (rtol != PETSC_DEFAULT) { 3579 if (rtol < 0.0 || 1.0 <= rtol) SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_OUTOFRANGE,"Relative tolerance %g must be non-negative and less than 1.0",(double)rtol); 3580 snes->rtol = rtol; 3581 } 3582 if (stol != PETSC_DEFAULT) { 3583 if (stol < 0.0) SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_OUTOFRANGE,"Step tolerance %g must be non-negative",(double)stol); 3584 snes->stol = stol; 3585 } 3586 if (maxit != PETSC_DEFAULT) { 3587 if (maxit < 0) SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_OUTOFRANGE,"Maximum number of iterations %D must be non-negative",maxit); 3588 snes->max_its = maxit; 3589 } 3590 if (maxf != PETSC_DEFAULT) { 3591 if (maxf < -1) SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_OUTOFRANGE,"Maximum number of function evaluations %D must be -1 or nonnegative",maxf); 3592 snes->max_funcs = maxf; 3593 } 3594 snes->tolerancesset = PETSC_TRUE; 3595 PetscFunctionReturn(0); 3596 } 3597 3598 /*@ 3599 SNESSetDivergenceTolerance - Sets the divergence tolerance used for the SNES divergence test. 3600 3601 Logically Collective on SNES 3602 3603 Input Parameters: 3604 + snes - the SNES context 3605 - divtol - the divergence tolerance. Use -1 to deactivate the test. 3606 3607 Options Database Keys: 3608 + -snes_divergence_tolerance <divtol> - Sets divtol 3609 3610 Notes: 3611 The default divergence tolerance is 1e4. 3612 3613 Level: intermediate 3614 3615 .keywords: SNES, nonlinear, set, divergence, tolerance 3616 3617 .seealso: SNESSetTolerances(), SNESGetDivergenceTolerance 3618 @*/ 3619 PetscErrorCode SNESSetDivergenceTolerance(SNES snes,PetscReal divtol) 3620 { 3621 PetscFunctionBegin; 3622 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3623 PetscValidLogicalCollectiveReal(snes,divtol,2); 3624 3625 if (divtol != PETSC_DEFAULT) { 3626 snes->divtol = divtol; 3627 } 3628 else { 3629 snes->divtol = 1.0e4; 3630 } 3631 PetscFunctionReturn(0); 3632 } 3633 3634 /*@ 3635 SNESGetTolerances - Gets various parameters used in convergence tests. 3636 3637 Not Collective 3638 3639 Input Parameters: 3640 + snes - the SNES context 3641 . atol - absolute convergence tolerance 3642 . rtol - relative convergence tolerance 3643 . stol - convergence tolerance in terms of the norm 3644 of the change in the solution between steps 3645 . maxit - maximum number of iterations 3646 - maxf - maximum number of function evaluations 3647 3648 Notes: 3649 The user can specify NULL for any parameter that is not needed. 3650 3651 Level: intermediate 3652 3653 .keywords: SNES, nonlinear, get, convergence, tolerances 3654 3655 .seealso: SNESSetTolerances() 3656 @*/ 3657 PetscErrorCode SNESGetTolerances(SNES snes,PetscReal *atol,PetscReal *rtol,PetscReal *stol,PetscInt *maxit,PetscInt *maxf) 3658 { 3659 PetscFunctionBegin; 3660 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3661 if (atol) *atol = snes->abstol; 3662 if (rtol) *rtol = snes->rtol; 3663 if (stol) *stol = snes->stol; 3664 if (maxit) *maxit = snes->max_its; 3665 if (maxf) *maxf = snes->max_funcs; 3666 PetscFunctionReturn(0); 3667 } 3668 3669 /*@ 3670 SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test. 3671 3672 Not Collective 3673 3674 Input Parameters: 3675 + snes - the SNES context 3676 - divtol - divergence tolerance 3677 3678 Level: intermediate 3679 3680 .keywords: SNES, nonlinear, get, divergence, tolerance 3681 3682 .seealso: SNESSetDivergenceTolerance() 3683 @*/ 3684 PetscErrorCode SNESGetDivergenceTolerance(SNES snes,PetscReal *divtol) 3685 { 3686 PetscFunctionBegin; 3687 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3688 if (divtol) *divtol = snes->divtol; 3689 PetscFunctionReturn(0); 3690 } 3691 3692 /*@ 3693 SNESSetTrustRegionTolerance - Sets the trust region parameter tolerance. 3694 3695 Logically Collective on SNES 3696 3697 Input Parameters: 3698 + snes - the SNES context 3699 - tol - tolerance 3700 3701 Options Database Key: 3702 . -snes_trtol <tol> - Sets tol 3703 3704 Level: intermediate 3705 3706 .keywords: SNES, nonlinear, set, trust region, tolerance 3707 3708 .seealso: SNESSetTolerances() 3709 @*/ 3710 PetscErrorCode SNESSetTrustRegionTolerance(SNES snes,PetscReal tol) 3711 { 3712 PetscFunctionBegin; 3713 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3714 PetscValidLogicalCollectiveReal(snes,tol,2); 3715 snes->deltatol = tol; 3716 PetscFunctionReturn(0); 3717 } 3718 3719 /* 3720 Duplicate the lg monitors for SNES from KSP; for some reason with 3721 dynamic libraries things don't work under Sun4 if we just use 3722 macros instead of functions 3723 */ 3724 PetscErrorCode SNESMonitorLGResidualNorm(SNES snes,PetscInt it,PetscReal norm,void *ctx) 3725 { 3726 PetscErrorCode ierr; 3727 3728 PetscFunctionBegin; 3729 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3730 ierr = KSPMonitorLGResidualNorm((KSP)snes,it,norm,ctx);CHKERRQ(ierr); 3731 PetscFunctionReturn(0); 3732 } 3733 3734 PetscErrorCode SNESMonitorLGCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscDrawLG *lgctx) 3735 { 3736 PetscErrorCode ierr; 3737 3738 PetscFunctionBegin; 3739 ierr = KSPMonitorLGResidualNormCreate(comm,host,label,x,y,m,n,lgctx);CHKERRQ(ierr); 3740 PetscFunctionReturn(0); 3741 } 3742 3743 PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES,PetscInt,PetscReal*); 3744 3745 PetscErrorCode SNESMonitorLGRange(SNES snes,PetscInt n,PetscReal rnorm,void *monctx) 3746 { 3747 PetscDrawLG lg; 3748 PetscErrorCode ierr; 3749 PetscReal x,y,per; 3750 PetscViewer v = (PetscViewer)monctx; 3751 static PetscReal prev; /* should be in the context */ 3752 PetscDraw draw; 3753 3754 PetscFunctionBegin; 3755 PetscValidHeaderSpecific(v,PETSC_VIEWER_CLASSID,4); 3756 ierr = PetscViewerDrawGetDrawLG(v,0,&lg);CHKERRQ(ierr); 3757 if (!n) {ierr = PetscDrawLGReset(lg);CHKERRQ(ierr);} 3758 ierr = PetscDrawLGGetDraw(lg,&draw);CHKERRQ(ierr); 3759 ierr = PetscDrawSetTitle(draw,"Residual norm");CHKERRQ(ierr); 3760 x = (PetscReal)n; 3761 if (rnorm > 0.0) y = PetscLog10Real(rnorm); 3762 else y = -15.0; 3763 ierr = PetscDrawLGAddPoint(lg,&x,&y);CHKERRQ(ierr); 3764 if (n < 20 || !(n % 5) || snes->reason) { 3765 ierr = PetscDrawLGDraw(lg);CHKERRQ(ierr); 3766 ierr = PetscDrawLGSave(lg);CHKERRQ(ierr); 3767 } 3768 3769 ierr = PetscViewerDrawGetDrawLG(v,1,&lg);CHKERRQ(ierr); 3770 if (!n) {ierr = PetscDrawLGReset(lg);CHKERRQ(ierr);} 3771 ierr = PetscDrawLGGetDraw(lg,&draw);CHKERRQ(ierr); 3772 ierr = PetscDrawSetTitle(draw,"% elemts > .2*max elemt");CHKERRQ(ierr); 3773 ierr = SNESMonitorRange_Private(snes,n,&per);CHKERRQ(ierr); 3774 x = (PetscReal)n; 3775 y = 100.0*per; 3776 ierr = PetscDrawLGAddPoint(lg,&x,&y);CHKERRQ(ierr); 3777 if (n < 20 || !(n % 5) || snes->reason) { 3778 ierr = PetscDrawLGDraw(lg);CHKERRQ(ierr); 3779 ierr = PetscDrawLGSave(lg);CHKERRQ(ierr); 3780 } 3781 3782 ierr = PetscViewerDrawGetDrawLG(v,2,&lg);CHKERRQ(ierr); 3783 if (!n) {prev = rnorm;ierr = PetscDrawLGReset(lg);CHKERRQ(ierr);} 3784 ierr = PetscDrawLGGetDraw(lg,&draw);CHKERRQ(ierr); 3785 ierr = PetscDrawSetTitle(draw,"(norm -oldnorm)/oldnorm");CHKERRQ(ierr); 3786 x = (PetscReal)n; 3787 y = (prev - rnorm)/prev; 3788 ierr = PetscDrawLGAddPoint(lg,&x,&y);CHKERRQ(ierr); 3789 if (n < 20 || !(n % 5) || snes->reason) { 3790 ierr = PetscDrawLGDraw(lg);CHKERRQ(ierr); 3791 ierr = PetscDrawLGSave(lg);CHKERRQ(ierr); 3792 } 3793 3794 ierr = PetscViewerDrawGetDrawLG(v,3,&lg);CHKERRQ(ierr); 3795 if (!n) {ierr = PetscDrawLGReset(lg);CHKERRQ(ierr);} 3796 ierr = PetscDrawLGGetDraw(lg,&draw);CHKERRQ(ierr); 3797 ierr = PetscDrawSetTitle(draw,"(norm -oldnorm)/oldnorm*(% > .2 max)");CHKERRQ(ierr); 3798 x = (PetscReal)n; 3799 y = (prev - rnorm)/(prev*per); 3800 if (n > 2) { /*skip initial crazy value */ 3801 ierr = PetscDrawLGAddPoint(lg,&x,&y);CHKERRQ(ierr); 3802 } 3803 if (n < 20 || !(n % 5) || snes->reason) { 3804 ierr = PetscDrawLGDraw(lg);CHKERRQ(ierr); 3805 ierr = PetscDrawLGSave(lg);CHKERRQ(ierr); 3806 } 3807 prev = rnorm; 3808 PetscFunctionReturn(0); 3809 } 3810 3811 /*@ 3812 SNESMonitor - runs the user provided monitor routines, if they exist 3813 3814 Collective on SNES 3815 3816 Input Parameters: 3817 + snes - nonlinear solver context obtained from SNESCreate() 3818 . iter - iteration number 3819 - rnorm - relative norm of the residual 3820 3821 Notes: 3822 This routine is called by the SNES implementations. 3823 It does not typically need to be called by the user. 3824 3825 Level: developer 3826 3827 .seealso: SNESMonitorSet() 3828 @*/ 3829 PetscErrorCode SNESMonitor(SNES snes,PetscInt iter,PetscReal rnorm) 3830 { 3831 PetscErrorCode ierr; 3832 PetscInt i,n = snes->numbermonitors; 3833 3834 PetscFunctionBegin; 3835 ierr = VecLockPush(snes->vec_sol);CHKERRQ(ierr); 3836 for (i=0; i<n; i++) { 3837 ierr = (*snes->monitor[i])(snes,iter,rnorm,snes->monitorcontext[i]);CHKERRQ(ierr); 3838 } 3839 ierr = VecLockPop(snes->vec_sol);CHKERRQ(ierr); 3840 PetscFunctionReturn(0); 3841 } 3842 3843 /* ------------ Routines to set performance monitoring options ----------- */ 3844 3845 /*MC 3846 SNESMonitorFunction - functional form passed to SNESMonitorSet() to monitor convergence of nonlinear solver 3847 3848 Synopsis: 3849 #include <petscsnes.h> 3850 $ PetscErrorCode SNESMonitorFunction(SNES snes,PetscInt its, PetscReal norm,void *mctx) 3851 3852 + snes - the SNES context 3853 . its - iteration number 3854 . norm - 2-norm function value (may be estimated) 3855 - mctx - [optional] monitoring context 3856 3857 Level: advanced 3858 3859 .seealso: SNESMonitorSet(), SNESMonitorGet() 3860 M*/ 3861 3862 /*@C 3863 SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every 3864 iteration of the nonlinear solver to display the iteration's 3865 progress. 3866 3867 Logically Collective on SNES 3868 3869 Input Parameters: 3870 + snes - the SNES context 3871 . f - the monitor function, see SNESMonitorFunction for the calling sequence 3872 . mctx - [optional] user-defined context for private data for the 3873 monitor routine (use NULL if no context is desired) 3874 - monitordestroy - [optional] routine that frees monitor context 3875 (may be NULL) 3876 3877 Options Database Keys: 3878 + -snes_monitor - sets SNESMonitorDefault() 3879 . -snes_monitor_lg_residualnorm - sets line graph monitor, 3880 uses SNESMonitorLGCreate() 3881 - -snes_monitor_cancel - cancels all monitors that have 3882 been hardwired into a code by 3883 calls to SNESMonitorSet(), but 3884 does not cancel those set via 3885 the options database. 3886 3887 Notes: 3888 Several different monitoring routines may be set by calling 3889 SNESMonitorSet() multiple times; all will be called in the 3890 order in which they were set. 3891 3892 Fortran Notes: 3893 Only a single monitor function can be set for each SNES object 3894 3895 Level: intermediate 3896 3897 .keywords: SNES, nonlinear, set, monitor 3898 3899 .seealso: SNESMonitorDefault(), SNESMonitorCancel(), SNESMonitorFunction 3900 @*/ 3901 PetscErrorCode SNESMonitorSet(SNES snes,PetscErrorCode (*f)(SNES,PetscInt,PetscReal,void*),void *mctx,PetscErrorCode (*monitordestroy)(void**)) 3902 { 3903 PetscInt i; 3904 PetscErrorCode ierr; 3905 PetscBool identical; 3906 3907 PetscFunctionBegin; 3908 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3909 for (i=0; i<snes->numbermonitors;i++) { 3910 ierr = PetscMonitorCompare((PetscErrorCode (*)(void))f,mctx,monitordestroy,(PetscErrorCode (*)(void))snes->monitor[i],snes->monitorcontext[i],snes->monitordestroy[i],&identical);CHKERRQ(ierr); 3911 if (identical) PetscFunctionReturn(0); 3912 } 3913 if (snes->numbermonitors >= MAXSNESMONITORS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many monitors set"); 3914 snes->monitor[snes->numbermonitors] = f; 3915 snes->monitordestroy[snes->numbermonitors] = monitordestroy; 3916 snes->monitorcontext[snes->numbermonitors++] = (void*)mctx; 3917 PetscFunctionReturn(0); 3918 } 3919 3920 /*@ 3921 SNESMonitorCancel - Clears all the monitor functions for a SNES object. 3922 3923 Logically Collective on SNES 3924 3925 Input Parameters: 3926 . snes - the SNES context 3927 3928 Options Database Key: 3929 . -snes_monitor_cancel - cancels all monitors that have been hardwired 3930 into a code by calls to SNESMonitorSet(), but does not cancel those 3931 set via the options database 3932 3933 Notes: 3934 There is no way to clear one specific monitor from a SNES object. 3935 3936 Level: intermediate 3937 3938 .keywords: SNES, nonlinear, set, monitor 3939 3940 .seealso: SNESMonitorDefault(), SNESMonitorSet() 3941 @*/ 3942 PetscErrorCode SNESMonitorCancel(SNES snes) 3943 { 3944 PetscErrorCode ierr; 3945 PetscInt i; 3946 3947 PetscFunctionBegin; 3948 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3949 for (i=0; i<snes->numbermonitors; i++) { 3950 if (snes->monitordestroy[i]) { 3951 ierr = (*snes->monitordestroy[i])(&snes->monitorcontext[i]);CHKERRQ(ierr); 3952 } 3953 } 3954 snes->numbermonitors = 0; 3955 PetscFunctionReturn(0); 3956 } 3957 3958 /*MC 3959 SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver 3960 3961 Synopsis: 3962 #include <petscsnes.h> 3963 $ PetscErrorCode SNESConvergenceTest(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gnorm,PetscReal f,SNESConvergedReason *reason,void *cctx) 3964 3965 + snes - the SNES context 3966 . it - current iteration (0 is the first and is before any Newton step) 3967 . cctx - [optional] convergence context 3968 . reason - reason for convergence/divergence 3969 . xnorm - 2-norm of current iterate 3970 . gnorm - 2-norm of current step 3971 - f - 2-norm of function 3972 3973 Level: intermediate 3974 3975 .seealso: SNESSetConvergenceTest(), SNESGetConvergenceTest() 3976 M*/ 3977 3978 /*@C 3979 SNESSetConvergenceTest - Sets the function that is to be used 3980 to test for convergence of the nonlinear iterative solution. 3981 3982 Logically Collective on SNES 3983 3984 Input Parameters: 3985 + snes - the SNES context 3986 . SNESConvergenceTestFunction - routine to test for convergence 3987 . cctx - [optional] context for private data for the convergence routine (may be NULL) 3988 - destroy - [optional] destructor for the context (may be NULL; PETSC_NULL_FUNCTION in Fortran) 3989 3990 Level: advanced 3991 3992 .keywords: SNES, nonlinear, set, convergence, test 3993 3994 .seealso: SNESConvergedDefault(), SNESConvergedSkip(), SNESConvergenceTestFunction 3995 @*/ 3996 PetscErrorCode SNESSetConvergenceTest(SNES snes,PetscErrorCode (*SNESConvergenceTestFunction)(SNES,PetscInt,PetscReal,PetscReal,PetscReal,SNESConvergedReason*,void*),void *cctx,PetscErrorCode (*destroy)(void*)) 3997 { 3998 PetscErrorCode ierr; 3999 4000 PetscFunctionBegin; 4001 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4002 if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip; 4003 if (snes->ops->convergeddestroy) { 4004 ierr = (*snes->ops->convergeddestroy)(snes->cnvP);CHKERRQ(ierr); 4005 } 4006 snes->ops->converged = SNESConvergenceTestFunction; 4007 snes->ops->convergeddestroy = destroy; 4008 snes->cnvP = cctx; 4009 PetscFunctionReturn(0); 4010 } 4011 4012 /*@ 4013 SNESGetConvergedReason - Gets the reason the SNES iteration was stopped. 4014 4015 Not Collective 4016 4017 Input Parameter: 4018 . snes - the SNES context 4019 4020 Output Parameter: 4021 . reason - negative value indicates diverged, positive value converged, see SNESConvergedReason or the 4022 manual pages for the individual convergence tests for complete lists 4023 4024 Options Database: 4025 . -snes_converged_reason - prints the reason to standard out 4026 4027 Level: intermediate 4028 4029 Notes: 4030 Should only be called after the call the SNESSolve() is complete, if it is called earlier it returns the value SNES__CONVERGED_ITERATING. 4031 4032 .keywords: SNES, nonlinear, set, convergence, test 4033 4034 .seealso: SNESSetConvergenceTest(), SNESSetConvergedReason(), SNESConvergedReason 4035 @*/ 4036 PetscErrorCode SNESGetConvergedReason(SNES snes,SNESConvergedReason *reason) 4037 { 4038 PetscFunctionBegin; 4039 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4040 PetscValidPointer(reason,2); 4041 *reason = snes->reason; 4042 PetscFunctionReturn(0); 4043 } 4044 4045 /*@ 4046 SNESSetConvergedReason - Sets the reason the SNES iteration was stopped. 4047 4048 Not Collective 4049 4050 Input Parameters: 4051 + snes - the SNES context 4052 - reason - negative value indicates diverged, positive value converged, see SNESConvergedReason or the 4053 manual pages for the individual convergence tests for complete lists 4054 4055 Level: intermediate 4056 4057 .keywords: SNES, nonlinear, set, convergence, test 4058 .seealso: SNESGetConvergedReason(), SNESSetConvergenceTest(), SNESConvergedReason 4059 @*/ 4060 PetscErrorCode SNESSetConvergedReason(SNES snes,SNESConvergedReason reason) 4061 { 4062 PetscFunctionBegin; 4063 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4064 snes->reason = reason; 4065 PetscFunctionReturn(0); 4066 } 4067 4068 /*@ 4069 SNESSetConvergenceHistory - Sets the array used to hold the convergence history. 4070 4071 Logically Collective on SNES 4072 4073 Input Parameters: 4074 + snes - iterative context obtained from SNESCreate() 4075 . a - array to hold history, this array will contain the function norms computed at each step 4076 . its - integer array holds the number of linear iterations for each solve. 4077 . na - size of a and its 4078 - reset - PETSC_TRUE indicates each new nonlinear solve resets the history counter to zero, 4079 else it continues storing new values for new nonlinear solves after the old ones 4080 4081 Notes: 4082 If 'a' and 'its' are NULL then space is allocated for the history. If 'na' PETSC_DECIDE or PETSC_DEFAULT then a 4083 default array of length 10000 is allocated. 4084 4085 This routine is useful, e.g., when running a code for purposes 4086 of accurate performance monitoring, when no I/O should be done 4087 during the section of code that is being timed. 4088 4089 Level: intermediate 4090 4091 .keywords: SNES, set, convergence, history 4092 4093 .seealso: SNESGetConvergenceHistory() 4094 4095 @*/ 4096 PetscErrorCode SNESSetConvergenceHistory(SNES snes,PetscReal a[],PetscInt its[],PetscInt na,PetscBool reset) 4097 { 4098 PetscErrorCode ierr; 4099 4100 PetscFunctionBegin; 4101 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4102 if (a) PetscValidScalarPointer(a,2); 4103 if (its) PetscValidIntPointer(its,3); 4104 if (!a) { 4105 if (na == PETSC_DECIDE || na == PETSC_DEFAULT) na = 1000; 4106 ierr = PetscCalloc1(na,&a);CHKERRQ(ierr); 4107 ierr = PetscCalloc1(na,&its);CHKERRQ(ierr); 4108 4109 snes->conv_malloc = PETSC_TRUE; 4110 } 4111 snes->conv_hist = a; 4112 snes->conv_hist_its = its; 4113 snes->conv_hist_max = na; 4114 snes->conv_hist_len = 0; 4115 snes->conv_hist_reset = reset; 4116 PetscFunctionReturn(0); 4117 } 4118 4119 #if defined(PETSC_HAVE_MATLAB_ENGINE) 4120 #include <engine.h> /* MATLAB include file */ 4121 #include <mex.h> /* MATLAB include file */ 4122 4123 PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes) 4124 { 4125 mxArray *mat; 4126 PetscInt i; 4127 PetscReal *ar; 4128 4129 PetscFunctionBegin; 4130 mat = mxCreateDoubleMatrix(snes->conv_hist_len,1,mxREAL); 4131 ar = (PetscReal*) mxGetData(mat); 4132 for (i=0; i<snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i]; 4133 PetscFunctionReturn(mat); 4134 } 4135 #endif 4136 4137 /*@C 4138 SNESGetConvergenceHistory - Gets the array used to hold the convergence history. 4139 4140 Not Collective 4141 4142 Input Parameter: 4143 . snes - iterative context obtained from SNESCreate() 4144 4145 Output Parameters: 4146 . a - array to hold history 4147 . its - integer array holds the number of linear iterations (or 4148 negative if not converged) for each solve. 4149 - na - size of a and its 4150 4151 Notes: 4152 The calling sequence for this routine in Fortran is 4153 $ call SNESGetConvergenceHistory(SNES snes, integer na, integer ierr) 4154 4155 This routine is useful, e.g., when running a code for purposes 4156 of accurate performance monitoring, when no I/O should be done 4157 during the section of code that is being timed. 4158 4159 Level: intermediate 4160 4161 .keywords: SNES, get, convergence, history 4162 4163 .seealso: SNESSetConvergencHistory() 4164 4165 @*/ 4166 PetscErrorCode SNESGetConvergenceHistory(SNES snes,PetscReal *a[],PetscInt *its[],PetscInt *na) 4167 { 4168 PetscFunctionBegin; 4169 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4170 if (a) *a = snes->conv_hist; 4171 if (its) *its = snes->conv_hist_its; 4172 if (na) *na = snes->conv_hist_len; 4173 PetscFunctionReturn(0); 4174 } 4175 4176 /*@C 4177 SNESSetUpdate - Sets the general-purpose update function called 4178 at the beginning of every iteration of the nonlinear solve. Specifically 4179 it is called just before the Jacobian is "evaluated". 4180 4181 Logically Collective on SNES 4182 4183 Input Parameters: 4184 . snes - The nonlinear solver context 4185 . func - The function 4186 4187 Calling sequence of func: 4188 . func (SNES snes, PetscInt step); 4189 4190 . step - The current step of the iteration 4191 4192 Level: advanced 4193 4194 Note: This is NOT what one uses to update the ghost points before a function evaluation, that should be done at the beginning of your FormFunction() 4195 This is not used by most users. 4196 4197 .keywords: SNES, update 4198 4199 .seealso SNESSetJacobian(), SNESSolve() 4200 @*/ 4201 PetscErrorCode SNESSetUpdate(SNES snes, PetscErrorCode (*func)(SNES, PetscInt)) 4202 { 4203 PetscFunctionBegin; 4204 PetscValidHeaderSpecific(snes, SNES_CLASSID,1); 4205 snes->ops->update = func; 4206 PetscFunctionReturn(0); 4207 } 4208 4209 /* 4210 SNESScaleStep_Private - Scales a step so that its length is less than the 4211 positive parameter delta. 4212 4213 Input Parameters: 4214 + snes - the SNES context 4215 . y - approximate solution of linear system 4216 . fnorm - 2-norm of current function 4217 - delta - trust region size 4218 4219 Output Parameters: 4220 + gpnorm - predicted function norm at the new point, assuming local 4221 linearization. The value is zero if the step lies within the trust 4222 region, and exceeds zero otherwise. 4223 - ynorm - 2-norm of the step 4224 4225 Note: 4226 For non-trust region methods such as SNESNEWTONLS, the parameter delta 4227 is set to be the maximum allowable step size. 4228 4229 .keywords: SNES, nonlinear, scale, step 4230 */ 4231 PetscErrorCode SNESScaleStep_Private(SNES snes,Vec y,PetscReal *fnorm,PetscReal *delta,PetscReal *gpnorm,PetscReal *ynorm) 4232 { 4233 PetscReal nrm; 4234 PetscScalar cnorm; 4235 PetscErrorCode ierr; 4236 4237 PetscFunctionBegin; 4238 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4239 PetscValidHeaderSpecific(y,VEC_CLASSID,2); 4240 PetscCheckSameComm(snes,1,y,2); 4241 4242 ierr = VecNorm(y,NORM_2,&nrm);CHKERRQ(ierr); 4243 if (nrm > *delta) { 4244 nrm = *delta/nrm; 4245 *gpnorm = (1.0 - nrm)*(*fnorm); 4246 cnorm = nrm; 4247 ierr = VecScale(y,cnorm);CHKERRQ(ierr); 4248 *ynorm = *delta; 4249 } else { 4250 *gpnorm = 0.0; 4251 *ynorm = nrm; 4252 } 4253 PetscFunctionReturn(0); 4254 } 4255 4256 /*@ 4257 SNESReasonView - Displays the reason a SNES solve converged or diverged to a viewer 4258 4259 Collective on SNES 4260 4261 Parameter: 4262 + snes - iterative context obtained from SNESCreate() 4263 - viewer - the viewer to display the reason 4264 4265 4266 Options Database Keys: 4267 . -snes_converged_reason - print reason for converged or diverged, also prints number of iterations 4268 4269 Level: beginner 4270 4271 .keywords: SNES, solve, linear system 4272 4273 .seealso: SNESCreate(), SNESSetUp(), SNESDestroy(), SNESSetTolerances(), SNESConvergedDefault() 4274 4275 @*/ 4276 PetscErrorCode SNESReasonView(SNES snes,PetscViewer viewer) 4277 { 4278 PetscViewerFormat format; 4279 PetscBool isAscii; 4280 PetscErrorCode ierr; 4281 4282 PetscFunctionBegin; 4283 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isAscii);CHKERRQ(ierr); 4284 if (isAscii) { 4285 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 4286 ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 4287 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 4288 DM dm; 4289 Vec u; 4290 PetscDS prob; 4291 PetscInt Nf, f; 4292 PetscErrorCode (**exactFuncs)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *); 4293 PetscReal error; 4294 4295 ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr); 4296 ierr = SNESGetSolution(snes, &u);CHKERRQ(ierr); 4297 ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 4298 ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr); 4299 ierr = PetscMalloc1(Nf, &exactFuncs);CHKERRQ(ierr); 4300 for (f = 0; f < Nf; ++f) {ierr = PetscDSGetExactSolution(prob, f, &exactFuncs[f]);CHKERRQ(ierr);} 4301 ierr = DMComputeL2Diff(dm, 0.0, exactFuncs, NULL, u, &error);CHKERRQ(ierr); 4302 ierr = PetscFree(exactFuncs);CHKERRQ(ierr); 4303 if (error < 1.0e-11) {ierr = PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n");CHKERRQ(ierr);} 4304 else {ierr = PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", error);CHKERRQ(ierr);} 4305 } 4306 if (snes->reason > 0) { 4307 if (((PetscObject) snes)->prefix) { 4308 ierr = PetscViewerASCIIPrintf(viewer,"Nonlinear %s solve converged due to %s iterations %D\n",((PetscObject) snes)->prefix,SNESConvergedReasons[snes->reason],snes->iter);CHKERRQ(ierr); 4309 } else { 4310 ierr = PetscViewerASCIIPrintf(viewer,"Nonlinear solve converged due to %s iterations %D\n",SNESConvergedReasons[snes->reason],snes->iter);CHKERRQ(ierr); 4311 } 4312 } else { 4313 if (((PetscObject) snes)->prefix) { 4314 ierr = PetscViewerASCIIPrintf(viewer,"Nonlinear %s solve did not converge due to %s iterations %D\n",((PetscObject) snes)->prefix,SNESConvergedReasons[snes->reason],snes->iter);CHKERRQ(ierr); 4315 } else { 4316 ierr = PetscViewerASCIIPrintf(viewer,"Nonlinear solve did not converge due to %s iterations %D\n",SNESConvergedReasons[snes->reason],snes->iter);CHKERRQ(ierr); 4317 } 4318 } 4319 ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 4320 } 4321 PetscFunctionReturn(0); 4322 } 4323 4324 /*@C 4325 SNESReasonViewFromOptions - Processes command line options to determine if/how a SNESReason is to be viewed. 4326 4327 Collective on SNES 4328 4329 Input Parameters: 4330 . snes - the SNES object 4331 4332 Level: intermediate 4333 4334 @*/ 4335 PetscErrorCode SNESReasonViewFromOptions(SNES snes) 4336 { 4337 PetscErrorCode ierr; 4338 PetscViewer viewer; 4339 PetscBool flg; 4340 static PetscBool incall = PETSC_FALSE; 4341 PetscViewerFormat format; 4342 4343 PetscFunctionBegin; 4344 if (incall) PetscFunctionReturn(0); 4345 incall = PETSC_TRUE; 4346 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-snes_converged_reason",&viewer,&format,&flg);CHKERRQ(ierr); 4347 if (flg) { 4348 ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr); 4349 ierr = SNESReasonView(snes,viewer);CHKERRQ(ierr); 4350 ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 4351 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 4352 } 4353 incall = PETSC_FALSE; 4354 PetscFunctionReturn(0); 4355 } 4356 4357 /*@ 4358 SNESSolve - Solves a nonlinear system F(x) = b. 4359 Call SNESSolve() after calling SNESCreate() and optional routines of the form SNESSetXXX(). 4360 4361 Collective on SNES 4362 4363 Input Parameters: 4364 + snes - the SNES context 4365 . b - the constant part of the equation F(x) = b, or NULL to use zero. 4366 - x - the solution vector. 4367 4368 Notes: 4369 The user should initialize the vector,x, with the initial guess 4370 for the nonlinear solve prior to calling SNESSolve. In particular, 4371 to employ an initial guess of zero, the user should explicitly set 4372 this vector to zero by calling VecSet(). 4373 4374 Level: beginner 4375 4376 .keywords: SNES, nonlinear, solve 4377 4378 .seealso: SNESCreate(), SNESDestroy(), SNESSetFunction(), SNESSetJacobian(), SNESSetGridSequence(), SNESGetSolution() 4379 @*/ 4380 PetscErrorCode SNESSolve(SNES snes,Vec b,Vec x) 4381 { 4382 PetscErrorCode ierr; 4383 PetscBool flg; 4384 PetscInt grid; 4385 Vec xcreated = NULL; 4386 DM dm; 4387 4388 PetscFunctionBegin; 4389 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4390 if (x) PetscValidHeaderSpecific(x,VEC_CLASSID,3); 4391 if (x) PetscCheckSameComm(snes,1,x,3); 4392 if (b) PetscValidHeaderSpecific(b,VEC_CLASSID,2); 4393 if (b) PetscCheckSameComm(snes,1,b,2); 4394 4395 /* High level operations using the nonlinear solver */ 4396 { 4397 PetscViewer viewer; 4398 PetscViewerFormat format; 4399 PetscInt num; 4400 PetscBool flg; 4401 static PetscBool incall = PETSC_FALSE; 4402 4403 if (!incall) { 4404 /* Estimate the convergence rate of the discretization */ 4405 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject) snes),((PetscObject)snes)->options, ((PetscObject) snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg);CHKERRQ(ierr); 4406 if (flg) { 4407 PetscConvEst conv; 4408 DM dm; 4409 PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */ 4410 PetscInt Nf; 4411 4412 incall = PETSC_TRUE; 4413 ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr); 4414 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 4415 ierr = PetscMalloc1(Nf, &alpha);CHKERRQ(ierr); 4416 ierr = PetscConvEstCreate(PetscObjectComm((PetscObject) snes), &conv);CHKERRQ(ierr); 4417 ierr = PetscConvEstSetSolver(conv, snes);CHKERRQ(ierr); 4418 ierr = PetscConvEstSetFromOptions(conv);CHKERRQ(ierr); 4419 ierr = PetscConvEstSetUp(conv);CHKERRQ(ierr); 4420 ierr = PetscConvEstGetConvRate(conv, alpha);CHKERRQ(ierr); 4421 ierr = PetscViewerPushFormat(viewer, format);CHKERRQ(ierr); 4422 ierr = PetscConvEstRateView(conv, alpha, viewer);CHKERRQ(ierr); 4423 ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 4424 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 4425 ierr = PetscConvEstDestroy(&conv);CHKERRQ(ierr); 4426 ierr = PetscFree(alpha);CHKERRQ(ierr); 4427 incall = PETSC_FALSE; 4428 } 4429 /* Adaptively refine the initial grid */ 4430 num = 1; 4431 ierr = PetscOptionsGetInt(NULL, ((PetscObject) snes)->prefix, "-snes_adapt_initial", &num, &flg);CHKERRQ(ierr); 4432 if (flg) { 4433 DMAdaptor adaptor; 4434 4435 incall = PETSC_TRUE; 4436 ierr = DMAdaptorCreate(PETSC_COMM_WORLD, &adaptor);CHKERRQ(ierr); 4437 ierr = DMAdaptorSetSolver(adaptor, snes);CHKERRQ(ierr); 4438 ierr = DMAdaptorSetSequenceLength(adaptor, num);CHKERRQ(ierr); 4439 ierr = DMAdaptorSetFromOptions(adaptor);CHKERRQ(ierr); 4440 ierr = DMAdaptorSetUp(adaptor);CHKERRQ(ierr); 4441 ierr = DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x);CHKERRQ(ierr); 4442 ierr = DMAdaptorDestroy(&adaptor);CHKERRQ(ierr); 4443 incall = PETSC_FALSE; 4444 } 4445 /* Use grid sequencing to adapt */ 4446 num = 0; 4447 ierr = PetscOptionsGetInt(NULL, ((PetscObject) snes)->prefix, "-snes_adapt_sequence", &num, NULL);CHKERRQ(ierr); 4448 if (num) { 4449 DMAdaptor adaptor; 4450 4451 incall = PETSC_TRUE; 4452 ierr = DMAdaptorCreate(PETSC_COMM_WORLD, &adaptor);CHKERRQ(ierr); 4453 ierr = DMAdaptorSetSolver(adaptor, snes);CHKERRQ(ierr); 4454 ierr = DMAdaptorSetSequenceLength(adaptor, num);CHKERRQ(ierr); 4455 ierr = DMAdaptorSetFromOptions(adaptor);CHKERRQ(ierr); 4456 ierr = DMAdaptorSetUp(adaptor);CHKERRQ(ierr); 4457 ierr = DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x);CHKERRQ(ierr); 4458 ierr = DMAdaptorDestroy(&adaptor);CHKERRQ(ierr); 4459 incall = PETSC_FALSE; 4460 } 4461 } 4462 } 4463 if (!x) { 4464 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 4465 ierr = DMCreateGlobalVector(dm,&xcreated);CHKERRQ(ierr); 4466 x = xcreated; 4467 } 4468 ierr = SNESViewFromOptions(snes,NULL,"-snes_view_pre");CHKERRQ(ierr); 4469 4470 for (grid=0; grid<snes->gridsequence; grid++) {ierr = PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)));CHKERRQ(ierr);} 4471 for (grid=0; grid<snes->gridsequence+1; grid++) { 4472 4473 /* set solution vector */ 4474 if (!grid) {ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr);} 4475 ierr = VecDestroy(&snes->vec_sol);CHKERRQ(ierr); 4476 snes->vec_sol = x; 4477 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 4478 4479 /* set affine vector if provided */ 4480 if (b) { ierr = PetscObjectReference((PetscObject)b);CHKERRQ(ierr); } 4481 ierr = VecDestroy(&snes->vec_rhs);CHKERRQ(ierr); 4482 snes->vec_rhs = b; 4483 4484 if (snes->vec_func == snes->vec_sol) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"Solution vector cannot be function vector"); 4485 if (snes->vec_rhs == snes->vec_sol) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"Solution vector cannot be right hand side vector"); 4486 if (!snes->vec_sol_update /* && snes->vec_sol */) { 4487 ierr = VecDuplicate(snes->vec_sol,&snes->vec_sol_update);CHKERRQ(ierr); 4488 ierr = PetscLogObjectParent((PetscObject)snes,(PetscObject)snes->vec_sol_update);CHKERRQ(ierr); 4489 } 4490 ierr = DMShellSetGlobalVector(dm,snes->vec_sol);CHKERRQ(ierr); 4491 ierr = SNESSetUp(snes);CHKERRQ(ierr); 4492 4493 if (!grid) { 4494 if (snes->ops->computeinitialguess) { 4495 ierr = (*snes->ops->computeinitialguess)(snes,snes->vec_sol,snes->initialguessP);CHKERRQ(ierr); 4496 } 4497 } 4498 4499 if (snes->conv_hist_reset) snes->conv_hist_len = 0; 4500 if (snes->counters_reset) {snes->nfuncs = 0; snes->linear_its = 0; snes->numFailures = 0;} 4501 4502 ierr = PetscLogEventBegin(SNES_Solve,snes,0,0,0);CHKERRQ(ierr); 4503 ierr = (*snes->ops->solve)(snes);CHKERRQ(ierr); 4504 ierr = PetscLogEventEnd(SNES_Solve,snes,0,0,0);CHKERRQ(ierr); 4505 if (!snes->reason) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Internal error, solver returned without setting converged reason"); 4506 snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */ 4507 4508 if (snes->lagjac_persist) snes->jac_iter += snes->iter; 4509 if (snes->lagpre_persist) snes->pre_iter += snes->iter; 4510 4511 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-snes_test_local_min",NULL,NULL,&flg);CHKERRQ(ierr); 4512 if (flg && !PetscPreLoadingOn) { ierr = SNESTestLocalMin(snes);CHKERRQ(ierr); } 4513 ierr = SNESReasonViewFromOptions(snes);CHKERRQ(ierr); 4514 4515 if (snes->errorifnotconverged && snes->reason < 0) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_NOT_CONVERGED,"SNESSolve has not converged"); 4516 if (snes->reason < 0) break; 4517 if (grid < snes->gridsequence) { 4518 DM fine; 4519 Vec xnew; 4520 Mat interp; 4521 4522 ierr = DMRefine(snes->dm,PetscObjectComm((PetscObject)snes),&fine);CHKERRQ(ierr); 4523 if (!fine) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_INCOMP,"DMRefine() did not perform any refinement, cannot continue grid sequencing"); 4524 ierr = DMCreateInterpolation(snes->dm,fine,&interp,NULL);CHKERRQ(ierr); 4525 ierr = DMCreateGlobalVector(fine,&xnew);CHKERRQ(ierr); 4526 ierr = MatInterpolate(interp,x,xnew);CHKERRQ(ierr); 4527 ierr = DMInterpolate(snes->dm,interp,fine);CHKERRQ(ierr); 4528 ierr = MatDestroy(&interp);CHKERRQ(ierr); 4529 x = xnew; 4530 4531 ierr = SNESReset(snes);CHKERRQ(ierr); 4532 ierr = SNESSetDM(snes,fine);CHKERRQ(ierr); 4533 ierr = SNESResetFromOptions(snes);CHKERRQ(ierr); 4534 ierr = DMDestroy(&fine);CHKERRQ(ierr); 4535 ierr = PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)));CHKERRQ(ierr); 4536 } 4537 } 4538 ierr = SNESViewFromOptions(snes,NULL,"-snes_view");CHKERRQ(ierr); 4539 ierr = VecViewFromOptions(snes->vec_sol,(PetscObject)snes,"-snes_view_solution");CHKERRQ(ierr); 4540 4541 ierr = VecDestroy(&xcreated);CHKERRQ(ierr); 4542 ierr = PetscObjectSAWsBlock((PetscObject)snes);CHKERRQ(ierr); 4543 PetscFunctionReturn(0); 4544 } 4545 4546 /* --------- Internal routines for SNES Package --------- */ 4547 4548 /*@C 4549 SNESSetType - Sets the method for the nonlinear solver. 4550 4551 Collective on SNES 4552 4553 Input Parameters: 4554 + snes - the SNES context 4555 - type - a known method 4556 4557 Options Database Key: 4558 . -snes_type <type> - Sets the method; use -help for a list 4559 of available methods (for instance, newtonls or newtontr) 4560 4561 Notes: 4562 See "petsc/include/petscsnes.h" for available methods (for instance) 4563 + SNESNEWTONLS - Newton's method with line search 4564 (systems of nonlinear equations) 4565 . SNESNEWTONTR - Newton's method with trust region 4566 (systems of nonlinear equations) 4567 4568 Normally, it is best to use the SNESSetFromOptions() command and then 4569 set the SNES solver type from the options database rather than by using 4570 this routine. Using the options database provides the user with 4571 maximum flexibility in evaluating the many nonlinear solvers. 4572 The SNESSetType() routine is provided for those situations where it 4573 is necessary to set the nonlinear solver independently of the command 4574 line or options database. This might be the case, for example, when 4575 the choice of solver changes during the execution of the program, 4576 and the user's application is taking responsibility for choosing the 4577 appropriate method. 4578 4579 Developer Notes: 4580 SNESRegister() adds a constructor for a new SNESType to SNESList, SNESSetType() locates 4581 the constructor in that list and calls it to create the spexific object. 4582 4583 Level: intermediate 4584 4585 .keywords: SNES, set, type 4586 4587 .seealso: SNESType, SNESCreate(), SNESDestroy(), SNESGetType(), SNESSetFromOptions() 4588 4589 @*/ 4590 PetscErrorCode SNESSetType(SNES snes,SNESType type) 4591 { 4592 PetscErrorCode ierr,(*r)(SNES); 4593 PetscBool match; 4594 4595 PetscFunctionBegin; 4596 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4597 PetscValidCharPointer(type,2); 4598 4599 ierr = PetscObjectTypeCompare((PetscObject)snes,type,&match);CHKERRQ(ierr); 4600 if (match) PetscFunctionReturn(0); 4601 4602 ierr = PetscFunctionListFind(SNESList,type,&r);CHKERRQ(ierr); 4603 if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested SNES type %s",type); 4604 /* Destroy the previous private SNES context */ 4605 if (snes->ops->destroy) { 4606 ierr = (*(snes)->ops->destroy)(snes);CHKERRQ(ierr); 4607 snes->ops->destroy = NULL; 4608 } 4609 /* Reinitialize function pointers in SNESOps structure */ 4610 snes->ops->setup = 0; 4611 snes->ops->solve = 0; 4612 snes->ops->view = 0; 4613 snes->ops->setfromoptions = 0; 4614 snes->ops->destroy = 0; 4615 /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */ 4616 snes->setupcalled = PETSC_FALSE; 4617 4618 ierr = PetscObjectChangeTypeName((PetscObject)snes,type);CHKERRQ(ierr); 4619 ierr = (*r)(snes);CHKERRQ(ierr); 4620 PetscFunctionReturn(0); 4621 } 4622 4623 /*@C 4624 SNESGetType - Gets the SNES method type and name (as a string). 4625 4626 Not Collective 4627 4628 Input Parameter: 4629 . snes - nonlinear solver context 4630 4631 Output Parameter: 4632 . type - SNES method (a character string) 4633 4634 Level: intermediate 4635 4636 .keywords: SNES, nonlinear, get, type, name 4637 @*/ 4638 PetscErrorCode SNESGetType(SNES snes,SNESType *type) 4639 { 4640 PetscFunctionBegin; 4641 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4642 PetscValidPointer(type,2); 4643 *type = ((PetscObject)snes)->type_name; 4644 PetscFunctionReturn(0); 4645 } 4646 4647 /*@ 4648 SNESSetSolution - Sets the solution vector for use by the SNES routines. 4649 4650 Logically Collective on SNES and Vec 4651 4652 Input Parameters: 4653 + snes - the SNES context obtained from SNESCreate() 4654 - u - the solution vector 4655 4656 Level: beginner 4657 4658 .keywords: SNES, set, solution 4659 @*/ 4660 PetscErrorCode SNESSetSolution(SNES snes, Vec u) 4661 { 4662 DM dm; 4663 PetscErrorCode ierr; 4664 4665 PetscFunctionBegin; 4666 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4667 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 4668 ierr = PetscObjectReference((PetscObject) u);CHKERRQ(ierr); 4669 ierr = VecDestroy(&snes->vec_sol);CHKERRQ(ierr); 4670 4671 snes->vec_sol = u; 4672 4673 ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr); 4674 ierr = DMShellSetGlobalVector(dm, u);CHKERRQ(ierr); 4675 PetscFunctionReturn(0); 4676 } 4677 4678 /*@ 4679 SNESGetSolution - Returns the vector where the approximate solution is 4680 stored. This is the fine grid solution when using SNESSetGridSequence(). 4681 4682 Not Collective, but Vec is parallel if SNES is parallel 4683 4684 Input Parameter: 4685 . snes - the SNES context 4686 4687 Output Parameter: 4688 . x - the solution 4689 4690 Level: intermediate 4691 4692 .keywords: SNES, nonlinear, get, solution 4693 4694 .seealso: SNESGetSolutionUpdate(), SNESGetFunction() 4695 @*/ 4696 PetscErrorCode SNESGetSolution(SNES snes,Vec *x) 4697 { 4698 PetscFunctionBegin; 4699 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4700 PetscValidPointer(x,2); 4701 *x = snes->vec_sol; 4702 PetscFunctionReturn(0); 4703 } 4704 4705 /*@ 4706 SNESGetSolutionUpdate - Returns the vector where the solution update is 4707 stored. 4708 4709 Not Collective, but Vec is parallel if SNES is parallel 4710 4711 Input Parameter: 4712 . snes - the SNES context 4713 4714 Output Parameter: 4715 . x - the solution update 4716 4717 Level: advanced 4718 4719 .keywords: SNES, nonlinear, get, solution, update 4720 4721 .seealso: SNESGetSolution(), SNESGetFunction() 4722 @*/ 4723 PetscErrorCode SNESGetSolutionUpdate(SNES snes,Vec *x) 4724 { 4725 PetscFunctionBegin; 4726 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4727 PetscValidPointer(x,2); 4728 *x = snes->vec_sol_update; 4729 PetscFunctionReturn(0); 4730 } 4731 4732 /*@C 4733 SNESGetFunction - Returns the vector where the function is stored. 4734 4735 Not Collective, but Vec is parallel if SNES is parallel. Collective if Vec is requested, but has not been created yet. 4736 4737 Input Parameter: 4738 . snes - the SNES context 4739 4740 Output Parameter: 4741 + r - the vector that is used to store residuals (or NULL if you don't want it) 4742 . f - the function (or NULL if you don't want it); see SNESFunction for calling sequence details 4743 - ctx - the function context (or NULL if you don't want it) 4744 4745 Level: advanced 4746 4747 Notes: The vector r DOES NOT, in general contain the current value of the SNES nonlinear function 4748 4749 .keywords: SNES, nonlinear, get, function 4750 4751 .seealso: SNESSetFunction(), SNESGetSolution(), SNESFunction 4752 @*/ 4753 PetscErrorCode SNESGetFunction(SNES snes,Vec *r,PetscErrorCode (**f)(SNES,Vec,Vec,void*),void **ctx) 4754 { 4755 PetscErrorCode ierr; 4756 DM dm; 4757 4758 PetscFunctionBegin; 4759 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4760 if (r) { 4761 if (!snes->vec_func) { 4762 if (snes->vec_rhs) { 4763 ierr = VecDuplicate(snes->vec_rhs,&snes->vec_func);CHKERRQ(ierr); 4764 } else if (snes->vec_sol) { 4765 ierr = VecDuplicate(snes->vec_sol,&snes->vec_func);CHKERRQ(ierr); 4766 } else if (snes->dm) { 4767 ierr = DMCreateGlobalVector(snes->dm,&snes->vec_func);CHKERRQ(ierr); 4768 } 4769 } 4770 *r = snes->vec_func; 4771 } 4772 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 4773 ierr = DMSNESGetFunction(dm,f,ctx);CHKERRQ(ierr); 4774 PetscFunctionReturn(0); 4775 } 4776 4777 /*@C 4778 SNESGetNGS - Returns the NGS function and context. 4779 4780 Input Parameter: 4781 . snes - the SNES context 4782 4783 Output Parameter: 4784 + f - the function (or NULL) see SNESNGSFunction for details 4785 - ctx - the function context (or NULL) 4786 4787 Level: advanced 4788 4789 .keywords: SNES, nonlinear, get, function 4790 4791 .seealso: SNESSetNGS(), SNESGetFunction() 4792 @*/ 4793 4794 PetscErrorCode SNESGetNGS (SNES snes, PetscErrorCode (**f)(SNES, Vec, Vec, void*), void ** ctx) 4795 { 4796 PetscErrorCode ierr; 4797 DM dm; 4798 4799 PetscFunctionBegin; 4800 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4801 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 4802 ierr = DMSNESGetNGS(dm,f,ctx);CHKERRQ(ierr); 4803 PetscFunctionReturn(0); 4804 } 4805 4806 /*@C 4807 SNESSetOptionsPrefix - Sets the prefix used for searching for all 4808 SNES options in the database. 4809 4810 Logically Collective on SNES 4811 4812 Input Parameter: 4813 + snes - the SNES context 4814 - prefix - the prefix to prepend to all option names 4815 4816 Notes: 4817 A hyphen (-) must NOT be given at the beginning of the prefix name. 4818 The first character of all runtime options is AUTOMATICALLY the hyphen. 4819 4820 Level: advanced 4821 4822 .keywords: SNES, set, options, prefix, database 4823 4824 .seealso: SNESSetFromOptions() 4825 @*/ 4826 PetscErrorCode SNESSetOptionsPrefix(SNES snes,const char prefix[]) 4827 { 4828 PetscErrorCode ierr; 4829 4830 PetscFunctionBegin; 4831 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4832 ierr = PetscObjectSetOptionsPrefix((PetscObject)snes,prefix);CHKERRQ(ierr); 4833 if (!snes->ksp) {ierr = SNESGetKSP(snes,&snes->ksp);CHKERRQ(ierr);} 4834 if (snes->linesearch) { 4835 ierr = SNESGetLineSearch(snes,&snes->linesearch);CHKERRQ(ierr); 4836 ierr = PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch,prefix);CHKERRQ(ierr); 4837 } 4838 ierr = KSPSetOptionsPrefix(snes->ksp,prefix);CHKERRQ(ierr); 4839 PetscFunctionReturn(0); 4840 } 4841 4842 /*@C 4843 SNESAppendOptionsPrefix - Appends to the prefix used for searching for all 4844 SNES options in the database. 4845 4846 Logically Collective on SNES 4847 4848 Input Parameters: 4849 + snes - the SNES context 4850 - prefix - the prefix to prepend to all option names 4851 4852 Notes: 4853 A hyphen (-) must NOT be given at the beginning of the prefix name. 4854 The first character of all runtime options is AUTOMATICALLY the hyphen. 4855 4856 Level: advanced 4857 4858 .keywords: SNES, append, options, prefix, database 4859 4860 .seealso: SNESGetOptionsPrefix() 4861 @*/ 4862 PetscErrorCode SNESAppendOptionsPrefix(SNES snes,const char prefix[]) 4863 { 4864 PetscErrorCode ierr; 4865 4866 PetscFunctionBegin; 4867 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4868 ierr = PetscObjectAppendOptionsPrefix((PetscObject)snes,prefix);CHKERRQ(ierr); 4869 if (!snes->ksp) {ierr = SNESGetKSP(snes,&snes->ksp);CHKERRQ(ierr);} 4870 if (snes->linesearch) { 4871 ierr = SNESGetLineSearch(snes,&snes->linesearch);CHKERRQ(ierr); 4872 ierr = PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch,prefix);CHKERRQ(ierr); 4873 } 4874 ierr = KSPAppendOptionsPrefix(snes->ksp,prefix);CHKERRQ(ierr); 4875 PetscFunctionReturn(0); 4876 } 4877 4878 /*@C 4879 SNESGetOptionsPrefix - Sets the prefix used for searching for all 4880 SNES options in the database. 4881 4882 Not Collective 4883 4884 Input Parameter: 4885 . snes - the SNES context 4886 4887 Output Parameter: 4888 . prefix - pointer to the prefix string used 4889 4890 Notes: 4891 On the fortran side, the user should pass in a string 'prefix' of 4892 sufficient length to hold the prefix. 4893 4894 Level: advanced 4895 4896 .keywords: SNES, get, options, prefix, database 4897 4898 .seealso: SNESAppendOptionsPrefix() 4899 @*/ 4900 PetscErrorCode SNESGetOptionsPrefix(SNES snes,const char *prefix[]) 4901 { 4902 PetscErrorCode ierr; 4903 4904 PetscFunctionBegin; 4905 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4906 ierr = PetscObjectGetOptionsPrefix((PetscObject)snes,prefix);CHKERRQ(ierr); 4907 PetscFunctionReturn(0); 4908 } 4909 4910 4911 /*@C 4912 SNESRegister - Adds a method to the nonlinear solver package. 4913 4914 Not collective 4915 4916 Input Parameters: 4917 + name_solver - name of a new user-defined solver 4918 - routine_create - routine to create method context 4919 4920 Notes: 4921 SNESRegister() may be called multiple times to add several user-defined solvers. 4922 4923 Sample usage: 4924 .vb 4925 SNESRegister("my_solver",MySolverCreate); 4926 .ve 4927 4928 Then, your solver can be chosen with the procedural interface via 4929 $ SNESSetType(snes,"my_solver") 4930 or at runtime via the option 4931 $ -snes_type my_solver 4932 4933 Level: advanced 4934 4935 Note: If your function is not being put into a shared library then use SNESRegister() instead 4936 4937 .keywords: SNES, nonlinear, register 4938 4939 .seealso: SNESRegisterAll(), SNESRegisterDestroy() 4940 4941 Level: advanced 4942 @*/ 4943 PetscErrorCode SNESRegister(const char sname[],PetscErrorCode (*function)(SNES)) 4944 { 4945 PetscErrorCode ierr; 4946 4947 PetscFunctionBegin; 4948 ierr = SNESInitializePackage();CHKERRQ(ierr); 4949 ierr = PetscFunctionListAdd(&SNESList,sname,function);CHKERRQ(ierr); 4950 PetscFunctionReturn(0); 4951 } 4952 4953 PetscErrorCode SNESTestLocalMin(SNES snes) 4954 { 4955 PetscErrorCode ierr; 4956 PetscInt N,i,j; 4957 Vec u,uh,fh; 4958 PetscScalar value; 4959 PetscReal norm; 4960 4961 PetscFunctionBegin; 4962 ierr = SNESGetSolution(snes,&u);CHKERRQ(ierr); 4963 ierr = VecDuplicate(u,&uh);CHKERRQ(ierr); 4964 ierr = VecDuplicate(u,&fh);CHKERRQ(ierr); 4965 4966 /* currently only works for sequential */ 4967 ierr = PetscPrintf(PETSC_COMM_WORLD,"Testing FormFunction() for local min\n");CHKERRQ(ierr); 4968 ierr = VecGetSize(u,&N);CHKERRQ(ierr); 4969 for (i=0; i<N; i++) { 4970 ierr = VecCopy(u,uh);CHKERRQ(ierr); 4971 ierr = PetscPrintf(PETSC_COMM_WORLD,"i = %D\n",i);CHKERRQ(ierr); 4972 for (j=-10; j<11; j++) { 4973 value = PetscSign(j)*PetscExpReal(PetscAbs(j)-10.0); 4974 ierr = VecSetValue(uh,i,value,ADD_VALUES);CHKERRQ(ierr); 4975 ierr = SNESComputeFunction(snes,uh,fh);CHKERRQ(ierr); 4976 ierr = VecNorm(fh,NORM_2,&norm);CHKERRQ(ierr); 4977 ierr = PetscPrintf(PETSC_COMM_WORLD," j norm %D %18.16e\n",j,norm);CHKERRQ(ierr); 4978 value = -value; 4979 ierr = VecSetValue(uh,i,value,ADD_VALUES);CHKERRQ(ierr); 4980 } 4981 } 4982 ierr = VecDestroy(&uh);CHKERRQ(ierr); 4983 ierr = VecDestroy(&fh);CHKERRQ(ierr); 4984 PetscFunctionReturn(0); 4985 } 4986 4987 /*@ 4988 SNESKSPSetUseEW - Sets SNES use Eisenstat-Walker method for 4989 computing relative tolerance for linear solvers within an inexact 4990 Newton method. 4991 4992 Logically Collective on SNES 4993 4994 Input Parameters: 4995 + snes - SNES context 4996 - flag - PETSC_TRUE or PETSC_FALSE 4997 4998 Options Database: 4999 + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence 5000 . -snes_ksp_ew_version ver - version of Eisenstat-Walker method 5001 . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0 5002 . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax 5003 . -snes_ksp_ew_gamma <gamma> - Sets gamma 5004 . -snes_ksp_ew_alpha <alpha> - Sets alpha 5005 . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2 5006 - -snes_ksp_ew_threshold <threshold> - Sets threshold 5007 5008 Notes: 5009 Currently, the default is to use a constant relative tolerance for 5010 the inner linear solvers. Alternatively, one can use the 5011 Eisenstat-Walker method, where the relative convergence tolerance 5012 is reset at each Newton iteration according progress of the nonlinear 5013 solver. 5014 5015 Level: advanced 5016 5017 Reference: 5018 S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an 5019 inexact Newton method", SISC 17 (1), pp.16-32, 1996. 5020 5021 .keywords: SNES, KSP, Eisenstat, Walker, convergence, test, inexact, Newton 5022 5023 .seealso: SNESKSPGetUseEW(), SNESKSPGetParametersEW(), SNESKSPSetParametersEW() 5024 @*/ 5025 PetscErrorCode SNESKSPSetUseEW(SNES snes,PetscBool flag) 5026 { 5027 PetscFunctionBegin; 5028 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 5029 PetscValidLogicalCollectiveBool(snes,flag,2); 5030 snes->ksp_ewconv = flag; 5031 PetscFunctionReturn(0); 5032 } 5033 5034 /*@ 5035 SNESKSPGetUseEW - Gets if SNES is using Eisenstat-Walker method 5036 for computing relative tolerance for linear solvers within an 5037 inexact Newton method. 5038 5039 Not Collective 5040 5041 Input Parameter: 5042 . snes - SNES context 5043 5044 Output Parameter: 5045 . flag - PETSC_TRUE or PETSC_FALSE 5046 5047 Notes: 5048 Currently, the default is to use a constant relative tolerance for 5049 the inner linear solvers. Alternatively, one can use the 5050 Eisenstat-Walker method, where the relative convergence tolerance 5051 is reset at each Newton iteration according progress of the nonlinear 5052 solver. 5053 5054 Level: advanced 5055 5056 Reference: 5057 S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an 5058 inexact Newton method", SISC 17 (1), pp.16-32, 1996. 5059 5060 .keywords: SNES, KSP, Eisenstat, Walker, convergence, test, inexact, Newton 5061 5062 .seealso: SNESKSPSetUseEW(), SNESKSPGetParametersEW(), SNESKSPSetParametersEW() 5063 @*/ 5064 PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag) 5065 { 5066 PetscFunctionBegin; 5067 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 5068 PetscValidPointer(flag,2); 5069 *flag = snes->ksp_ewconv; 5070 PetscFunctionReturn(0); 5071 } 5072 5073 /*@ 5074 SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker 5075 convergence criteria for the linear solvers within an inexact 5076 Newton method. 5077 5078 Logically Collective on SNES 5079 5080 Input Parameters: 5081 + snes - SNES context 5082 . version - version 1, 2 (default is 2) or 3 5083 . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 5084 . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 5085 . gamma - multiplicative factor for version 2 rtol computation 5086 (0 <= gamma2 <= 1) 5087 . alpha - power for version 2 rtol computation (1 < alpha <= 2) 5088 . alpha2 - power for safeguard 5089 - threshold - threshold for imposing safeguard (0 < threshold < 1) 5090 5091 Note: 5092 Version 3 was contributed by Luis Chacon, June 2006. 5093 5094 Use PETSC_DEFAULT to retain the default for any of the parameters. 5095 5096 Level: advanced 5097 5098 Reference: 5099 S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an 5100 inexact Newton method", Utah State University Math. Stat. Dept. Res. 5101 Report 6/94/75, June, 1994, to appear in SIAM J. Sci. Comput. 5102 5103 .keywords: SNES, KSP, Eisenstat, Walker, set, parameters 5104 5105 .seealso: SNESKSPSetUseEW(), SNESKSPGetUseEW(), SNESKSPGetParametersEW() 5106 @*/ 5107 PetscErrorCode SNESKSPSetParametersEW(SNES snes,PetscInt version,PetscReal rtol_0,PetscReal rtol_max,PetscReal gamma,PetscReal alpha,PetscReal alpha2,PetscReal threshold) 5108 { 5109 SNESKSPEW *kctx; 5110 5111 PetscFunctionBegin; 5112 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 5113 kctx = (SNESKSPEW*)snes->kspconvctx; 5114 if (!kctx) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context existing"); 5115 PetscValidLogicalCollectiveInt(snes,version,2); 5116 PetscValidLogicalCollectiveReal(snes,rtol_0,3); 5117 PetscValidLogicalCollectiveReal(snes,rtol_max,4); 5118 PetscValidLogicalCollectiveReal(snes,gamma,5); 5119 PetscValidLogicalCollectiveReal(snes,alpha,6); 5120 PetscValidLogicalCollectiveReal(snes,alpha2,7); 5121 PetscValidLogicalCollectiveReal(snes,threshold,8); 5122 5123 if (version != PETSC_DEFAULT) kctx->version = version; 5124 if (rtol_0 != PETSC_DEFAULT) kctx->rtol_0 = rtol_0; 5125 if (rtol_max != PETSC_DEFAULT) kctx->rtol_max = rtol_max; 5126 if (gamma != PETSC_DEFAULT) kctx->gamma = gamma; 5127 if (alpha != PETSC_DEFAULT) kctx->alpha = alpha; 5128 if (alpha2 != PETSC_DEFAULT) kctx->alpha2 = alpha2; 5129 if (threshold != PETSC_DEFAULT) kctx->threshold = threshold; 5130 5131 if (kctx->version < 1 || kctx->version > 3) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Only versions 1, 2 and 3 are supported: %D",kctx->version); 5132 if (kctx->rtol_0 < 0.0 || kctx->rtol_0 >= 1.0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= rtol_0 < 1.0: %g",(double)kctx->rtol_0); 5133 if (kctx->rtol_max < 0.0 || kctx->rtol_max >= 1.0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= rtol_max (%g) < 1.0\n",(double)kctx->rtol_max); 5134 if (kctx->gamma < 0.0 || kctx->gamma > 1.0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"0.0 <= gamma (%g) <= 1.0\n",(double)kctx->gamma); 5135 if (kctx->alpha <= 1.0 || kctx->alpha > 2.0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"1.0 < alpha (%g) <= 2.0\n",(double)kctx->alpha); 5136 if (kctx->threshold <= 0.0 || kctx->threshold >= 1.0) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"0.0 < threshold (%g) < 1.0\n",(double)kctx->threshold); 5137 PetscFunctionReturn(0); 5138 } 5139 5140 /*@ 5141 SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker 5142 convergence criteria for the linear solvers within an inexact 5143 Newton method. 5144 5145 Not Collective 5146 5147 Input Parameters: 5148 snes - SNES context 5149 5150 Output Parameters: 5151 + version - version 1, 2 (default is 2) or 3 5152 . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 5153 . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 5154 . gamma - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1) 5155 . alpha - power for version 2 rtol computation (1 < alpha <= 2) 5156 . alpha2 - power for safeguard 5157 - threshold - threshold for imposing safeguard (0 < threshold < 1) 5158 5159 Level: advanced 5160 5161 .keywords: SNES, KSP, Eisenstat, Walker, get, parameters 5162 5163 .seealso: SNESKSPSetUseEW(), SNESKSPGetUseEW(), SNESKSPSetParametersEW() 5164 @*/ 5165 PetscErrorCode SNESKSPGetParametersEW(SNES snes,PetscInt *version,PetscReal *rtol_0,PetscReal *rtol_max,PetscReal *gamma,PetscReal *alpha,PetscReal *alpha2,PetscReal *threshold) 5166 { 5167 SNESKSPEW *kctx; 5168 5169 PetscFunctionBegin; 5170 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 5171 kctx = (SNESKSPEW*)snes->kspconvctx; 5172 if (!kctx) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context existing"); 5173 if (version) *version = kctx->version; 5174 if (rtol_0) *rtol_0 = kctx->rtol_0; 5175 if (rtol_max) *rtol_max = kctx->rtol_max; 5176 if (gamma) *gamma = kctx->gamma; 5177 if (alpha) *alpha = kctx->alpha; 5178 if (alpha2) *alpha2 = kctx->alpha2; 5179 if (threshold) *threshold = kctx->threshold; 5180 PetscFunctionReturn(0); 5181 } 5182 5183 PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, SNES snes) 5184 { 5185 PetscErrorCode ierr; 5186 SNESKSPEW *kctx = (SNESKSPEW*)snes->kspconvctx; 5187 PetscReal rtol = PETSC_DEFAULT,stol; 5188 5189 PetscFunctionBegin; 5190 if (!snes->ksp_ewconv) PetscFunctionReturn(0); 5191 if (!snes->iter) { 5192 rtol = kctx->rtol_0; /* first time in, so use the original user rtol */ 5193 ierr = VecNorm(snes->vec_func,NORM_2,&kctx->norm_first);CHKERRQ(ierr); 5194 } 5195 else { 5196 if (kctx->version == 1) { 5197 rtol = (snes->norm - kctx->lresid_last)/kctx->norm_last; 5198 if (rtol < 0.0) rtol = -rtol; 5199 stol = PetscPowReal(kctx->rtol_last,kctx->alpha2); 5200 if (stol > kctx->threshold) rtol = PetscMax(rtol,stol); 5201 } else if (kctx->version == 2) { 5202 rtol = kctx->gamma * PetscPowReal(snes->norm/kctx->norm_last,kctx->alpha); 5203 stol = kctx->gamma * PetscPowReal(kctx->rtol_last,kctx->alpha); 5204 if (stol > kctx->threshold) rtol = PetscMax(rtol,stol); 5205 } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */ 5206 rtol = kctx->gamma * PetscPowReal(snes->norm/kctx->norm_last,kctx->alpha); 5207 /* safeguard: avoid sharp decrease of rtol */ 5208 stol = kctx->gamma*PetscPowReal(kctx->rtol_last,kctx->alpha); 5209 stol = PetscMax(rtol,stol); 5210 rtol = PetscMin(kctx->rtol_0,stol); 5211 /* safeguard: avoid oversolving */ 5212 stol = kctx->gamma*(kctx->norm_first*snes->rtol)/snes->norm; 5213 stol = PetscMax(rtol,stol); 5214 rtol = PetscMin(kctx->rtol_0,stol); 5215 } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Only versions 1, 2 or 3 are supported: %D",kctx->version); 5216 } 5217 /* safeguard: avoid rtol greater than one */ 5218 rtol = PetscMin(rtol,kctx->rtol_max); 5219 ierr = KSPSetTolerances(ksp,rtol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);CHKERRQ(ierr); 5220 ierr = PetscInfo3(snes,"iter %D, Eisenstat-Walker (version %D) KSP rtol=%g\n",snes->iter,kctx->version,(double)rtol);CHKERRQ(ierr); 5221 PetscFunctionReturn(0); 5222 } 5223 5224 PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, SNES snes) 5225 { 5226 PetscErrorCode ierr; 5227 SNESKSPEW *kctx = (SNESKSPEW*)snes->kspconvctx; 5228 PCSide pcside; 5229 Vec lres; 5230 5231 PetscFunctionBegin; 5232 if (!snes->ksp_ewconv) PetscFunctionReturn(0); 5233 ierr = KSPGetTolerances(ksp,&kctx->rtol_last,0,0,0);CHKERRQ(ierr); 5234 kctx->norm_last = snes->norm; 5235 if (kctx->version == 1) { 5236 PC pc; 5237 PetscBool isNone; 5238 5239 ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr); 5240 ierr = PetscObjectTypeCompare((PetscObject) pc, PCNONE, &isNone);CHKERRQ(ierr); 5241 ierr = KSPGetPCSide(ksp,&pcside);CHKERRQ(ierr); 5242 if (pcside == PC_RIGHT || isNone) { /* XXX Should we also test KSP_UNPRECONDITIONED_NORM ? */ 5243 /* KSP residual is true linear residual */ 5244 ierr = KSPGetResidualNorm(ksp,&kctx->lresid_last);CHKERRQ(ierr); 5245 } else { 5246 /* KSP residual is preconditioned residual */ 5247 /* compute true linear residual norm */ 5248 ierr = VecDuplicate(b,&lres);CHKERRQ(ierr); 5249 ierr = MatMult(snes->jacobian,x,lres);CHKERRQ(ierr); 5250 ierr = VecAYPX(lres,-1.0,b);CHKERRQ(ierr); 5251 ierr = VecNorm(lres,NORM_2,&kctx->lresid_last);CHKERRQ(ierr); 5252 ierr = VecDestroy(&lres);CHKERRQ(ierr); 5253 } 5254 } 5255 PetscFunctionReturn(0); 5256 } 5257 5258 /*@ 5259 SNESGetKSP - Returns the KSP context for a SNES solver. 5260 5261 Not Collective, but if SNES object is parallel, then KSP object is parallel 5262 5263 Input Parameter: 5264 . snes - the SNES context 5265 5266 Output Parameter: 5267 . ksp - the KSP context 5268 5269 Notes: 5270 The user can then directly manipulate the KSP context to set various 5271 options, etc. Likewise, the user can then extract and manipulate the 5272 PC contexts as well. 5273 5274 Level: beginner 5275 5276 .keywords: SNES, nonlinear, get, KSP, context 5277 5278 .seealso: KSPGetPC(), SNESCreate(), KSPCreate(), SNESSetKSP() 5279 @*/ 5280 PetscErrorCode SNESGetKSP(SNES snes,KSP *ksp) 5281 { 5282 PetscErrorCode ierr; 5283 5284 PetscFunctionBegin; 5285 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 5286 PetscValidPointer(ksp,2); 5287 5288 if (!snes->ksp) { 5289 PetscBool monitor = PETSC_FALSE; 5290 5291 ierr = KSPCreate(PetscObjectComm((PetscObject)snes),&snes->ksp);CHKERRQ(ierr); 5292 ierr = PetscObjectIncrementTabLevel((PetscObject)snes->ksp,(PetscObject)snes,1);CHKERRQ(ierr); 5293 ierr = PetscLogObjectParent((PetscObject)snes,(PetscObject)snes->ksp);CHKERRQ(ierr); 5294 5295 ierr = KSPSetPreSolve(snes->ksp,(PetscErrorCode (*)(KSP,Vec,Vec,void*))KSPPreSolve_SNESEW,snes);CHKERRQ(ierr); 5296 ierr = KSPSetPostSolve(snes->ksp,(PetscErrorCode (*)(KSP,Vec,Vec,void*))KSPPostSolve_SNESEW,snes);CHKERRQ(ierr); 5297 5298 ierr = PetscOptionsGetBool(((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-ksp_monitor_snes",&monitor,NULL);CHKERRQ(ierr); 5299 if (monitor) { 5300 ierr = KSPMonitorSet(snes->ksp,KSPMonitorSNES,snes,NULL);CHKERRQ(ierr); 5301 } 5302 monitor = PETSC_FALSE; 5303 ierr = PetscOptionsGetBool(((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-ksp_monitor_snes_lg",&monitor,NULL);CHKERRQ(ierr); 5304 if (monitor) { 5305 PetscObject *objs; 5306 ierr = KSPMonitorSNESLGResidualNormCreate(PetscObjectComm((PetscObject)snes),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,600,600,&objs);CHKERRQ(ierr); 5307 objs[0] = (PetscObject) snes; 5308 ierr = KSPMonitorSet(snes->ksp,(PetscErrorCode (*)(KSP,PetscInt,PetscReal,void*))KSPMonitorSNESLGResidualNorm,objs,(PetscErrorCode (*)(void**))KSPMonitorSNESLGResidualNormDestroy);CHKERRQ(ierr); 5309 } 5310 ierr = PetscObjectSetOptions((PetscObject)snes->ksp,((PetscObject)snes)->options);CHKERRQ(ierr); 5311 } 5312 *ksp = snes->ksp; 5313 PetscFunctionReturn(0); 5314 } 5315 5316 5317 #include <petsc/private/dmimpl.h> 5318 /*@ 5319 SNESSetDM - Sets the DM that may be used by some nonlinear solvers or their underlying preconditioners 5320 5321 Logically Collective on SNES 5322 5323 Input Parameters: 5324 + snes - the nonlinear solver context 5325 - dm - the dm, cannot be NULL 5326 5327 Notes: 5328 A DM can only be used for solving one problem at a time because information about the problem is stored on the DM, 5329 even when not using interfaces like DMSNESSetFunction(). Use DMClone() to get a distinct DM when solving different 5330 problems using the same function space. 5331 5332 Level: intermediate 5333 5334 .seealso: SNESGetDM(), KSPSetDM(), KSPGetDM() 5335 @*/ 5336 PetscErrorCode SNESSetDM(SNES snes,DM dm) 5337 { 5338 PetscErrorCode ierr; 5339 KSP ksp; 5340 DMSNES sdm; 5341 5342 PetscFunctionBegin; 5343 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 5344 PetscValidHeaderSpecific(dm,DM_CLASSID,2); 5345 ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr); 5346 if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */ 5347 if (snes->dm->dmsnes && !dm->dmsnes) { 5348 ierr = DMCopyDMSNES(snes->dm,dm);CHKERRQ(ierr); 5349 ierr = DMGetDMSNES(snes->dm,&sdm);CHKERRQ(ierr); 5350 if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */ 5351 } 5352 ierr = DMCoarsenHookRemove(snes->dm,DMCoarsenHook_SNESVecSol,DMRestrictHook_SNESVecSol,snes);CHKERRQ(ierr); 5353 ierr = DMDestroy(&snes->dm);CHKERRQ(ierr); 5354 } 5355 snes->dm = dm; 5356 snes->dmAuto = PETSC_FALSE; 5357 5358 ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr); 5359 ierr = KSPSetDM(ksp,dm);CHKERRQ(ierr); 5360 ierr = KSPSetDMActive(ksp,PETSC_FALSE);CHKERRQ(ierr); 5361 if (snes->npc) { 5362 ierr = SNESSetDM(snes->npc, snes->dm);CHKERRQ(ierr); 5363 ierr = SNESSetNPCSide(snes,snes->npcside);CHKERRQ(ierr); 5364 } 5365 PetscFunctionReturn(0); 5366 } 5367 5368 /*@ 5369 SNESGetDM - Gets the DM that may be used by some preconditioners 5370 5371 Not Collective but DM obtained is parallel on SNES 5372 5373 Input Parameter: 5374 . snes - the preconditioner context 5375 5376 Output Parameter: 5377 . dm - the dm 5378 5379 Level: intermediate 5380 5381 .seealso: SNESSetDM(), KSPSetDM(), KSPGetDM() 5382 @*/ 5383 PetscErrorCode SNESGetDM(SNES snes,DM *dm) 5384 { 5385 PetscErrorCode ierr; 5386 5387 PetscFunctionBegin; 5388 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 5389 if (!snes->dm) { 5390 ierr = DMShellCreate(PetscObjectComm((PetscObject)snes),&snes->dm);CHKERRQ(ierr); 5391 snes->dmAuto = PETSC_TRUE; 5392 } 5393 *dm = snes->dm; 5394 PetscFunctionReturn(0); 5395 } 5396 5397 /*@ 5398 SNESSetNPC - Sets the nonlinear preconditioner to be used. 5399 5400 Collective on SNES 5401 5402 Input Parameters: 5403 + snes - iterative context obtained from SNESCreate() 5404 - pc - the preconditioner object 5405 5406 Notes: 5407 Use SNESGetNPC() to retrieve the preconditioner context (for example, 5408 to configure it using the API). 5409 5410 Level: developer 5411 5412 .keywords: SNES, set, precondition 5413 .seealso: SNESGetNPC(), SNESHasNPC() 5414 @*/ 5415 PetscErrorCode SNESSetNPC(SNES snes, SNES pc) 5416 { 5417 PetscErrorCode ierr; 5418 5419 PetscFunctionBegin; 5420 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5421 PetscValidHeaderSpecific(pc, SNES_CLASSID, 2); 5422 PetscCheckSameComm(snes, 1, pc, 2); 5423 ierr = PetscObjectReference((PetscObject) pc);CHKERRQ(ierr); 5424 ierr = SNESDestroy(&snes->npc);CHKERRQ(ierr); 5425 snes->npc = pc; 5426 ierr = PetscLogObjectParent((PetscObject)snes, (PetscObject)snes->npc);CHKERRQ(ierr); 5427 PetscFunctionReturn(0); 5428 } 5429 5430 /*@ 5431 SNESGetNPC - Creates a nonlinear preconditioning solver (SNES) to be used to precondition the nonlinear solver. 5432 5433 Not Collective 5434 5435 Input Parameter: 5436 . snes - iterative context obtained from SNESCreate() 5437 5438 Output Parameter: 5439 . pc - preconditioner context 5440 5441 Notes: 5442 If a SNES was previously set with SNESSetNPC() then that SNES is returned. 5443 5444 Level: developer 5445 5446 .keywords: SNES, get, preconditioner 5447 .seealso: SNESSetNPC(), SNESHasNPC() 5448 @*/ 5449 PetscErrorCode SNESGetNPC(SNES snes, SNES *pc) 5450 { 5451 PetscErrorCode ierr; 5452 const char *optionsprefix; 5453 5454 PetscFunctionBegin; 5455 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5456 PetscValidPointer(pc, 2); 5457 if (!snes->npc) { 5458 ierr = SNESCreate(PetscObjectComm((PetscObject)snes),&snes->npc);CHKERRQ(ierr); 5459 ierr = PetscObjectIncrementTabLevel((PetscObject)snes->npc,(PetscObject)snes,1);CHKERRQ(ierr); 5460 ierr = PetscLogObjectParent((PetscObject)snes,(PetscObject)snes->npc);CHKERRQ(ierr); 5461 ierr = SNESGetOptionsPrefix(snes,&optionsprefix);CHKERRQ(ierr); 5462 ierr = SNESSetOptionsPrefix(snes->npc,optionsprefix);CHKERRQ(ierr); 5463 ierr = SNESAppendOptionsPrefix(snes->npc,"npc_");CHKERRQ(ierr); 5464 ierr = SNESSetCountersReset(snes->npc,PETSC_FALSE);CHKERRQ(ierr); 5465 } 5466 *pc = snes->npc; 5467 PetscFunctionReturn(0); 5468 } 5469 5470 /*@ 5471 SNESHasNPC - Returns whether a nonlinear preconditioner exists 5472 5473 Not Collective 5474 5475 Input Parameter: 5476 . snes - iterative context obtained from SNESCreate() 5477 5478 Output Parameter: 5479 . has_npc - whether the SNES has an NPC or not 5480 5481 Level: developer 5482 5483 .keywords: SNES, has, preconditioner 5484 .seealso: SNESSetNPC(), SNESGetNPC() 5485 @*/ 5486 PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc) 5487 { 5488 PetscFunctionBegin; 5489 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5490 *has_npc = (PetscBool) (snes->npc ? PETSC_TRUE : PETSC_FALSE); 5491 PetscFunctionReturn(0); 5492 } 5493 5494 /*@ 5495 SNESSetNPCSide - Sets the preconditioning side. 5496 5497 Logically Collective on SNES 5498 5499 Input Parameter: 5500 . snes - iterative context obtained from SNESCreate() 5501 5502 Output Parameter: 5503 . side - the preconditioning side, where side is one of 5504 .vb 5505 PC_LEFT - left preconditioning 5506 PC_RIGHT - right preconditioning (default for most nonlinear solvers) 5507 .ve 5508 5509 Options Database Keys: 5510 . -snes_pc_side <right,left> 5511 5512 Notes: 5513 SNESNRICHARDSON and SNESNCG only support left preconditioning. 5514 5515 Level: intermediate 5516 5517 .keywords: SNES, set, right, left, side, preconditioner, flag 5518 5519 .seealso: SNESGetNPCSide(), KSPSetPCSide() 5520 @*/ 5521 PetscErrorCode SNESSetNPCSide(SNES snes,PCSide side) 5522 { 5523 PetscFunctionBegin; 5524 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 5525 PetscValidLogicalCollectiveEnum(snes,side,2); 5526 snes->npcside= side; 5527 PetscFunctionReturn(0); 5528 } 5529 5530 /*@ 5531 SNESGetNPCSide - Gets the preconditioning side. 5532 5533 Not Collective 5534 5535 Input Parameter: 5536 . snes - iterative context obtained from SNESCreate() 5537 5538 Output Parameter: 5539 . side - the preconditioning side, where side is one of 5540 .vb 5541 PC_LEFT - left preconditioning 5542 PC_RIGHT - right preconditioning (default for most nonlinear solvers) 5543 .ve 5544 5545 Level: intermediate 5546 5547 .keywords: SNES, get, right, left, side, preconditioner, flag 5548 5549 .seealso: SNESSetNPCSide(), KSPGetPCSide() 5550 @*/ 5551 PetscErrorCode SNESGetNPCSide(SNES snes,PCSide *side) 5552 { 5553 PetscFunctionBegin; 5554 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 5555 PetscValidPointer(side,2); 5556 *side = snes->npcside; 5557 PetscFunctionReturn(0); 5558 } 5559 5560 /*@ 5561 SNESSetLineSearch - Sets the linesearch on the SNES instance. 5562 5563 Collective on SNES 5564 5565 Input Parameters: 5566 + snes - iterative context obtained from SNESCreate() 5567 - linesearch - the linesearch object 5568 5569 Notes: 5570 Use SNESGetLineSearch() to retrieve the preconditioner context (for example, 5571 to configure it using the API). 5572 5573 Level: developer 5574 5575 .keywords: SNES, set, linesearch 5576 .seealso: SNESGetLineSearch() 5577 @*/ 5578 PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch) 5579 { 5580 PetscErrorCode ierr; 5581 5582 PetscFunctionBegin; 5583 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5584 PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2); 5585 PetscCheckSameComm(snes, 1, linesearch, 2); 5586 ierr = PetscObjectReference((PetscObject) linesearch);CHKERRQ(ierr); 5587 ierr = SNESLineSearchDestroy(&snes->linesearch);CHKERRQ(ierr); 5588 5589 snes->linesearch = linesearch; 5590 5591 ierr = PetscLogObjectParent((PetscObject)snes, (PetscObject)snes->linesearch);CHKERRQ(ierr); 5592 PetscFunctionReturn(0); 5593 } 5594 5595 /*@ 5596 SNESGetLineSearch - Returns a pointer to the line search context set with SNESSetLineSearch() 5597 or creates a default line search instance associated with the SNES and returns it. 5598 5599 Not Collective 5600 5601 Input Parameter: 5602 . snes - iterative context obtained from SNESCreate() 5603 5604 Output Parameter: 5605 . linesearch - linesearch context 5606 5607 Level: beginner 5608 5609 .keywords: SNES, get, linesearch 5610 .seealso: SNESSetLineSearch(), SNESLineSearchCreate() 5611 @*/ 5612 PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch) 5613 { 5614 PetscErrorCode ierr; 5615 const char *optionsprefix; 5616 5617 PetscFunctionBegin; 5618 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5619 PetscValidPointer(linesearch, 2); 5620 if (!snes->linesearch) { 5621 ierr = SNESGetOptionsPrefix(snes, &optionsprefix);CHKERRQ(ierr); 5622 ierr = SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch);CHKERRQ(ierr); 5623 ierr = SNESLineSearchSetSNES(snes->linesearch, snes);CHKERRQ(ierr); 5624 ierr = SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix);CHKERRQ(ierr); 5625 ierr = PetscObjectIncrementTabLevel((PetscObject) snes->linesearch, (PetscObject) snes, 1);CHKERRQ(ierr); 5626 ierr = PetscLogObjectParent((PetscObject)snes, (PetscObject)snes->linesearch);CHKERRQ(ierr); 5627 } 5628 *linesearch = snes->linesearch; 5629 PetscFunctionReturn(0); 5630 } 5631 5632 #if defined(PETSC_HAVE_MATLAB_ENGINE) 5633 #include <mex.h> 5634 5635 typedef struct {char *funcname; mxArray *ctx;} SNESMatlabContext; 5636 5637 /* 5638 SNESComputeFunction_Matlab - Calls the function that has been set with SNESSetFunctionMatlab(). 5639 5640 Collective on SNES 5641 5642 Input Parameters: 5643 + snes - the SNES context 5644 - x - input vector 5645 5646 Output Parameter: 5647 . y - function vector, as set by SNESSetFunction() 5648 5649 Notes: 5650 SNESComputeFunction() is typically used within nonlinear solvers 5651 implementations, so most users would not generally call this routine 5652 themselves. 5653 5654 Level: developer 5655 5656 .keywords: SNES, nonlinear, compute, function 5657 5658 .seealso: SNESSetFunction(), SNESGetFunction() 5659 */ 5660 PetscErrorCode SNESComputeFunction_Matlab(SNES snes,Vec x,Vec y, void *ctx) 5661 { 5662 PetscErrorCode ierr; 5663 SNESMatlabContext *sctx = (SNESMatlabContext*)ctx; 5664 int nlhs = 1,nrhs = 5; 5665 mxArray *plhs[1],*prhs[5]; 5666 long long int lx = 0,ly = 0,ls = 0; 5667 5668 PetscFunctionBegin; 5669 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 5670 PetscValidHeaderSpecific(x,VEC_CLASSID,2); 5671 PetscValidHeaderSpecific(y,VEC_CLASSID,3); 5672 PetscCheckSameComm(snes,1,x,2); 5673 PetscCheckSameComm(snes,1,y,3); 5674 5675 /* call Matlab function in ctx with arguments x and y */ 5676 5677 ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr); 5678 ierr = PetscMemcpy(&lx,&x,sizeof(x));CHKERRQ(ierr); 5679 ierr = PetscMemcpy(&ly,&y,sizeof(x));CHKERRQ(ierr); 5680 prhs[0] = mxCreateDoubleScalar((double)ls); 5681 prhs[1] = mxCreateDoubleScalar((double)lx); 5682 prhs[2] = mxCreateDoubleScalar((double)ly); 5683 prhs[3] = mxCreateString(sctx->funcname); 5684 prhs[4] = sctx->ctx; 5685 ierr = mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESComputeFunctionInternal");CHKERRQ(ierr); 5686 ierr = mxGetScalar(plhs[0]);CHKERRQ(ierr); 5687 mxDestroyArray(prhs[0]); 5688 mxDestroyArray(prhs[1]); 5689 mxDestroyArray(prhs[2]); 5690 mxDestroyArray(prhs[3]); 5691 mxDestroyArray(plhs[0]); 5692 PetscFunctionReturn(0); 5693 } 5694 5695 /* 5696 SNESSetFunctionMatlab - Sets the function evaluation routine and function 5697 vector for use by the SNES routines in solving systems of nonlinear 5698 equations from MATLAB. Here the function is a string containing the name of a MATLAB function 5699 5700 Logically Collective on SNES 5701 5702 Input Parameters: 5703 + snes - the SNES context 5704 . r - vector to store function value 5705 - f - function evaluation routine 5706 5707 Notes: 5708 The Newton-like methods typically solve linear systems of the form 5709 $ f'(x) x = -f(x), 5710 where f'(x) denotes the Jacobian matrix and f(x) is the function. 5711 5712 Level: beginner 5713 5714 Developer Note: This bleeds the allocated memory SNESMatlabContext *sctx; 5715 5716 .keywords: SNES, nonlinear, set, function 5717 5718 .seealso: SNESGetFunction(), SNESComputeFunction(), SNESSetJacobian(), SNESSetFunction() 5719 */ 5720 PetscErrorCode SNESSetFunctionMatlab(SNES snes,Vec r,const char *f,mxArray *ctx) 5721 { 5722 PetscErrorCode ierr; 5723 SNESMatlabContext *sctx; 5724 5725 PetscFunctionBegin; 5726 /* currently sctx is memory bleed */ 5727 ierr = PetscNew(&sctx);CHKERRQ(ierr); 5728 ierr = PetscStrallocpy(f,&sctx->funcname);CHKERRQ(ierr); 5729 /* 5730 This should work, but it doesn't 5731 sctx->ctx = ctx; 5732 mexMakeArrayPersistent(sctx->ctx); 5733 */ 5734 sctx->ctx = mxDuplicateArray(ctx); 5735 ierr = SNESSetFunction(snes,r,SNESComputeFunction_Matlab,sctx);CHKERRQ(ierr); 5736 PetscFunctionReturn(0); 5737 } 5738 5739 /* 5740 SNESComputeJacobian_Matlab - Calls the function that has been set with SNESSetJacobianMatlab(). 5741 5742 Collective on SNES 5743 5744 Input Parameters: 5745 + snes - the SNES context 5746 . x - input vector 5747 . A, B - the matrices 5748 - ctx - user context 5749 5750 Level: developer 5751 5752 .keywords: SNES, nonlinear, compute, function 5753 5754 .seealso: SNESSetFunction(), SNESGetFunction() 5755 @*/ 5756 PetscErrorCode SNESComputeJacobian_Matlab(SNES snes,Vec x,Mat A,Mat B,void *ctx) 5757 { 5758 PetscErrorCode ierr; 5759 SNESMatlabContext *sctx = (SNESMatlabContext*)ctx; 5760 int nlhs = 2,nrhs = 6; 5761 mxArray *plhs[2],*prhs[6]; 5762 long long int lx = 0,lA = 0,ls = 0, lB = 0; 5763 5764 PetscFunctionBegin; 5765 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 5766 PetscValidHeaderSpecific(x,VEC_CLASSID,2); 5767 5768 /* call Matlab function in ctx with arguments x and y */ 5769 5770 ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr); 5771 ierr = PetscMemcpy(&lx,&x,sizeof(x));CHKERRQ(ierr); 5772 ierr = PetscMemcpy(&lA,A,sizeof(x));CHKERRQ(ierr); 5773 ierr = PetscMemcpy(&lB,B,sizeof(x));CHKERRQ(ierr); 5774 prhs[0] = mxCreateDoubleScalar((double)ls); 5775 prhs[1] = mxCreateDoubleScalar((double)lx); 5776 prhs[2] = mxCreateDoubleScalar((double)lA); 5777 prhs[3] = mxCreateDoubleScalar((double)lB); 5778 prhs[4] = mxCreateString(sctx->funcname); 5779 prhs[5] = sctx->ctx; 5780 ierr = mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESComputeJacobianInternal");CHKERRQ(ierr); 5781 ierr = mxGetScalar(plhs[0]);CHKERRQ(ierr); 5782 mxDestroyArray(prhs[0]); 5783 mxDestroyArray(prhs[1]); 5784 mxDestroyArray(prhs[2]); 5785 mxDestroyArray(prhs[3]); 5786 mxDestroyArray(prhs[4]); 5787 mxDestroyArray(plhs[0]); 5788 mxDestroyArray(plhs[1]); 5789 PetscFunctionReturn(0); 5790 } 5791 5792 /* 5793 SNESSetJacobianMatlab - Sets the Jacobian function evaluation routine and two empty Jacobian matrices 5794 vector for use by the SNES routines in solving systems of nonlinear 5795 equations from MATLAB. Here the function is a string containing the name of a MATLAB function 5796 5797 Logically Collective on SNES 5798 5799 Input Parameters: 5800 + snes - the SNES context 5801 . A,B - Jacobian matrices 5802 . J - function evaluation routine 5803 - ctx - user context 5804 5805 Level: developer 5806 5807 Developer Note: This bleeds the allocated memory SNESMatlabContext *sctx; 5808 5809 .keywords: SNES, nonlinear, set, function 5810 5811 .seealso: SNESGetFunction(), SNESComputeFunction(), SNESSetJacobian(), SNESSetFunction(), J 5812 */ 5813 PetscErrorCode SNESSetJacobianMatlab(SNES snes,Mat A,Mat B,const char *J,mxArray *ctx) 5814 { 5815 PetscErrorCode ierr; 5816 SNESMatlabContext *sctx; 5817 5818 PetscFunctionBegin; 5819 /* currently sctx is memory bleed */ 5820 ierr = PetscNew(&sctx);CHKERRQ(ierr); 5821 ierr = PetscStrallocpy(J,&sctx->funcname);CHKERRQ(ierr); 5822 /* 5823 This should work, but it doesn't 5824 sctx->ctx = ctx; 5825 mexMakeArrayPersistent(sctx->ctx); 5826 */ 5827 sctx->ctx = mxDuplicateArray(ctx); 5828 ierr = SNESSetJacobian(snes,A,B,SNESComputeJacobian_Matlab,sctx);CHKERRQ(ierr); 5829 PetscFunctionReturn(0); 5830 } 5831 5832 /* 5833 SNESMonitor_Matlab - Calls the function that has been set with SNESMonitorSetMatlab(). 5834 5835 Collective on SNES 5836 5837 .seealso: SNESSetFunction(), SNESGetFunction() 5838 @*/ 5839 PetscErrorCode SNESMonitor_Matlab(SNES snes,PetscInt it, PetscReal fnorm, void *ctx) 5840 { 5841 PetscErrorCode ierr; 5842 SNESMatlabContext *sctx = (SNESMatlabContext*)ctx; 5843 int nlhs = 1,nrhs = 6; 5844 mxArray *plhs[1],*prhs[6]; 5845 long long int lx = 0,ls = 0; 5846 Vec x = snes->vec_sol; 5847 5848 PetscFunctionBegin; 5849 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 5850 5851 ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr); 5852 ierr = PetscMemcpy(&lx,&x,sizeof(x));CHKERRQ(ierr); 5853 prhs[0] = mxCreateDoubleScalar((double)ls); 5854 prhs[1] = mxCreateDoubleScalar((double)it); 5855 prhs[2] = mxCreateDoubleScalar((double)fnorm); 5856 prhs[3] = mxCreateDoubleScalar((double)lx); 5857 prhs[4] = mxCreateString(sctx->funcname); 5858 prhs[5] = sctx->ctx; 5859 ierr = mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESMonitorInternal");CHKERRQ(ierr); 5860 ierr = mxGetScalar(plhs[0]);CHKERRQ(ierr); 5861 mxDestroyArray(prhs[0]); 5862 mxDestroyArray(prhs[1]); 5863 mxDestroyArray(prhs[2]); 5864 mxDestroyArray(prhs[3]); 5865 mxDestroyArray(prhs[4]); 5866 mxDestroyArray(plhs[0]); 5867 PetscFunctionReturn(0); 5868 } 5869 5870 /* 5871 SNESMonitorSetMatlab - Sets the monitor function from MATLAB 5872 5873 Level: developer 5874 5875 Developer Note: This bleeds the allocated memory SNESMatlabContext *sctx; 5876 5877 .keywords: SNES, nonlinear, set, function 5878 5879 .seealso: SNESGetFunction(), SNESComputeFunction(), SNESSetJacobian(), SNESSetFunction() 5880 */ 5881 PetscErrorCode SNESMonitorSetMatlab(SNES snes,const char *f,mxArray *ctx) 5882 { 5883 PetscErrorCode ierr; 5884 SNESMatlabContext *sctx; 5885 5886 PetscFunctionBegin; 5887 /* currently sctx is memory bleed */ 5888 ierr = PetscNew(&sctx);CHKERRQ(ierr); 5889 ierr = PetscStrallocpy(f,&sctx->funcname);CHKERRQ(ierr); 5890 /* 5891 This should work, but it doesn't 5892 sctx->ctx = ctx; 5893 mexMakeArrayPersistent(sctx->ctx); 5894 */ 5895 sctx->ctx = mxDuplicateArray(ctx); 5896 ierr = SNESMonitorSet(snes,SNESMonitor_Matlab,sctx,NULL);CHKERRQ(ierr); 5897 PetscFunctionReturn(0); 5898 } 5899 5900 #endif 5901