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