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 ierr = SNESLineSearchSetFromOptions(snes->linesearch);CHKERRQ(ierr); 1085 } 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 ierr = SNESLineSearchSetFunction(snes->linesearch,SNESComputeFunction);CHKERRQ(ierr); 3092 } 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 if (snes->linesearch && snes->npc->linesearch) { 3127 ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr); 3128 ierr = SNESGetLineSearch(snes->npc,&pclinesearch);CHKERRQ(ierr); 3129 ierr = SNESLineSearchGetPreCheck(linesearch,&precheck,&lsprectx);CHKERRQ(ierr); 3130 ierr = SNESLineSearchGetPostCheck(linesearch,&postcheck,&lspostctx);CHKERRQ(ierr); 3131 ierr = SNESLineSearchSetPreCheck(pclinesearch,precheck,lsprectx);CHKERRQ(ierr); 3132 ierr = SNESLineSearchSetPostCheck(pclinesearch,postcheck,lspostctx);CHKERRQ(ierr); 3133 ierr = PetscObjectCopyFortranFunctionPointers((PetscObject)linesearch, (PetscObject)pclinesearch);CHKERRQ(ierr); 3134 } 3135 } 3136 if (snes->mf) { 3137 ierr = SNESSetUpMatrixFree_Private(snes, snes->mf_operator, snes->mf_version);CHKERRQ(ierr); 3138 } 3139 if (snes->ops->usercompute && !snes->user) { 3140 ierr = (*snes->ops->usercompute)(snes,(void**)&snes->user);CHKERRQ(ierr); 3141 } 3142 3143 snes->jac_iter = 0; 3144 snes->pre_iter = 0; 3145 3146 if (snes->ops->setup) { 3147 ierr = (*snes->ops->setup)(snes);CHKERRQ(ierr); 3148 } 3149 3150 if (snes->npc && (snes->npcside== PC_LEFT)) { 3151 if (snes->functype == SNES_FUNCTION_PRECONDITIONED) { 3152 if (snes->linesearch){ 3153 ierr = SNESGetLineSearch(snes,&linesearch);CHKERRQ(ierr); 3154 ierr = SNESLineSearchSetFunction(linesearch,SNESComputeFunctionDefaultNPC);CHKERRQ(ierr); 3155 } 3156 } 3157 } 3158 3159 snes->setupcalled = PETSC_TRUE; 3160 PetscFunctionReturn(0); 3161 } 3162 3163 /*@ 3164 SNESReset - Resets a SNES context to the snessetupcalled = 0 state and removes any allocated Vecs and Mats 3165 3166 Collective on SNES 3167 3168 Input Parameter: 3169 . snes - iterative context obtained from SNESCreate() 3170 3171 Level: intermediate 3172 3173 Notes: 3174 Also calls the application context destroy routine set with SNESSetComputeApplicationContext() 3175 3176 .keywords: SNES, destroy 3177 3178 .seealso: SNESCreate(), SNESSetUp(), SNESSolve() 3179 @*/ 3180 PetscErrorCode SNESReset(SNES snes) 3181 { 3182 PetscErrorCode ierr; 3183 3184 PetscFunctionBegin; 3185 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3186 if (snes->ops->userdestroy && snes->user) { 3187 ierr = (*snes->ops->userdestroy)((void**)&snes->user);CHKERRQ(ierr); 3188 snes->user = NULL; 3189 } 3190 if (snes->npc) { 3191 ierr = SNESReset(snes->npc);CHKERRQ(ierr); 3192 } 3193 3194 if (snes->ops->reset) { 3195 ierr = (*snes->ops->reset)(snes);CHKERRQ(ierr); 3196 } 3197 if (snes->ksp) { 3198 ierr = KSPReset(snes->ksp);CHKERRQ(ierr); 3199 } 3200 3201 if (snes->linesearch) { 3202 ierr = SNESLineSearchReset(snes->linesearch);CHKERRQ(ierr); 3203 } 3204 3205 ierr = VecDestroy(&snes->vec_rhs);CHKERRQ(ierr); 3206 ierr = VecDestroy(&snes->vec_sol);CHKERRQ(ierr); 3207 ierr = VecDestroy(&snes->vec_sol_update);CHKERRQ(ierr); 3208 ierr = VecDestroy(&snes->vec_func);CHKERRQ(ierr); 3209 ierr = MatDestroy(&snes->jacobian);CHKERRQ(ierr); 3210 ierr = MatDestroy(&snes->jacobian_pre);CHKERRQ(ierr); 3211 ierr = VecDestroyVecs(snes->nwork,&snes->work);CHKERRQ(ierr); 3212 ierr = VecDestroyVecs(snes->nvwork,&snes->vwork);CHKERRQ(ierr); 3213 3214 snes->alwayscomputesfinalresidual = PETSC_FALSE; 3215 3216 snes->nwork = snes->nvwork = 0; 3217 snes->setupcalled = PETSC_FALSE; 3218 PetscFunctionReturn(0); 3219 } 3220 3221 /*@ 3222 SNESDestroy - Destroys the nonlinear solver context that was created 3223 with SNESCreate(). 3224 3225 Collective on SNES 3226 3227 Input Parameter: 3228 . snes - the SNES context 3229 3230 Level: beginner 3231 3232 .keywords: SNES, nonlinear, destroy 3233 3234 .seealso: SNESCreate(), SNESSolve() 3235 @*/ 3236 PetscErrorCode SNESDestroy(SNES *snes) 3237 { 3238 PetscErrorCode ierr; 3239 3240 PetscFunctionBegin; 3241 if (!*snes) PetscFunctionReturn(0); 3242 PetscValidHeaderSpecific((*snes),SNES_CLASSID,1); 3243 if (--((PetscObject)(*snes))->refct > 0) {*snes = 0; PetscFunctionReturn(0);} 3244 3245 ierr = SNESReset((*snes));CHKERRQ(ierr); 3246 ierr = SNESDestroy(&(*snes)->npc);CHKERRQ(ierr); 3247 3248 /* if memory was published with SAWs then destroy it */ 3249 ierr = PetscObjectSAWsViewOff((PetscObject)*snes);CHKERRQ(ierr); 3250 if ((*snes)->ops->destroy) {ierr = (*((*snes))->ops->destroy)((*snes));CHKERRQ(ierr);} 3251 3252 if ((*snes)->dm) {ierr = DMCoarsenHookRemove((*snes)->dm,DMCoarsenHook_SNESVecSol,DMRestrictHook_SNESVecSol,*snes);CHKERRQ(ierr);} 3253 ierr = DMDestroy(&(*snes)->dm);CHKERRQ(ierr); 3254 ierr = KSPDestroy(&(*snes)->ksp);CHKERRQ(ierr); 3255 ierr = SNESLineSearchDestroy(&(*snes)->linesearch);CHKERRQ(ierr); 3256 3257 ierr = PetscFree((*snes)->kspconvctx);CHKERRQ(ierr); 3258 if ((*snes)->ops->convergeddestroy) { 3259 ierr = (*(*snes)->ops->convergeddestroy)((*snes)->cnvP);CHKERRQ(ierr); 3260 } 3261 if ((*snes)->conv_malloc) { 3262 ierr = PetscFree((*snes)->conv_hist);CHKERRQ(ierr); 3263 ierr = PetscFree((*snes)->conv_hist_its);CHKERRQ(ierr); 3264 } 3265 ierr = SNESMonitorCancel((*snes));CHKERRQ(ierr); 3266 ierr = PetscHeaderDestroy(snes);CHKERRQ(ierr); 3267 PetscFunctionReturn(0); 3268 } 3269 3270 /* ----------- Routines to set solver parameters ---------- */ 3271 3272 /*@ 3273 SNESSetLagPreconditioner - Determines when the preconditioner is rebuilt in the nonlinear solve. 3274 3275 Logically Collective on SNES 3276 3277 Input Parameters: 3278 + snes - the SNES context 3279 - lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 3280 the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3281 3282 Options Database Keys: 3283 . -snes_lag_preconditioner <lag> 3284 3285 Notes: 3286 The default is 1 3287 The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3288 If -1 is used before the very first nonlinear solve the preconditioner is still built because there is no previous preconditioner to use 3289 3290 Level: intermediate 3291 3292 .keywords: SNES, nonlinear, set, convergence, tolerances 3293 3294 .seealso: SNESSetTrustRegionTolerance(), SNESGetLagPreconditioner(), SNESSetLagJacobian(), SNESGetLagJacobian() 3295 3296 @*/ 3297 PetscErrorCode SNESSetLagPreconditioner(SNES snes,PetscInt lag) 3298 { 3299 PetscFunctionBegin; 3300 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3301 if (lag < -2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Lag must be -2, -1, 1 or greater"); 3302 if (!lag) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Lag cannot be 0"); 3303 PetscValidLogicalCollectiveInt(snes,lag,2); 3304 snes->lagpreconditioner = lag; 3305 PetscFunctionReturn(0); 3306 } 3307 3308 /*@ 3309 SNESSetGridSequence - sets the number of steps of grid sequencing that SNES does 3310 3311 Logically Collective on SNES 3312 3313 Input Parameters: 3314 + snes - the SNES context 3315 - steps - the number of refinements to do, defaults to 0 3316 3317 Options Database Keys: 3318 . -snes_grid_sequence <steps> 3319 3320 Level: intermediate 3321 3322 Notes: 3323 Use SNESGetSolution() to extract the fine grid solution after grid sequencing. 3324 3325 .keywords: SNES, nonlinear, set, convergence, tolerances 3326 3327 .seealso: SNESSetTrustRegionTolerance(), SNESGetLagPreconditioner(), SNESSetLagJacobian(), SNESGetLagJacobian(), SNESGetGridSequence() 3328 3329 @*/ 3330 PetscErrorCode SNESSetGridSequence(SNES snes,PetscInt steps) 3331 { 3332 PetscFunctionBegin; 3333 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3334 PetscValidLogicalCollectiveInt(snes,steps,2); 3335 snes->gridsequence = steps; 3336 PetscFunctionReturn(0); 3337 } 3338 3339 /*@ 3340 SNESGetGridSequence - gets the number of steps of grid sequencing that SNES does 3341 3342 Logically Collective on SNES 3343 3344 Input Parameter: 3345 . snes - the SNES context 3346 3347 Output Parameter: 3348 . steps - the number of refinements to do, defaults to 0 3349 3350 Options Database Keys: 3351 . -snes_grid_sequence <steps> 3352 3353 Level: intermediate 3354 3355 Notes: 3356 Use SNESGetSolution() to extract the fine grid solution after grid sequencing. 3357 3358 .keywords: SNES, nonlinear, set, convergence, tolerances 3359 3360 .seealso: SNESSetTrustRegionTolerance(), SNESGetLagPreconditioner(), SNESSetLagJacobian(), SNESGetLagJacobian(), SNESSetGridSequence() 3361 3362 @*/ 3363 PetscErrorCode SNESGetGridSequence(SNES snes,PetscInt *steps) 3364 { 3365 PetscFunctionBegin; 3366 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3367 *steps = snes->gridsequence; 3368 PetscFunctionReturn(0); 3369 } 3370 3371 /*@ 3372 SNESGetLagPreconditioner - Indicates how often the preconditioner is rebuilt 3373 3374 Not Collective 3375 3376 Input Parameter: 3377 . snes - the SNES context 3378 3379 Output Parameter: 3380 . lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 3381 the Jacobian is built etc. -2 indicates rebuild preconditioner at next chance but then never rebuild after that 3382 3383 Options Database Keys: 3384 . -snes_lag_preconditioner <lag> 3385 3386 Notes: 3387 The default is 1 3388 The preconditioner is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3389 3390 Level: intermediate 3391 3392 .keywords: SNES, nonlinear, set, convergence, tolerances 3393 3394 .seealso: SNESSetTrustRegionTolerance(), SNESSetLagPreconditioner() 3395 3396 @*/ 3397 PetscErrorCode SNESGetLagPreconditioner(SNES snes,PetscInt *lag) 3398 { 3399 PetscFunctionBegin; 3400 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3401 *lag = snes->lagpreconditioner; 3402 PetscFunctionReturn(0); 3403 } 3404 3405 /*@ 3406 SNESSetLagJacobian - Determines when the Jacobian is rebuilt in the nonlinear solve. See SNESSetLagPreconditioner() for determining how 3407 often the preconditioner is rebuilt. 3408 3409 Logically Collective on SNES 3410 3411 Input Parameters: 3412 + snes - the SNES context 3413 - lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 3414 the Jacobian is built etc. -2 means rebuild at next chance but then never again 3415 3416 Options Database Keys: 3417 . -snes_lag_jacobian <lag> 3418 3419 Notes: 3420 The default is 1 3421 The Jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3422 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 3423 at the next Newton step but never again (unless it is reset to another value) 3424 3425 Level: intermediate 3426 3427 .keywords: SNES, nonlinear, set, convergence, tolerances 3428 3429 .seealso: SNESSetTrustRegionTolerance(), SNESGetLagPreconditioner(), SNESSetLagPreconditioner(), SNESGetLagJacobian() 3430 3431 @*/ 3432 PetscErrorCode SNESSetLagJacobian(SNES snes,PetscInt lag) 3433 { 3434 PetscFunctionBegin; 3435 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3436 if (lag < -2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Lag must be -2, -1, 1 or greater"); 3437 if (!lag) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Lag cannot be 0"); 3438 PetscValidLogicalCollectiveInt(snes,lag,2); 3439 snes->lagjacobian = lag; 3440 PetscFunctionReturn(0); 3441 } 3442 3443 /*@ 3444 SNESGetLagJacobian - Indicates how often the Jacobian is rebuilt. See SNESGetLagPreconditioner() to determine when the preconditioner is rebuilt 3445 3446 Not Collective 3447 3448 Input Parameter: 3449 . snes - the SNES context 3450 3451 Output Parameter: 3452 . lag - -1 indicates NEVER rebuild, 1 means rebuild every time the Jacobian is computed within a single nonlinear solve, 2 means every second time 3453 the Jacobian is built etc. 3454 3455 Options Database Keys: 3456 . -snes_lag_jacobian <lag> 3457 3458 Notes: 3459 The default is 1 3460 The jacobian is ALWAYS built in the first iteration of a nonlinear solve unless lag is -1 3461 3462 Level: intermediate 3463 3464 .keywords: SNES, nonlinear, set, convergence, tolerances 3465 3466 .seealso: SNESSetTrustRegionTolerance(), SNESSetLagJacobian(), SNESSetLagPreconditioner(), SNESGetLagPreconditioner() 3467 3468 @*/ 3469 PetscErrorCode SNESGetLagJacobian(SNES snes,PetscInt *lag) 3470 { 3471 PetscFunctionBegin; 3472 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3473 *lag = snes->lagjacobian; 3474 PetscFunctionReturn(0); 3475 } 3476 3477 /*@ 3478 SNESSetLagJacobianPersists - Set whether or not the Jacobian lagging persists through multiple solves 3479 3480 Logically collective on SNES 3481 3482 Input Parameter: 3483 + snes - the SNES context 3484 - flg - jacobian lagging persists if true 3485 3486 Options Database Keys: 3487 . -snes_lag_jacobian_persists <flg> 3488 3489 Notes: 3490 This is useful both for nonlinear preconditioning, where it's appropriate to have the Jacobian be stale by 3491 several solves, and for implicit time-stepping, where Jacobian lagging in the inner nonlinear solve over several 3492 timesteps may present huge efficiency gains. 3493 3494 Level: developer 3495 3496 .keywords: SNES, nonlinear, lag 3497 3498 .seealso: SNESSetLagPreconditionerPersists(), SNESSetLagJacobian(), SNESGetLagJacobian(), SNESGetNPC() 3499 3500 @*/ 3501 PetscErrorCode SNESSetLagJacobianPersists(SNES snes,PetscBool flg) 3502 { 3503 PetscFunctionBegin; 3504 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3505 PetscValidLogicalCollectiveBool(snes,flg,2); 3506 snes->lagjac_persist = flg; 3507 PetscFunctionReturn(0); 3508 } 3509 3510 /*@ 3511 SNESSetLagPreconditionerPersists - Set whether or not the preconditioner lagging persists through multiple solves 3512 3513 Logically Collective on SNES 3514 3515 Input Parameter: 3516 + snes - the SNES context 3517 - flg - preconditioner lagging persists if true 3518 3519 Options Database Keys: 3520 . -snes_lag_jacobian_persists <flg> 3521 3522 Notes: 3523 This is useful both for nonlinear preconditioning, where it's appropriate to have the preconditioner be stale 3524 by several solves, and for implicit time-stepping, where preconditioner lagging in the inner nonlinear solve over 3525 several timesteps may present huge efficiency gains. 3526 3527 Level: developer 3528 3529 .keywords: SNES, nonlinear, lag 3530 3531 .seealso: SNESSetLagJacobianPersists(), SNESSetLagJacobian(), SNESGetLagJacobian(), SNESGetNPC() 3532 3533 @*/ 3534 PetscErrorCode SNESSetLagPreconditionerPersists(SNES snes,PetscBool flg) 3535 { 3536 PetscFunctionBegin; 3537 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3538 PetscValidLogicalCollectiveBool(snes,flg,2); 3539 snes->lagpre_persist = flg; 3540 PetscFunctionReturn(0); 3541 } 3542 3543 /*@ 3544 SNESSetForceIteration - force SNESSolve() to take at least one iteration regardless of the initial residual norm 3545 3546 Logically Collective on SNES 3547 3548 Input Parameters: 3549 + snes - the SNES context 3550 - force - PETSC_TRUE require at least one iteration 3551 3552 Options Database Keys: 3553 . -snes_force_iteration <force> - Sets forcing an iteration 3554 3555 Notes: 3556 This is used sometimes with TS to prevent TS from detecting a false steady state solution 3557 3558 Level: intermediate 3559 3560 .keywords: SNES, nonlinear, set, convergence, tolerances 3561 3562 .seealso: SNESSetTrustRegionTolerance(), SNESSetDivergenceTolerance() 3563 @*/ 3564 PetscErrorCode SNESSetForceIteration(SNES snes,PetscBool force) 3565 { 3566 PetscFunctionBegin; 3567 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3568 snes->forceiteration = force; 3569 PetscFunctionReturn(0); 3570 } 3571 3572 /*@ 3573 SNESGetForceIteration - Whether or not to force SNESSolve() take at least one iteration regardless of the initial residual norm 3574 3575 Logically Collective on SNES 3576 3577 Input Parameters: 3578 . snes - the SNES context 3579 3580 Output Parameter: 3581 . force - PETSC_TRUE requires at least one iteration. 3582 3583 .keywords: SNES, nonlinear, set, convergence, tolerances 3584 3585 Level: intermediate 3586 3587 .seealso: SNESSetForceIteration(), SNESSetTrustRegionTolerance(), SNESSetDivergenceTolerance() 3588 @*/ 3589 PetscErrorCode SNESGetForceIteration(SNES snes,PetscBool *force) 3590 { 3591 PetscFunctionBegin; 3592 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3593 *force = snes->forceiteration; 3594 PetscFunctionReturn(0); 3595 } 3596 3597 /*@ 3598 SNESSetTolerances - Sets various parameters used in convergence tests. 3599 3600 Logically Collective on SNES 3601 3602 Input Parameters: 3603 + snes - the SNES context 3604 . abstol - absolute convergence tolerance 3605 . rtol - relative convergence tolerance 3606 . stol - convergence tolerance in terms of the norm of the change in the solution between steps, || delta x || < stol*|| x || 3607 . maxit - maximum number of iterations 3608 - maxf - maximum number of function evaluations (-1 indicates no limit) 3609 3610 Options Database Keys: 3611 + -snes_atol <abstol> - Sets abstol 3612 . -snes_rtol <rtol> - Sets rtol 3613 . -snes_stol <stol> - Sets stol 3614 . -snes_max_it <maxit> - Sets maxit 3615 - -snes_max_funcs <maxf> - Sets maxf 3616 3617 Notes: 3618 The default maximum number of iterations is 50. 3619 The default maximum number of function evaluations is 1000. 3620 3621 Level: intermediate 3622 3623 .keywords: SNES, nonlinear, set, convergence, tolerances 3624 3625 .seealso: SNESSetTrustRegionTolerance(), SNESSetDivergenceTolerance(), SNESSetForceIteration() 3626 @*/ 3627 PetscErrorCode SNESSetTolerances(SNES snes,PetscReal abstol,PetscReal rtol,PetscReal stol,PetscInt maxit,PetscInt maxf) 3628 { 3629 PetscFunctionBegin; 3630 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3631 PetscValidLogicalCollectiveReal(snes,abstol,2); 3632 PetscValidLogicalCollectiveReal(snes,rtol,3); 3633 PetscValidLogicalCollectiveReal(snes,stol,4); 3634 PetscValidLogicalCollectiveInt(snes,maxit,5); 3635 PetscValidLogicalCollectiveInt(snes,maxf,6); 3636 3637 if (abstol != PETSC_DEFAULT) { 3638 if (abstol < 0.0) SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_OUTOFRANGE,"Absolute tolerance %g must be non-negative",(double)abstol); 3639 snes->abstol = abstol; 3640 } 3641 if (rtol != PETSC_DEFAULT) { 3642 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); 3643 snes->rtol = rtol; 3644 } 3645 if (stol != PETSC_DEFAULT) { 3646 if (stol < 0.0) SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_OUTOFRANGE,"Step tolerance %g must be non-negative",(double)stol); 3647 snes->stol = stol; 3648 } 3649 if (maxit != PETSC_DEFAULT) { 3650 if (maxit < 0) SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_OUTOFRANGE,"Maximum number of iterations %D must be non-negative",maxit); 3651 snes->max_its = maxit; 3652 } 3653 if (maxf != PETSC_DEFAULT) { 3654 if (maxf < -1) SETERRQ1(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_OUTOFRANGE,"Maximum number of function evaluations %D must be -1 or nonnegative",maxf); 3655 snes->max_funcs = maxf; 3656 } 3657 snes->tolerancesset = PETSC_TRUE; 3658 PetscFunctionReturn(0); 3659 } 3660 3661 /*@ 3662 SNESSetDivergenceTolerance - Sets the divergence tolerance used for the SNES divergence test. 3663 3664 Logically Collective on SNES 3665 3666 Input Parameters: 3667 + snes - the SNES context 3668 - divtol - the divergence tolerance. Use -1 to deactivate the test. 3669 3670 Options Database Keys: 3671 + -snes_divergence_tolerance <divtol> - Sets divtol 3672 3673 Notes: 3674 The default divergence tolerance is 1e4. 3675 3676 Level: intermediate 3677 3678 .keywords: SNES, nonlinear, set, divergence, tolerance 3679 3680 .seealso: SNESSetTolerances(), SNESGetDivergenceTolerance 3681 @*/ 3682 PetscErrorCode SNESSetDivergenceTolerance(SNES snes,PetscReal divtol) 3683 { 3684 PetscFunctionBegin; 3685 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3686 PetscValidLogicalCollectiveReal(snes,divtol,2); 3687 3688 if (divtol != PETSC_DEFAULT) { 3689 snes->divtol = divtol; 3690 } 3691 else { 3692 snes->divtol = 1.0e4; 3693 } 3694 PetscFunctionReturn(0); 3695 } 3696 3697 /*@ 3698 SNESGetTolerances - Gets various parameters used in convergence tests. 3699 3700 Not Collective 3701 3702 Input Parameters: 3703 + snes - the SNES context 3704 . atol - absolute convergence tolerance 3705 . rtol - relative convergence tolerance 3706 . stol - convergence tolerance in terms of the norm 3707 of the change in the solution between steps 3708 . maxit - maximum number of iterations 3709 - maxf - maximum number of function evaluations 3710 3711 Notes: 3712 The user can specify NULL for any parameter that is not needed. 3713 3714 Level: intermediate 3715 3716 .keywords: SNES, nonlinear, get, convergence, tolerances 3717 3718 .seealso: SNESSetTolerances() 3719 @*/ 3720 PetscErrorCode SNESGetTolerances(SNES snes,PetscReal *atol,PetscReal *rtol,PetscReal *stol,PetscInt *maxit,PetscInt *maxf) 3721 { 3722 PetscFunctionBegin; 3723 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3724 if (atol) *atol = snes->abstol; 3725 if (rtol) *rtol = snes->rtol; 3726 if (stol) *stol = snes->stol; 3727 if (maxit) *maxit = snes->max_its; 3728 if (maxf) *maxf = snes->max_funcs; 3729 PetscFunctionReturn(0); 3730 } 3731 3732 /*@ 3733 SNESGetDivergenceTolerance - Gets divergence tolerance used in divergence test. 3734 3735 Not Collective 3736 3737 Input Parameters: 3738 + snes - the SNES context 3739 - divtol - divergence tolerance 3740 3741 Level: intermediate 3742 3743 .keywords: SNES, nonlinear, get, divergence, tolerance 3744 3745 .seealso: SNESSetDivergenceTolerance() 3746 @*/ 3747 PetscErrorCode SNESGetDivergenceTolerance(SNES snes,PetscReal *divtol) 3748 { 3749 PetscFunctionBegin; 3750 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3751 if (divtol) *divtol = snes->divtol; 3752 PetscFunctionReturn(0); 3753 } 3754 3755 /*@ 3756 SNESSetTrustRegionTolerance - Sets the trust region parameter tolerance. 3757 3758 Logically Collective on SNES 3759 3760 Input Parameters: 3761 + snes - the SNES context 3762 - tol - tolerance 3763 3764 Options Database Key: 3765 . -snes_trtol <tol> - Sets tol 3766 3767 Level: intermediate 3768 3769 .keywords: SNES, nonlinear, set, trust region, tolerance 3770 3771 .seealso: SNESSetTolerances() 3772 @*/ 3773 PetscErrorCode SNESSetTrustRegionTolerance(SNES snes,PetscReal tol) 3774 { 3775 PetscFunctionBegin; 3776 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3777 PetscValidLogicalCollectiveReal(snes,tol,2); 3778 snes->deltatol = tol; 3779 PetscFunctionReturn(0); 3780 } 3781 3782 /* 3783 Duplicate the lg monitors for SNES from KSP; for some reason with 3784 dynamic libraries things don't work under Sun4 if we just use 3785 macros instead of functions 3786 */ 3787 PetscErrorCode SNESMonitorLGResidualNorm(SNES snes,PetscInt it,PetscReal norm,void *ctx) 3788 { 3789 PetscErrorCode ierr; 3790 3791 PetscFunctionBegin; 3792 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3793 ierr = KSPMonitorLGResidualNorm((KSP)snes,it,norm,ctx);CHKERRQ(ierr); 3794 PetscFunctionReturn(0); 3795 } 3796 3797 PetscErrorCode SNESMonitorLGCreate(MPI_Comm comm,const char host[],const char label[],int x,int y,int m,int n,PetscDrawLG *lgctx) 3798 { 3799 PetscErrorCode ierr; 3800 3801 PetscFunctionBegin; 3802 ierr = KSPMonitorLGResidualNormCreate(comm,host,label,x,y,m,n,lgctx);CHKERRQ(ierr); 3803 PetscFunctionReturn(0); 3804 } 3805 3806 PETSC_INTERN PetscErrorCode SNESMonitorRange_Private(SNES,PetscInt,PetscReal*); 3807 3808 PetscErrorCode SNESMonitorLGRange(SNES snes,PetscInt n,PetscReal rnorm,void *monctx) 3809 { 3810 PetscDrawLG lg; 3811 PetscErrorCode ierr; 3812 PetscReal x,y,per; 3813 PetscViewer v = (PetscViewer)monctx; 3814 static PetscReal prev; /* should be in the context */ 3815 PetscDraw draw; 3816 3817 PetscFunctionBegin; 3818 PetscValidHeaderSpecific(v,PETSC_VIEWER_CLASSID,4); 3819 ierr = PetscViewerDrawGetDrawLG(v,0,&lg);CHKERRQ(ierr); 3820 if (!n) {ierr = PetscDrawLGReset(lg);CHKERRQ(ierr);} 3821 ierr = PetscDrawLGGetDraw(lg,&draw);CHKERRQ(ierr); 3822 ierr = PetscDrawSetTitle(draw,"Residual norm");CHKERRQ(ierr); 3823 x = (PetscReal)n; 3824 if (rnorm > 0.0) y = PetscLog10Real(rnorm); 3825 else y = -15.0; 3826 ierr = PetscDrawLGAddPoint(lg,&x,&y);CHKERRQ(ierr); 3827 if (n < 20 || !(n % 5) || snes->reason) { 3828 ierr = PetscDrawLGDraw(lg);CHKERRQ(ierr); 3829 ierr = PetscDrawLGSave(lg);CHKERRQ(ierr); 3830 } 3831 3832 ierr = PetscViewerDrawGetDrawLG(v,1,&lg);CHKERRQ(ierr); 3833 if (!n) {ierr = PetscDrawLGReset(lg);CHKERRQ(ierr);} 3834 ierr = PetscDrawLGGetDraw(lg,&draw);CHKERRQ(ierr); 3835 ierr = PetscDrawSetTitle(draw,"% elemts > .2*max elemt");CHKERRQ(ierr); 3836 ierr = SNESMonitorRange_Private(snes,n,&per);CHKERRQ(ierr); 3837 x = (PetscReal)n; 3838 y = 100.0*per; 3839 ierr = PetscDrawLGAddPoint(lg,&x,&y);CHKERRQ(ierr); 3840 if (n < 20 || !(n % 5) || snes->reason) { 3841 ierr = PetscDrawLGDraw(lg);CHKERRQ(ierr); 3842 ierr = PetscDrawLGSave(lg);CHKERRQ(ierr); 3843 } 3844 3845 ierr = PetscViewerDrawGetDrawLG(v,2,&lg);CHKERRQ(ierr); 3846 if (!n) {prev = rnorm;ierr = PetscDrawLGReset(lg);CHKERRQ(ierr);} 3847 ierr = PetscDrawLGGetDraw(lg,&draw);CHKERRQ(ierr); 3848 ierr = PetscDrawSetTitle(draw,"(norm -oldnorm)/oldnorm");CHKERRQ(ierr); 3849 x = (PetscReal)n; 3850 y = (prev - rnorm)/prev; 3851 ierr = PetscDrawLGAddPoint(lg,&x,&y);CHKERRQ(ierr); 3852 if (n < 20 || !(n % 5) || snes->reason) { 3853 ierr = PetscDrawLGDraw(lg);CHKERRQ(ierr); 3854 ierr = PetscDrawLGSave(lg);CHKERRQ(ierr); 3855 } 3856 3857 ierr = PetscViewerDrawGetDrawLG(v,3,&lg);CHKERRQ(ierr); 3858 if (!n) {ierr = PetscDrawLGReset(lg);CHKERRQ(ierr);} 3859 ierr = PetscDrawLGGetDraw(lg,&draw);CHKERRQ(ierr); 3860 ierr = PetscDrawSetTitle(draw,"(norm -oldnorm)/oldnorm*(% > .2 max)");CHKERRQ(ierr); 3861 x = (PetscReal)n; 3862 y = (prev - rnorm)/(prev*per); 3863 if (n > 2) { /*skip initial crazy value */ 3864 ierr = PetscDrawLGAddPoint(lg,&x,&y);CHKERRQ(ierr); 3865 } 3866 if (n < 20 || !(n % 5) || snes->reason) { 3867 ierr = PetscDrawLGDraw(lg);CHKERRQ(ierr); 3868 ierr = PetscDrawLGSave(lg);CHKERRQ(ierr); 3869 } 3870 prev = rnorm; 3871 PetscFunctionReturn(0); 3872 } 3873 3874 /*@ 3875 SNESMonitor - runs the user provided monitor routines, if they exist 3876 3877 Collective on SNES 3878 3879 Input Parameters: 3880 + snes - nonlinear solver context obtained from SNESCreate() 3881 . iter - iteration number 3882 - rnorm - relative norm of the residual 3883 3884 Notes: 3885 This routine is called by the SNES implementations. 3886 It does not typically need to be called by the user. 3887 3888 Level: developer 3889 3890 .seealso: SNESMonitorSet() 3891 @*/ 3892 PetscErrorCode SNESMonitor(SNES snes,PetscInt iter,PetscReal rnorm) 3893 { 3894 PetscErrorCode ierr; 3895 PetscInt i,n = snes->numbermonitors; 3896 3897 PetscFunctionBegin; 3898 ierr = VecLockReadPush(snes->vec_sol);CHKERRQ(ierr); 3899 for (i=0; i<n; i++) { 3900 ierr = (*snes->monitor[i])(snes,iter,rnorm,snes->monitorcontext[i]);CHKERRQ(ierr); 3901 } 3902 ierr = VecLockReadPop(snes->vec_sol);CHKERRQ(ierr); 3903 PetscFunctionReturn(0); 3904 } 3905 3906 /* ------------ Routines to set performance monitoring options ----------- */ 3907 3908 /*MC 3909 SNESMonitorFunction - functional form passed to SNESMonitorSet() to monitor convergence of nonlinear solver 3910 3911 Synopsis: 3912 #include <petscsnes.h> 3913 $ PetscErrorCode SNESMonitorFunction(SNES snes,PetscInt its, PetscReal norm,void *mctx) 3914 3915 + snes - the SNES context 3916 . its - iteration number 3917 . norm - 2-norm function value (may be estimated) 3918 - mctx - [optional] monitoring context 3919 3920 Level: advanced 3921 3922 .seealso: SNESMonitorSet(), SNESMonitorGet() 3923 M*/ 3924 3925 /*@C 3926 SNESMonitorSet - Sets an ADDITIONAL function that is to be used at every 3927 iteration of the nonlinear solver to display the iteration's 3928 progress. 3929 3930 Logically Collective on SNES 3931 3932 Input Parameters: 3933 + snes - the SNES context 3934 . f - the monitor function, see SNESMonitorFunction for the calling sequence 3935 . mctx - [optional] user-defined context for private data for the 3936 monitor routine (use NULL if no context is desired) 3937 - monitordestroy - [optional] routine that frees monitor context 3938 (may be NULL) 3939 3940 Options Database Keys: 3941 + -snes_monitor - sets SNESMonitorDefault() 3942 . -snes_monitor_lg_residualnorm - sets line graph monitor, 3943 uses SNESMonitorLGCreate() 3944 - -snes_monitor_cancel - cancels all monitors that have 3945 been hardwired into a code by 3946 calls to SNESMonitorSet(), but 3947 does not cancel those set via 3948 the options database. 3949 3950 Notes: 3951 Several different monitoring routines may be set by calling 3952 SNESMonitorSet() multiple times; all will be called in the 3953 order in which they were set. 3954 3955 Fortran Notes: 3956 Only a single monitor function can be set for each SNES object 3957 3958 Level: intermediate 3959 3960 .keywords: SNES, nonlinear, set, monitor 3961 3962 .seealso: SNESMonitorDefault(), SNESMonitorCancel(), SNESMonitorFunction 3963 @*/ 3964 PetscErrorCode SNESMonitorSet(SNES snes,PetscErrorCode (*f)(SNES,PetscInt,PetscReal,void*),void *mctx,PetscErrorCode (*monitordestroy)(void**)) 3965 { 3966 PetscInt i; 3967 PetscErrorCode ierr; 3968 PetscBool identical; 3969 3970 PetscFunctionBegin; 3971 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 3972 for (i=0; i<snes->numbermonitors;i++) { 3973 ierr = PetscMonitorCompare((PetscErrorCode (*)(void))f,mctx,monitordestroy,(PetscErrorCode (*)(void))snes->monitor[i],snes->monitorcontext[i],snes->monitordestroy[i],&identical);CHKERRQ(ierr); 3974 if (identical) PetscFunctionReturn(0); 3975 } 3976 if (snes->numbermonitors >= MAXSNESMONITORS) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Too many monitors set"); 3977 snes->monitor[snes->numbermonitors] = f; 3978 snes->monitordestroy[snes->numbermonitors] = monitordestroy; 3979 snes->monitorcontext[snes->numbermonitors++] = (void*)mctx; 3980 PetscFunctionReturn(0); 3981 } 3982 3983 /*@ 3984 SNESMonitorCancel - Clears all the monitor functions for a SNES object. 3985 3986 Logically Collective on SNES 3987 3988 Input Parameters: 3989 . snes - the SNES context 3990 3991 Options Database Key: 3992 . -snes_monitor_cancel - cancels all monitors that have been hardwired 3993 into a code by calls to SNESMonitorSet(), but does not cancel those 3994 set via the options database 3995 3996 Notes: 3997 There is no way to clear one specific monitor from a SNES object. 3998 3999 Level: intermediate 4000 4001 .keywords: SNES, nonlinear, set, monitor 4002 4003 .seealso: SNESMonitorDefault(), SNESMonitorSet() 4004 @*/ 4005 PetscErrorCode SNESMonitorCancel(SNES snes) 4006 { 4007 PetscErrorCode ierr; 4008 PetscInt i; 4009 4010 PetscFunctionBegin; 4011 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4012 for (i=0; i<snes->numbermonitors; i++) { 4013 if (snes->monitordestroy[i]) { 4014 ierr = (*snes->monitordestroy[i])(&snes->monitorcontext[i]);CHKERRQ(ierr); 4015 } 4016 } 4017 snes->numbermonitors = 0; 4018 PetscFunctionReturn(0); 4019 } 4020 4021 /*MC 4022 SNESConvergenceTestFunction - functional form used for testing of convergence of nonlinear solver 4023 4024 Synopsis: 4025 #include <petscsnes.h> 4026 $ PetscErrorCode SNESConvergenceTest(SNES snes,PetscInt it,PetscReal xnorm,PetscReal gnorm,PetscReal f,SNESConvergedReason *reason,void *cctx) 4027 4028 + snes - the SNES context 4029 . it - current iteration (0 is the first and is before any Newton step) 4030 . cctx - [optional] convergence context 4031 . reason - reason for convergence/divergence 4032 . xnorm - 2-norm of current iterate 4033 . gnorm - 2-norm of current step 4034 - f - 2-norm of function 4035 4036 Level: intermediate 4037 4038 .seealso: SNESSetConvergenceTest(), SNESGetConvergenceTest() 4039 M*/ 4040 4041 /*@C 4042 SNESSetConvergenceTest - Sets the function that is to be used 4043 to test for convergence of the nonlinear iterative solution. 4044 4045 Logically Collective on SNES 4046 4047 Input Parameters: 4048 + snes - the SNES context 4049 . SNESConvergenceTestFunction - routine to test for convergence 4050 . cctx - [optional] context for private data for the convergence routine (may be NULL) 4051 - destroy - [optional] destructor for the context (may be NULL; PETSC_NULL_FUNCTION in Fortran) 4052 4053 Level: advanced 4054 4055 .keywords: SNES, nonlinear, set, convergence, test 4056 4057 .seealso: SNESConvergedDefault(), SNESConvergedSkip(), SNESConvergenceTestFunction 4058 @*/ 4059 PetscErrorCode SNESSetConvergenceTest(SNES snes,PetscErrorCode (*SNESConvergenceTestFunction)(SNES,PetscInt,PetscReal,PetscReal,PetscReal,SNESConvergedReason*,void*),void *cctx,PetscErrorCode (*destroy)(void*)) 4060 { 4061 PetscErrorCode ierr; 4062 4063 PetscFunctionBegin; 4064 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4065 if (!SNESConvergenceTestFunction) SNESConvergenceTestFunction = SNESConvergedSkip; 4066 if (snes->ops->convergeddestroy) { 4067 ierr = (*snes->ops->convergeddestroy)(snes->cnvP);CHKERRQ(ierr); 4068 } 4069 snes->ops->converged = SNESConvergenceTestFunction; 4070 snes->ops->convergeddestroy = destroy; 4071 snes->cnvP = cctx; 4072 PetscFunctionReturn(0); 4073 } 4074 4075 /*@ 4076 SNESGetConvergedReason - Gets the reason the SNES iteration was stopped. 4077 4078 Not Collective 4079 4080 Input Parameter: 4081 . snes - the SNES context 4082 4083 Output Parameter: 4084 . reason - negative value indicates diverged, positive value converged, see SNESConvergedReason or the 4085 manual pages for the individual convergence tests for complete lists 4086 4087 Options Database: 4088 . -snes_converged_reason - prints the reason to standard out 4089 4090 Level: intermediate 4091 4092 Notes: 4093 Should only be called after the call the SNESSolve() is complete, if it is called earlier it returns the value SNES__CONVERGED_ITERATING. 4094 4095 .keywords: SNES, nonlinear, set, convergence, test 4096 4097 .seealso: SNESSetConvergenceTest(), SNESSetConvergedReason(), SNESConvergedReason 4098 @*/ 4099 PetscErrorCode SNESGetConvergedReason(SNES snes,SNESConvergedReason *reason) 4100 { 4101 PetscFunctionBegin; 4102 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4103 PetscValidPointer(reason,2); 4104 *reason = snes->reason; 4105 PetscFunctionReturn(0); 4106 } 4107 4108 /*@ 4109 SNESSetConvergedReason - Sets the reason the SNES iteration was stopped. 4110 4111 Not Collective 4112 4113 Input Parameters: 4114 + snes - the SNES context 4115 - reason - negative value indicates diverged, positive value converged, see SNESConvergedReason or the 4116 manual pages for the individual convergence tests for complete lists 4117 4118 Level: intermediate 4119 4120 .keywords: SNES, nonlinear, set, convergence, test 4121 .seealso: SNESGetConvergedReason(), SNESSetConvergenceTest(), SNESConvergedReason 4122 @*/ 4123 PetscErrorCode SNESSetConvergedReason(SNES snes,SNESConvergedReason reason) 4124 { 4125 PetscFunctionBegin; 4126 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4127 snes->reason = reason; 4128 PetscFunctionReturn(0); 4129 } 4130 4131 /*@ 4132 SNESSetConvergenceHistory - Sets the array used to hold the convergence history. 4133 4134 Logically Collective on SNES 4135 4136 Input Parameters: 4137 + snes - iterative context obtained from SNESCreate() 4138 . a - array to hold history, this array will contain the function norms computed at each step 4139 . its - integer array holds the number of linear iterations for each solve. 4140 . na - size of a and its 4141 - reset - PETSC_TRUE indicates each new nonlinear solve resets the history counter to zero, 4142 else it continues storing new values for new nonlinear solves after the old ones 4143 4144 Notes: 4145 If 'a' and 'its' are NULL then space is allocated for the history. If 'na' PETSC_DECIDE or PETSC_DEFAULT then a 4146 default array of length 10000 is allocated. 4147 4148 This routine is useful, e.g., when running a code for purposes 4149 of accurate performance monitoring, when no I/O should be done 4150 during the section of code that is being timed. 4151 4152 Level: intermediate 4153 4154 .keywords: SNES, set, convergence, history 4155 4156 .seealso: SNESGetConvergenceHistory() 4157 4158 @*/ 4159 PetscErrorCode SNESSetConvergenceHistory(SNES snes,PetscReal a[],PetscInt its[],PetscInt na,PetscBool reset) 4160 { 4161 PetscErrorCode ierr; 4162 4163 PetscFunctionBegin; 4164 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4165 if (a) PetscValidScalarPointer(a,2); 4166 if (its) PetscValidIntPointer(its,3); 4167 if (!a) { 4168 if (na == PETSC_DECIDE || na == PETSC_DEFAULT) na = 1000; 4169 ierr = PetscCalloc1(na,&a);CHKERRQ(ierr); 4170 ierr = PetscCalloc1(na,&its);CHKERRQ(ierr); 4171 4172 snes->conv_malloc = PETSC_TRUE; 4173 } 4174 snes->conv_hist = a; 4175 snes->conv_hist_its = its; 4176 snes->conv_hist_max = na; 4177 snes->conv_hist_len = 0; 4178 snes->conv_hist_reset = reset; 4179 PetscFunctionReturn(0); 4180 } 4181 4182 #if defined(PETSC_HAVE_MATLAB_ENGINE) 4183 #include <engine.h> /* MATLAB include file */ 4184 #include <mex.h> /* MATLAB include file */ 4185 4186 PETSC_EXTERN mxArray *SNESGetConvergenceHistoryMatlab(SNES snes) 4187 { 4188 mxArray *mat; 4189 PetscInt i; 4190 PetscReal *ar; 4191 4192 PetscFunctionBegin; 4193 mat = mxCreateDoubleMatrix(snes->conv_hist_len,1,mxREAL); 4194 ar = (PetscReal*) mxGetData(mat); 4195 for (i=0; i<snes->conv_hist_len; i++) ar[i] = snes->conv_hist[i]; 4196 PetscFunctionReturn(mat); 4197 } 4198 #endif 4199 4200 /*@C 4201 SNESGetConvergenceHistory - Gets the array used to hold the convergence history. 4202 4203 Not Collective 4204 4205 Input Parameter: 4206 . snes - iterative context obtained from SNESCreate() 4207 4208 Output Parameters: 4209 . a - array to hold history 4210 . its - integer array holds the number of linear iterations (or 4211 negative if not converged) for each solve. 4212 - na - size of a and its 4213 4214 Notes: 4215 The calling sequence for this routine in Fortran is 4216 $ call SNESGetConvergenceHistory(SNES snes, integer na, integer ierr) 4217 4218 This routine is useful, e.g., when running a code for purposes 4219 of accurate performance monitoring, when no I/O should be done 4220 during the section of code that is being timed. 4221 4222 Level: intermediate 4223 4224 .keywords: SNES, get, convergence, history 4225 4226 .seealso: SNESSetConvergencHistory() 4227 4228 @*/ 4229 PetscErrorCode SNESGetConvergenceHistory(SNES snes,PetscReal *a[],PetscInt *its[],PetscInt *na) 4230 { 4231 PetscFunctionBegin; 4232 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4233 if (a) *a = snes->conv_hist; 4234 if (its) *its = snes->conv_hist_its; 4235 if (na) *na = snes->conv_hist_len; 4236 PetscFunctionReturn(0); 4237 } 4238 4239 /*@C 4240 SNESSetUpdate - Sets the general-purpose update function called 4241 at the beginning of every iteration of the nonlinear solve. Specifically 4242 it is called just before the Jacobian is "evaluated". 4243 4244 Logically Collective on SNES 4245 4246 Input Parameters: 4247 . snes - The nonlinear solver context 4248 . func - The function 4249 4250 Calling sequence of func: 4251 . func (SNES snes, PetscInt step); 4252 4253 . step - The current step of the iteration 4254 4255 Level: advanced 4256 4257 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() 4258 This is not used by most users. 4259 4260 .keywords: SNES, update 4261 4262 .seealso SNESSetJacobian(), SNESSolve() 4263 @*/ 4264 PetscErrorCode SNESSetUpdate(SNES snes, PetscErrorCode (*func)(SNES, PetscInt)) 4265 { 4266 PetscFunctionBegin; 4267 PetscValidHeaderSpecific(snes, SNES_CLASSID,1); 4268 snes->ops->update = func; 4269 PetscFunctionReturn(0); 4270 } 4271 4272 /* 4273 SNESScaleStep_Private - Scales a step so that its length is less than the 4274 positive parameter delta. 4275 4276 Input Parameters: 4277 + snes - the SNES context 4278 . y - approximate solution of linear system 4279 . fnorm - 2-norm of current function 4280 - delta - trust region size 4281 4282 Output Parameters: 4283 + gpnorm - predicted function norm at the new point, assuming local 4284 linearization. The value is zero if the step lies within the trust 4285 region, and exceeds zero otherwise. 4286 - ynorm - 2-norm of the step 4287 4288 Note: 4289 For non-trust region methods such as SNESNEWTONLS, the parameter delta 4290 is set to be the maximum allowable step size. 4291 4292 .keywords: SNES, nonlinear, scale, step 4293 */ 4294 PetscErrorCode SNESScaleStep_Private(SNES snes,Vec y,PetscReal *fnorm,PetscReal *delta,PetscReal *gpnorm,PetscReal *ynorm) 4295 { 4296 PetscReal nrm; 4297 PetscScalar cnorm; 4298 PetscErrorCode ierr; 4299 4300 PetscFunctionBegin; 4301 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4302 PetscValidHeaderSpecific(y,VEC_CLASSID,2); 4303 PetscCheckSameComm(snes,1,y,2); 4304 4305 ierr = VecNorm(y,NORM_2,&nrm);CHKERRQ(ierr); 4306 if (nrm > *delta) { 4307 nrm = *delta/nrm; 4308 *gpnorm = (1.0 - nrm)*(*fnorm); 4309 cnorm = nrm; 4310 ierr = VecScale(y,cnorm);CHKERRQ(ierr); 4311 *ynorm = *delta; 4312 } else { 4313 *gpnorm = 0.0; 4314 *ynorm = nrm; 4315 } 4316 PetscFunctionReturn(0); 4317 } 4318 4319 /*@ 4320 SNESReasonView - Displays the reason a SNES solve converged or diverged to a viewer 4321 4322 Collective on SNES 4323 4324 Parameter: 4325 + snes - iterative context obtained from SNESCreate() 4326 - viewer - the viewer to display the reason 4327 4328 4329 Options Database Keys: 4330 . -snes_converged_reason - print reason for converged or diverged, also prints number of iterations 4331 4332 Level: beginner 4333 4334 .keywords: SNES, solve, linear system 4335 4336 .seealso: SNESCreate(), SNESSetUp(), SNESDestroy(), SNESSetTolerances(), SNESConvergedDefault() 4337 4338 @*/ 4339 PetscErrorCode SNESReasonView(SNES snes,PetscViewer viewer) 4340 { 4341 PetscViewerFormat format; 4342 PetscBool isAscii; 4343 PetscErrorCode ierr; 4344 4345 PetscFunctionBegin; 4346 ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isAscii);CHKERRQ(ierr); 4347 if (isAscii) { 4348 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 4349 ierr = PetscViewerASCIIAddTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 4350 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 4351 DM dm; 4352 Vec u; 4353 PetscDS prob; 4354 PetscInt Nf, f; 4355 PetscErrorCode (**exactSol)(PetscInt, PetscReal, const PetscReal[], PetscInt, PetscScalar[], void *); 4356 void **exactCtx; 4357 PetscReal error; 4358 4359 ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr); 4360 ierr = SNESGetSolution(snes, &u);CHKERRQ(ierr); 4361 ierr = DMGetDS(dm, &prob);CHKERRQ(ierr); 4362 ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr); 4363 ierr = PetscMalloc2(Nf, &exactSol, Nf, &exactCtx);CHKERRQ(ierr); 4364 for (f = 0; f < Nf; ++f) {ierr = PetscDSGetExactSolution(prob, f, &exactSol[f], &exactCtx[f]);CHKERRQ(ierr);} 4365 ierr = DMComputeL2Diff(dm, 0.0, exactSol, exactCtx, u, &error);CHKERRQ(ierr); 4366 ierr = PetscFree2(exactSol, exactCtx);CHKERRQ(ierr); 4367 if (error < 1.0e-11) {ierr = PetscViewerASCIIPrintf(viewer, "L_2 Error: < 1.0e-11\n");CHKERRQ(ierr);} 4368 else {ierr = PetscViewerASCIIPrintf(viewer, "L_2 Error: %g\n", error);CHKERRQ(ierr);} 4369 } 4370 if (snes->reason > 0) { 4371 if (((PetscObject) snes)->prefix) { 4372 ierr = PetscViewerASCIIPrintf(viewer,"Nonlinear %s solve converged due to %s iterations %D\n",((PetscObject) snes)->prefix,SNESConvergedReasons[snes->reason],snes->iter);CHKERRQ(ierr); 4373 } else { 4374 ierr = PetscViewerASCIIPrintf(viewer,"Nonlinear solve converged due to %s iterations %D\n",SNESConvergedReasons[snes->reason],snes->iter);CHKERRQ(ierr); 4375 } 4376 } else { 4377 if (((PetscObject) snes)->prefix) { 4378 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); 4379 } else { 4380 ierr = PetscViewerASCIIPrintf(viewer,"Nonlinear solve did not converge due to %s iterations %D\n",SNESConvergedReasons[snes->reason],snes->iter);CHKERRQ(ierr); 4381 } 4382 } 4383 ierr = PetscViewerASCIISubtractTab(viewer,((PetscObject)snes)->tablevel);CHKERRQ(ierr); 4384 } 4385 PetscFunctionReturn(0); 4386 } 4387 4388 /*@C 4389 SNESReasonViewFromOptions - Processes command line options to determine if/how a SNESReason is to be viewed. 4390 4391 Collective on SNES 4392 4393 Input Parameters: 4394 . snes - the SNES object 4395 4396 Level: intermediate 4397 4398 @*/ 4399 PetscErrorCode SNESReasonViewFromOptions(SNES snes) 4400 { 4401 PetscErrorCode ierr; 4402 PetscViewer viewer; 4403 PetscBool flg; 4404 static PetscBool incall = PETSC_FALSE; 4405 PetscViewerFormat format; 4406 4407 PetscFunctionBegin; 4408 if (incall) PetscFunctionReturn(0); 4409 incall = PETSC_TRUE; 4410 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-snes_converged_reason",&viewer,&format,&flg);CHKERRQ(ierr); 4411 if (flg) { 4412 ierr = PetscViewerPushFormat(viewer,format);CHKERRQ(ierr); 4413 ierr = SNESReasonView(snes,viewer);CHKERRQ(ierr); 4414 ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 4415 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 4416 } 4417 incall = PETSC_FALSE; 4418 PetscFunctionReturn(0); 4419 } 4420 4421 /*@ 4422 SNESSolve - Solves a nonlinear system F(x) = b. 4423 Call SNESSolve() after calling SNESCreate() and optional routines of the form SNESSetXXX(). 4424 4425 Collective on SNES 4426 4427 Input Parameters: 4428 + snes - the SNES context 4429 . b - the constant part of the equation F(x) = b, or NULL to use zero. 4430 - x - the solution vector. 4431 4432 Notes: 4433 The user should initialize the vector,x, with the initial guess 4434 for the nonlinear solve prior to calling SNESSolve. In particular, 4435 to employ an initial guess of zero, the user should explicitly set 4436 this vector to zero by calling VecSet(). 4437 4438 Level: beginner 4439 4440 .keywords: SNES, nonlinear, solve 4441 4442 .seealso: SNESCreate(), SNESDestroy(), SNESSetFunction(), SNESSetJacobian(), SNESSetGridSequence(), SNESGetSolution() 4443 @*/ 4444 PetscErrorCode SNESSolve(SNES snes,Vec b,Vec x) 4445 { 4446 PetscErrorCode ierr; 4447 PetscBool flg; 4448 PetscInt grid; 4449 Vec xcreated = NULL; 4450 DM dm; 4451 4452 PetscFunctionBegin; 4453 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4454 if (x) PetscValidHeaderSpecific(x,VEC_CLASSID,3); 4455 if (x) PetscCheckSameComm(snes,1,x,3); 4456 if (b) PetscValidHeaderSpecific(b,VEC_CLASSID,2); 4457 if (b) PetscCheckSameComm(snes,1,b,2); 4458 4459 /* High level operations using the nonlinear solver */ 4460 { 4461 PetscViewer viewer; 4462 PetscViewerFormat format; 4463 PetscInt num; 4464 PetscBool flg; 4465 static PetscBool incall = PETSC_FALSE; 4466 4467 if (!incall) { 4468 /* Estimate the convergence rate of the discretization */ 4469 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject) snes),((PetscObject)snes)->options, ((PetscObject) snes)->prefix, "-snes_convergence_estimate", &viewer, &format, &flg);CHKERRQ(ierr); 4470 if (flg) { 4471 PetscConvEst conv; 4472 DM dm; 4473 PetscReal *alpha; /* Convergence rate of the solution error for each field in the L_2 norm */ 4474 PetscInt Nf; 4475 4476 incall = PETSC_TRUE; 4477 ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr); 4478 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 4479 ierr = PetscMalloc1(Nf, &alpha);CHKERRQ(ierr); 4480 ierr = PetscConvEstCreate(PetscObjectComm((PetscObject) snes), &conv);CHKERRQ(ierr); 4481 ierr = PetscConvEstSetSolver(conv, snes);CHKERRQ(ierr); 4482 ierr = PetscConvEstSetFromOptions(conv);CHKERRQ(ierr); 4483 ierr = PetscConvEstSetUp(conv);CHKERRQ(ierr); 4484 ierr = PetscConvEstGetConvRate(conv, alpha);CHKERRQ(ierr); 4485 ierr = PetscViewerPushFormat(viewer, format);CHKERRQ(ierr); 4486 ierr = PetscConvEstRateView(conv, alpha, viewer);CHKERRQ(ierr); 4487 ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 4488 ierr = PetscViewerDestroy(&viewer);CHKERRQ(ierr); 4489 ierr = PetscConvEstDestroy(&conv);CHKERRQ(ierr); 4490 ierr = PetscFree(alpha);CHKERRQ(ierr); 4491 incall = PETSC_FALSE; 4492 } 4493 /* Adaptively refine the initial grid */ 4494 num = 1; 4495 ierr = PetscOptionsGetInt(NULL, ((PetscObject) snes)->prefix, "-snes_adapt_initial", &num, &flg);CHKERRQ(ierr); 4496 if (flg) { 4497 DMAdaptor adaptor; 4498 4499 incall = PETSC_TRUE; 4500 ierr = DMAdaptorCreate(PETSC_COMM_WORLD, &adaptor);CHKERRQ(ierr); 4501 ierr = DMAdaptorSetSolver(adaptor, snes);CHKERRQ(ierr); 4502 ierr = DMAdaptorSetSequenceLength(adaptor, num);CHKERRQ(ierr); 4503 ierr = DMAdaptorSetFromOptions(adaptor);CHKERRQ(ierr); 4504 ierr = DMAdaptorSetUp(adaptor);CHKERRQ(ierr); 4505 ierr = DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_INITIAL, &dm, &x);CHKERRQ(ierr); 4506 ierr = DMAdaptorDestroy(&adaptor);CHKERRQ(ierr); 4507 incall = PETSC_FALSE; 4508 } 4509 /* Use grid sequencing to adapt */ 4510 num = 0; 4511 ierr = PetscOptionsGetInt(NULL, ((PetscObject) snes)->prefix, "-snes_adapt_sequence", &num, NULL);CHKERRQ(ierr); 4512 if (num) { 4513 DMAdaptor adaptor; 4514 4515 incall = PETSC_TRUE; 4516 ierr = DMAdaptorCreate(PETSC_COMM_WORLD, &adaptor);CHKERRQ(ierr); 4517 ierr = DMAdaptorSetSolver(adaptor, snes);CHKERRQ(ierr); 4518 ierr = DMAdaptorSetSequenceLength(adaptor, num);CHKERRQ(ierr); 4519 ierr = DMAdaptorSetFromOptions(adaptor);CHKERRQ(ierr); 4520 ierr = DMAdaptorSetUp(adaptor);CHKERRQ(ierr); 4521 ierr = DMAdaptorAdapt(adaptor, x, DM_ADAPTATION_SEQUENTIAL, &dm, &x);CHKERRQ(ierr); 4522 ierr = DMAdaptorDestroy(&adaptor);CHKERRQ(ierr); 4523 incall = PETSC_FALSE; 4524 } 4525 } 4526 } 4527 if (!x) { 4528 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 4529 ierr = DMCreateGlobalVector(dm,&xcreated);CHKERRQ(ierr); 4530 x = xcreated; 4531 } 4532 ierr = SNESViewFromOptions(snes,NULL,"-snes_view_pre");CHKERRQ(ierr); 4533 4534 for (grid=0; grid<snes->gridsequence; grid++) {ierr = PetscViewerASCIIPushTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)));CHKERRQ(ierr);} 4535 for (grid=0; grid<snes->gridsequence+1; grid++) { 4536 4537 /* set solution vector */ 4538 if (!grid) {ierr = PetscObjectReference((PetscObject)x);CHKERRQ(ierr);} 4539 ierr = VecDestroy(&snes->vec_sol);CHKERRQ(ierr); 4540 snes->vec_sol = x; 4541 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 4542 4543 /* set affine vector if provided */ 4544 if (b) { ierr = PetscObjectReference((PetscObject)b);CHKERRQ(ierr); } 4545 ierr = VecDestroy(&snes->vec_rhs);CHKERRQ(ierr); 4546 snes->vec_rhs = b; 4547 4548 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"); 4549 if (snes->vec_func == snes->vec_sol) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"Solution vector cannot be function vector"); 4550 if (snes->vec_rhs == snes->vec_sol) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_IDN,"Solution vector cannot be right hand side vector"); 4551 if (!snes->vec_sol_update /* && snes->vec_sol */) { 4552 ierr = VecDuplicate(snes->vec_sol,&snes->vec_sol_update);CHKERRQ(ierr); 4553 ierr = PetscLogObjectParent((PetscObject)snes,(PetscObject)snes->vec_sol_update);CHKERRQ(ierr); 4554 } 4555 ierr = DMShellSetGlobalVector(dm,snes->vec_sol);CHKERRQ(ierr); 4556 ierr = SNESSetUp(snes);CHKERRQ(ierr); 4557 4558 if (!grid) { 4559 if (snes->ops->computeinitialguess) { 4560 ierr = (*snes->ops->computeinitialguess)(snes,snes->vec_sol,snes->initialguessP);CHKERRQ(ierr); 4561 } 4562 } 4563 4564 if (snes->conv_hist_reset) snes->conv_hist_len = 0; 4565 if (snes->counters_reset) {snes->nfuncs = 0; snes->linear_its = 0; snes->numFailures = 0;} 4566 4567 ierr = PetscLogEventBegin(SNES_Solve,snes,0,0,0);CHKERRQ(ierr); 4568 ierr = (*snes->ops->solve)(snes);CHKERRQ(ierr); 4569 ierr = PetscLogEventEnd(SNES_Solve,snes,0,0,0);CHKERRQ(ierr); 4570 if (!snes->reason) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Internal error, solver returned without setting converged reason"); 4571 snes->domainerror = PETSC_FALSE; /* clear the flag if it has been set */ 4572 4573 if (snes->lagjac_persist) snes->jac_iter += snes->iter; 4574 if (snes->lagpre_persist) snes->pre_iter += snes->iter; 4575 4576 ierr = PetscOptionsGetViewer(PetscObjectComm((PetscObject)snes),((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-snes_test_local_min",NULL,NULL,&flg);CHKERRQ(ierr); 4577 if (flg && !PetscPreLoadingOn) { ierr = SNESTestLocalMin(snes);CHKERRQ(ierr); } 4578 ierr = SNESReasonViewFromOptions(snes);CHKERRQ(ierr); 4579 4580 if (snes->errorifnotconverged && snes->reason < 0) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_NOT_CONVERGED,"SNESSolve has not converged"); 4581 if (snes->reason < 0) break; 4582 if (grid < snes->gridsequence) { 4583 DM fine; 4584 Vec xnew; 4585 Mat interp; 4586 4587 ierr = DMRefine(snes->dm,PetscObjectComm((PetscObject)snes),&fine);CHKERRQ(ierr); 4588 if (!fine) SETERRQ(PetscObjectComm((PetscObject)snes),PETSC_ERR_ARG_INCOMP,"DMRefine() did not perform any refinement, cannot continue grid sequencing"); 4589 ierr = DMCreateInterpolation(snes->dm,fine,&interp,NULL);CHKERRQ(ierr); 4590 ierr = DMCreateGlobalVector(fine,&xnew);CHKERRQ(ierr); 4591 ierr = MatInterpolate(interp,x,xnew);CHKERRQ(ierr); 4592 ierr = DMInterpolate(snes->dm,interp,fine);CHKERRQ(ierr); 4593 ierr = MatDestroy(&interp);CHKERRQ(ierr); 4594 x = xnew; 4595 4596 ierr = SNESReset(snes);CHKERRQ(ierr); 4597 ierr = SNESSetDM(snes,fine);CHKERRQ(ierr); 4598 ierr = SNESResetFromOptions(snes);CHKERRQ(ierr); 4599 ierr = DMDestroy(&fine);CHKERRQ(ierr); 4600 ierr = PetscViewerASCIIPopTab(PETSC_VIEWER_STDOUT_(PetscObjectComm((PetscObject)snes)));CHKERRQ(ierr); 4601 } 4602 } 4603 ierr = SNESViewFromOptions(snes,NULL,"-snes_view");CHKERRQ(ierr); 4604 ierr = VecViewFromOptions(snes->vec_sol,(PetscObject)snes,"-snes_view_solution");CHKERRQ(ierr); 4605 4606 ierr = VecDestroy(&xcreated);CHKERRQ(ierr); 4607 ierr = PetscObjectSAWsBlock((PetscObject)snes);CHKERRQ(ierr); 4608 PetscFunctionReturn(0); 4609 } 4610 4611 /* --------- Internal routines for SNES Package --------- */ 4612 4613 /*@C 4614 SNESSetType - Sets the method for the nonlinear solver. 4615 4616 Collective on SNES 4617 4618 Input Parameters: 4619 + snes - the SNES context 4620 - type - a known method 4621 4622 Options Database Key: 4623 . -snes_type <type> - Sets the method; use -help for a list 4624 of available methods (for instance, newtonls or newtontr) 4625 4626 Notes: 4627 See "petsc/include/petscsnes.h" for available methods (for instance) 4628 + SNESNEWTONLS - Newton's method with line search 4629 (systems of nonlinear equations) 4630 . SNESNEWTONTR - Newton's method with trust region 4631 (systems of nonlinear equations) 4632 4633 Normally, it is best to use the SNESSetFromOptions() command and then 4634 set the SNES solver type from the options database rather than by using 4635 this routine. Using the options database provides the user with 4636 maximum flexibility in evaluating the many nonlinear solvers. 4637 The SNESSetType() routine is provided for those situations where it 4638 is necessary to set the nonlinear solver independently of the command 4639 line or options database. This might be the case, for example, when 4640 the choice of solver changes during the execution of the program, 4641 and the user's application is taking responsibility for choosing the 4642 appropriate method. 4643 4644 Developer Notes: 4645 SNESRegister() adds a constructor for a new SNESType to SNESList, SNESSetType() locates 4646 the constructor in that list and calls it to create the spexific object. 4647 4648 Level: intermediate 4649 4650 .keywords: SNES, set, type 4651 4652 .seealso: SNESType, SNESCreate(), SNESDestroy(), SNESGetType(), SNESSetFromOptions() 4653 4654 @*/ 4655 PetscErrorCode SNESSetType(SNES snes,SNESType type) 4656 { 4657 PetscErrorCode ierr,(*r)(SNES); 4658 PetscBool match; 4659 4660 PetscFunctionBegin; 4661 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4662 PetscValidCharPointer(type,2); 4663 4664 ierr = PetscObjectTypeCompare((PetscObject)snes,type,&match);CHKERRQ(ierr); 4665 if (match) PetscFunctionReturn(0); 4666 4667 ierr = PetscFunctionListFind(SNESList,type,&r);CHKERRQ(ierr); 4668 if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE,"Unable to find requested SNES type %s",type); 4669 /* Destroy the previous private SNES context */ 4670 if (snes->ops->destroy) { 4671 ierr = (*(snes)->ops->destroy)(snes);CHKERRQ(ierr); 4672 snes->ops->destroy = NULL; 4673 } 4674 /* Reinitialize function pointers in SNESOps structure */ 4675 snes->ops->setup = 0; 4676 snes->ops->solve = 0; 4677 snes->ops->view = 0; 4678 snes->ops->setfromoptions = 0; 4679 snes->ops->destroy = 0; 4680 ierr = SNESLineSearchDestroy(&snes->linesearch);CHKERRQ(ierr); 4681 /* Call the SNESCreate_XXX routine for this particular Nonlinear solver */ 4682 snes->setupcalled = PETSC_FALSE; 4683 4684 ierr = PetscObjectChangeTypeName((PetscObject)snes,type);CHKERRQ(ierr); 4685 ierr = (*r)(snes);CHKERRQ(ierr); 4686 PetscFunctionReturn(0); 4687 } 4688 4689 /*@C 4690 SNESGetType - Gets the SNES method type and name (as a string). 4691 4692 Not Collective 4693 4694 Input Parameter: 4695 . snes - nonlinear solver context 4696 4697 Output Parameter: 4698 . type - SNES method (a character string) 4699 4700 Level: intermediate 4701 4702 .keywords: SNES, nonlinear, get, type, name 4703 @*/ 4704 PetscErrorCode SNESGetType(SNES snes,SNESType *type) 4705 { 4706 PetscFunctionBegin; 4707 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4708 PetscValidPointer(type,2); 4709 *type = ((PetscObject)snes)->type_name; 4710 PetscFunctionReturn(0); 4711 } 4712 4713 /*@ 4714 SNESSetSolution - Sets the solution vector for use by the SNES routines. 4715 4716 Logically Collective on SNES and Vec 4717 4718 Input Parameters: 4719 + snes - the SNES context obtained from SNESCreate() 4720 - u - the solution vector 4721 4722 Level: beginner 4723 4724 .keywords: SNES, set, solution 4725 @*/ 4726 PetscErrorCode SNESSetSolution(SNES snes, Vec u) 4727 { 4728 DM dm; 4729 PetscErrorCode ierr; 4730 4731 PetscFunctionBegin; 4732 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 4733 PetscValidHeaderSpecific(u, VEC_CLASSID, 2); 4734 ierr = PetscObjectReference((PetscObject) u);CHKERRQ(ierr); 4735 ierr = VecDestroy(&snes->vec_sol);CHKERRQ(ierr); 4736 4737 snes->vec_sol = u; 4738 4739 ierr = SNESGetDM(snes, &dm);CHKERRQ(ierr); 4740 ierr = DMShellSetGlobalVector(dm, u);CHKERRQ(ierr); 4741 PetscFunctionReturn(0); 4742 } 4743 4744 /*@ 4745 SNESGetSolution - Returns the vector where the approximate solution is 4746 stored. This is the fine grid solution when using SNESSetGridSequence(). 4747 4748 Not Collective, but Vec is parallel if SNES is parallel 4749 4750 Input Parameter: 4751 . snes - the SNES context 4752 4753 Output Parameter: 4754 . x - the solution 4755 4756 Level: intermediate 4757 4758 .keywords: SNES, nonlinear, get, solution 4759 4760 .seealso: SNESGetSolutionUpdate(), SNESGetFunction() 4761 @*/ 4762 PetscErrorCode SNESGetSolution(SNES snes,Vec *x) 4763 { 4764 PetscFunctionBegin; 4765 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4766 PetscValidPointer(x,2); 4767 *x = snes->vec_sol; 4768 PetscFunctionReturn(0); 4769 } 4770 4771 /*@ 4772 SNESGetSolutionUpdate - Returns the vector where the solution update is 4773 stored. 4774 4775 Not Collective, but Vec is parallel if SNES is parallel 4776 4777 Input Parameter: 4778 . snes - the SNES context 4779 4780 Output Parameter: 4781 . x - the solution update 4782 4783 Level: advanced 4784 4785 .keywords: SNES, nonlinear, get, solution, update 4786 4787 .seealso: SNESGetSolution(), SNESGetFunction() 4788 @*/ 4789 PetscErrorCode SNESGetSolutionUpdate(SNES snes,Vec *x) 4790 { 4791 PetscFunctionBegin; 4792 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4793 PetscValidPointer(x,2); 4794 *x = snes->vec_sol_update; 4795 PetscFunctionReturn(0); 4796 } 4797 4798 /*@C 4799 SNESGetFunction - Returns the vector where the function is stored. 4800 4801 Not Collective, but Vec is parallel if SNES is parallel. Collective if Vec is requested, but has not been created yet. 4802 4803 Input Parameter: 4804 . snes - the SNES context 4805 4806 Output Parameter: 4807 + r - the vector that is used to store residuals (or NULL if you don't want it) 4808 . f - the function (or NULL if you don't want it); see SNESFunction for calling sequence details 4809 - ctx - the function context (or NULL if you don't want it) 4810 4811 Level: advanced 4812 4813 Notes: The vector r DOES NOT, in general contain the current value of the SNES nonlinear function 4814 4815 .keywords: SNES, nonlinear, get, function 4816 4817 .seealso: SNESSetFunction(), SNESGetSolution(), SNESFunction 4818 @*/ 4819 PetscErrorCode SNESGetFunction(SNES snes,Vec *r,PetscErrorCode (**f)(SNES,Vec,Vec,void*),void **ctx) 4820 { 4821 PetscErrorCode ierr; 4822 DM dm; 4823 4824 PetscFunctionBegin; 4825 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4826 if (r) { 4827 if (!snes->vec_func) { 4828 if (snes->vec_rhs) { 4829 ierr = VecDuplicate(snes->vec_rhs,&snes->vec_func);CHKERRQ(ierr); 4830 } else if (snes->vec_sol) { 4831 ierr = VecDuplicate(snes->vec_sol,&snes->vec_func);CHKERRQ(ierr); 4832 } else if (snes->dm) { 4833 ierr = DMCreateGlobalVector(snes->dm,&snes->vec_func);CHKERRQ(ierr); 4834 } 4835 } 4836 *r = snes->vec_func; 4837 } 4838 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 4839 ierr = DMSNESGetFunction(dm,f,ctx);CHKERRQ(ierr); 4840 PetscFunctionReturn(0); 4841 } 4842 4843 /*@C 4844 SNESGetNGS - Returns the NGS function and context. 4845 4846 Input Parameter: 4847 . snes - the SNES context 4848 4849 Output Parameter: 4850 + f - the function (or NULL) see SNESNGSFunction for details 4851 - ctx - the function context (or NULL) 4852 4853 Level: advanced 4854 4855 .keywords: SNES, nonlinear, get, function 4856 4857 .seealso: SNESSetNGS(), SNESGetFunction() 4858 @*/ 4859 4860 PetscErrorCode SNESGetNGS (SNES snes, PetscErrorCode (**f)(SNES, Vec, Vec, void*), void ** ctx) 4861 { 4862 PetscErrorCode ierr; 4863 DM dm; 4864 4865 PetscFunctionBegin; 4866 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4867 ierr = SNESGetDM(snes,&dm);CHKERRQ(ierr); 4868 ierr = DMSNESGetNGS(dm,f,ctx);CHKERRQ(ierr); 4869 PetscFunctionReturn(0); 4870 } 4871 4872 /*@C 4873 SNESSetOptionsPrefix - Sets the prefix used for searching for all 4874 SNES options in the database. 4875 4876 Logically Collective on SNES 4877 4878 Input Parameter: 4879 + snes - the SNES context 4880 - prefix - the prefix to prepend to all option names 4881 4882 Notes: 4883 A hyphen (-) must NOT be given at the beginning of the prefix name. 4884 The first character of all runtime options is AUTOMATICALLY the hyphen. 4885 4886 Level: advanced 4887 4888 .keywords: SNES, set, options, prefix, database 4889 4890 .seealso: SNESSetFromOptions() 4891 @*/ 4892 PetscErrorCode SNESSetOptionsPrefix(SNES snes,const char prefix[]) 4893 { 4894 PetscErrorCode ierr; 4895 4896 PetscFunctionBegin; 4897 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4898 ierr = PetscObjectSetOptionsPrefix((PetscObject)snes,prefix);CHKERRQ(ierr); 4899 if (!snes->ksp) {ierr = SNESGetKSP(snes,&snes->ksp);CHKERRQ(ierr);} 4900 if (snes->linesearch) { 4901 ierr = SNESGetLineSearch(snes,&snes->linesearch);CHKERRQ(ierr); 4902 ierr = PetscObjectSetOptionsPrefix((PetscObject)snes->linesearch,prefix);CHKERRQ(ierr); 4903 } 4904 ierr = KSPSetOptionsPrefix(snes->ksp,prefix);CHKERRQ(ierr); 4905 PetscFunctionReturn(0); 4906 } 4907 4908 /*@C 4909 SNESAppendOptionsPrefix - Appends to the prefix used for searching for all 4910 SNES options in the database. 4911 4912 Logically Collective on SNES 4913 4914 Input Parameters: 4915 + snes - the SNES context 4916 - prefix - the prefix to prepend to all option names 4917 4918 Notes: 4919 A hyphen (-) must NOT be given at the beginning of the prefix name. 4920 The first character of all runtime options is AUTOMATICALLY the hyphen. 4921 4922 Level: advanced 4923 4924 .keywords: SNES, append, options, prefix, database 4925 4926 .seealso: SNESGetOptionsPrefix() 4927 @*/ 4928 PetscErrorCode SNESAppendOptionsPrefix(SNES snes,const char prefix[]) 4929 { 4930 PetscErrorCode ierr; 4931 4932 PetscFunctionBegin; 4933 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4934 ierr = PetscObjectAppendOptionsPrefix((PetscObject)snes,prefix);CHKERRQ(ierr); 4935 if (!snes->ksp) {ierr = SNESGetKSP(snes,&snes->ksp);CHKERRQ(ierr);} 4936 if (snes->linesearch) { 4937 ierr = SNESGetLineSearch(snes,&snes->linesearch);CHKERRQ(ierr); 4938 ierr = PetscObjectAppendOptionsPrefix((PetscObject)snes->linesearch,prefix);CHKERRQ(ierr); 4939 } 4940 ierr = KSPAppendOptionsPrefix(snes->ksp,prefix);CHKERRQ(ierr); 4941 PetscFunctionReturn(0); 4942 } 4943 4944 /*@C 4945 SNESGetOptionsPrefix - Sets the prefix used for searching for all 4946 SNES options in the database. 4947 4948 Not Collective 4949 4950 Input Parameter: 4951 . snes - the SNES context 4952 4953 Output Parameter: 4954 . prefix - pointer to the prefix string used 4955 4956 Notes: 4957 On the fortran side, the user should pass in a string 'prefix' of 4958 sufficient length to hold the prefix. 4959 4960 Level: advanced 4961 4962 .keywords: SNES, get, options, prefix, database 4963 4964 .seealso: SNESAppendOptionsPrefix() 4965 @*/ 4966 PetscErrorCode SNESGetOptionsPrefix(SNES snes,const char *prefix[]) 4967 { 4968 PetscErrorCode ierr; 4969 4970 PetscFunctionBegin; 4971 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 4972 ierr = PetscObjectGetOptionsPrefix((PetscObject)snes,prefix);CHKERRQ(ierr); 4973 PetscFunctionReturn(0); 4974 } 4975 4976 4977 /*@C 4978 SNESRegister - Adds a method to the nonlinear solver package. 4979 4980 Not collective 4981 4982 Input Parameters: 4983 + name_solver - name of a new user-defined solver 4984 - routine_create - routine to create method context 4985 4986 Notes: 4987 SNESRegister() may be called multiple times to add several user-defined solvers. 4988 4989 Sample usage: 4990 .vb 4991 SNESRegister("my_solver",MySolverCreate); 4992 .ve 4993 4994 Then, your solver can be chosen with the procedural interface via 4995 $ SNESSetType(snes,"my_solver") 4996 or at runtime via the option 4997 $ -snes_type my_solver 4998 4999 Level: advanced 5000 5001 Note: If your function is not being put into a shared library then use SNESRegister() instead 5002 5003 .keywords: SNES, nonlinear, register 5004 5005 .seealso: SNESRegisterAll(), SNESRegisterDestroy() 5006 5007 Level: advanced 5008 @*/ 5009 PetscErrorCode SNESRegister(const char sname[],PetscErrorCode (*function)(SNES)) 5010 { 5011 PetscErrorCode ierr; 5012 5013 PetscFunctionBegin; 5014 ierr = SNESInitializePackage();CHKERRQ(ierr); 5015 ierr = PetscFunctionListAdd(&SNESList,sname,function);CHKERRQ(ierr); 5016 PetscFunctionReturn(0); 5017 } 5018 5019 PetscErrorCode SNESTestLocalMin(SNES snes) 5020 { 5021 PetscErrorCode ierr; 5022 PetscInt N,i,j; 5023 Vec u,uh,fh; 5024 PetscScalar value; 5025 PetscReal norm; 5026 5027 PetscFunctionBegin; 5028 ierr = SNESGetSolution(snes,&u);CHKERRQ(ierr); 5029 ierr = VecDuplicate(u,&uh);CHKERRQ(ierr); 5030 ierr = VecDuplicate(u,&fh);CHKERRQ(ierr); 5031 5032 /* currently only works for sequential */ 5033 ierr = PetscPrintf(PETSC_COMM_WORLD,"Testing FormFunction() for local min\n");CHKERRQ(ierr); 5034 ierr = VecGetSize(u,&N);CHKERRQ(ierr); 5035 for (i=0; i<N; i++) { 5036 ierr = VecCopy(u,uh);CHKERRQ(ierr); 5037 ierr = PetscPrintf(PETSC_COMM_WORLD,"i = %D\n",i);CHKERRQ(ierr); 5038 for (j=-10; j<11; j++) { 5039 value = PetscSign(j)*PetscExpReal(PetscAbs(j)-10.0); 5040 ierr = VecSetValue(uh,i,value,ADD_VALUES);CHKERRQ(ierr); 5041 ierr = SNESComputeFunction(snes,uh,fh);CHKERRQ(ierr); 5042 ierr = VecNorm(fh,NORM_2,&norm);CHKERRQ(ierr); 5043 ierr = PetscPrintf(PETSC_COMM_WORLD," j norm %D %18.16e\n",j,norm);CHKERRQ(ierr); 5044 value = -value; 5045 ierr = VecSetValue(uh,i,value,ADD_VALUES);CHKERRQ(ierr); 5046 } 5047 } 5048 ierr = VecDestroy(&uh);CHKERRQ(ierr); 5049 ierr = VecDestroy(&fh);CHKERRQ(ierr); 5050 PetscFunctionReturn(0); 5051 } 5052 5053 /*@ 5054 SNESKSPSetUseEW - Sets SNES use Eisenstat-Walker method for 5055 computing relative tolerance for linear solvers within an inexact 5056 Newton method. 5057 5058 Logically Collective on SNES 5059 5060 Input Parameters: 5061 + snes - SNES context 5062 - flag - PETSC_TRUE or PETSC_FALSE 5063 5064 Options Database: 5065 + -snes_ksp_ew - use Eisenstat-Walker method for determining linear system convergence 5066 . -snes_ksp_ew_version ver - version of Eisenstat-Walker method 5067 . -snes_ksp_ew_rtol0 <rtol0> - Sets rtol0 5068 . -snes_ksp_ew_rtolmax <rtolmax> - Sets rtolmax 5069 . -snes_ksp_ew_gamma <gamma> - Sets gamma 5070 . -snes_ksp_ew_alpha <alpha> - Sets alpha 5071 . -snes_ksp_ew_alpha2 <alpha2> - Sets alpha2 5072 - -snes_ksp_ew_threshold <threshold> - Sets threshold 5073 5074 Notes: 5075 Currently, the default is to use a constant relative tolerance for 5076 the inner linear solvers. Alternatively, one can use the 5077 Eisenstat-Walker method, where the relative convergence tolerance 5078 is reset at each Newton iteration according progress of the nonlinear 5079 solver. 5080 5081 Level: advanced 5082 5083 Reference: 5084 S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an 5085 inexact Newton method", SISC 17 (1), pp.16-32, 1996. 5086 5087 .keywords: SNES, KSP, Eisenstat, Walker, convergence, test, inexact, Newton 5088 5089 .seealso: SNESKSPGetUseEW(), SNESKSPGetParametersEW(), SNESKSPSetParametersEW() 5090 @*/ 5091 PetscErrorCode SNESKSPSetUseEW(SNES snes,PetscBool flag) 5092 { 5093 PetscFunctionBegin; 5094 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 5095 PetscValidLogicalCollectiveBool(snes,flag,2); 5096 snes->ksp_ewconv = flag; 5097 PetscFunctionReturn(0); 5098 } 5099 5100 /*@ 5101 SNESKSPGetUseEW - Gets if SNES is using Eisenstat-Walker method 5102 for computing relative tolerance for linear solvers within an 5103 inexact Newton method. 5104 5105 Not Collective 5106 5107 Input Parameter: 5108 . snes - SNES context 5109 5110 Output Parameter: 5111 . flag - PETSC_TRUE or PETSC_FALSE 5112 5113 Notes: 5114 Currently, the default is to use a constant relative tolerance for 5115 the inner linear solvers. Alternatively, one can use the 5116 Eisenstat-Walker method, where the relative convergence tolerance 5117 is reset at each Newton iteration according progress of the nonlinear 5118 solver. 5119 5120 Level: advanced 5121 5122 Reference: 5123 S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an 5124 inexact Newton method", SISC 17 (1), pp.16-32, 1996. 5125 5126 .keywords: SNES, KSP, Eisenstat, Walker, convergence, test, inexact, Newton 5127 5128 .seealso: SNESKSPSetUseEW(), SNESKSPGetParametersEW(), SNESKSPSetParametersEW() 5129 @*/ 5130 PetscErrorCode SNESKSPGetUseEW(SNES snes, PetscBool *flag) 5131 { 5132 PetscFunctionBegin; 5133 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 5134 PetscValidPointer(flag,2); 5135 *flag = snes->ksp_ewconv; 5136 PetscFunctionReturn(0); 5137 } 5138 5139 /*@ 5140 SNESKSPSetParametersEW - Sets parameters for Eisenstat-Walker 5141 convergence criteria for the linear solvers within an inexact 5142 Newton method. 5143 5144 Logically Collective on SNES 5145 5146 Input Parameters: 5147 + snes - SNES context 5148 . version - version 1, 2 (default is 2) or 3 5149 . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 5150 . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 5151 . gamma - multiplicative factor for version 2 rtol computation 5152 (0 <= gamma2 <= 1) 5153 . alpha - power for version 2 rtol computation (1 < alpha <= 2) 5154 . alpha2 - power for safeguard 5155 - threshold - threshold for imposing safeguard (0 < threshold < 1) 5156 5157 Note: 5158 Version 3 was contributed by Luis Chacon, June 2006. 5159 5160 Use PETSC_DEFAULT to retain the default for any of the parameters. 5161 5162 Level: advanced 5163 5164 Reference: 5165 S. C. Eisenstat and H. F. Walker, "Choosing the forcing terms in an 5166 inexact Newton method", Utah State University Math. Stat. Dept. Res. 5167 Report 6/94/75, June, 1994, to appear in SIAM J. Sci. Comput. 5168 5169 .keywords: SNES, KSP, Eisenstat, Walker, set, parameters 5170 5171 .seealso: SNESKSPSetUseEW(), SNESKSPGetUseEW(), SNESKSPGetParametersEW() 5172 @*/ 5173 PetscErrorCode SNESKSPSetParametersEW(SNES snes,PetscInt version,PetscReal rtol_0,PetscReal rtol_max,PetscReal gamma,PetscReal alpha,PetscReal alpha2,PetscReal threshold) 5174 { 5175 SNESKSPEW *kctx; 5176 5177 PetscFunctionBegin; 5178 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 5179 kctx = (SNESKSPEW*)snes->kspconvctx; 5180 if (!kctx) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context existing"); 5181 PetscValidLogicalCollectiveInt(snes,version,2); 5182 PetscValidLogicalCollectiveReal(snes,rtol_0,3); 5183 PetscValidLogicalCollectiveReal(snes,rtol_max,4); 5184 PetscValidLogicalCollectiveReal(snes,gamma,5); 5185 PetscValidLogicalCollectiveReal(snes,alpha,6); 5186 PetscValidLogicalCollectiveReal(snes,alpha2,7); 5187 PetscValidLogicalCollectiveReal(snes,threshold,8); 5188 5189 if (version != PETSC_DEFAULT) kctx->version = version; 5190 if (rtol_0 != PETSC_DEFAULT) kctx->rtol_0 = rtol_0; 5191 if (rtol_max != PETSC_DEFAULT) kctx->rtol_max = rtol_max; 5192 if (gamma != PETSC_DEFAULT) kctx->gamma = gamma; 5193 if (alpha != PETSC_DEFAULT) kctx->alpha = alpha; 5194 if (alpha2 != PETSC_DEFAULT) kctx->alpha2 = alpha2; 5195 if (threshold != PETSC_DEFAULT) kctx->threshold = threshold; 5196 5197 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); 5198 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); 5199 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); 5200 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); 5201 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); 5202 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); 5203 PetscFunctionReturn(0); 5204 } 5205 5206 /*@ 5207 SNESKSPGetParametersEW - Gets parameters for Eisenstat-Walker 5208 convergence criteria for the linear solvers within an inexact 5209 Newton method. 5210 5211 Not Collective 5212 5213 Input Parameters: 5214 snes - SNES context 5215 5216 Output Parameters: 5217 + version - version 1, 2 (default is 2) or 3 5218 . rtol_0 - initial relative tolerance (0 <= rtol_0 < 1) 5219 . rtol_max - maximum relative tolerance (0 <= rtol_max < 1) 5220 . gamma - multiplicative factor for version 2 rtol computation (0 <= gamma2 <= 1) 5221 . alpha - power for version 2 rtol computation (1 < alpha <= 2) 5222 . alpha2 - power for safeguard 5223 - threshold - threshold for imposing safeguard (0 < threshold < 1) 5224 5225 Level: advanced 5226 5227 .keywords: SNES, KSP, Eisenstat, Walker, get, parameters 5228 5229 .seealso: SNESKSPSetUseEW(), SNESKSPGetUseEW(), SNESKSPSetParametersEW() 5230 @*/ 5231 PetscErrorCode SNESKSPGetParametersEW(SNES snes,PetscInt *version,PetscReal *rtol_0,PetscReal *rtol_max,PetscReal *gamma,PetscReal *alpha,PetscReal *alpha2,PetscReal *threshold) 5232 { 5233 SNESKSPEW *kctx; 5234 5235 PetscFunctionBegin; 5236 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 5237 kctx = (SNESKSPEW*)snes->kspconvctx; 5238 if (!kctx) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"No Eisenstat-Walker context existing"); 5239 if (version) *version = kctx->version; 5240 if (rtol_0) *rtol_0 = kctx->rtol_0; 5241 if (rtol_max) *rtol_max = kctx->rtol_max; 5242 if (gamma) *gamma = kctx->gamma; 5243 if (alpha) *alpha = kctx->alpha; 5244 if (alpha2) *alpha2 = kctx->alpha2; 5245 if (threshold) *threshold = kctx->threshold; 5246 PetscFunctionReturn(0); 5247 } 5248 5249 PetscErrorCode KSPPreSolve_SNESEW(KSP ksp, Vec b, Vec x, SNES snes) 5250 { 5251 PetscErrorCode ierr; 5252 SNESKSPEW *kctx = (SNESKSPEW*)snes->kspconvctx; 5253 PetscReal rtol = PETSC_DEFAULT,stol; 5254 5255 PetscFunctionBegin; 5256 if (!snes->ksp_ewconv) PetscFunctionReturn(0); 5257 if (!snes->iter) { 5258 rtol = kctx->rtol_0; /* first time in, so use the original user rtol */ 5259 ierr = VecNorm(snes->vec_func,NORM_2,&kctx->norm_first);CHKERRQ(ierr); 5260 } 5261 else { 5262 if (kctx->version == 1) { 5263 rtol = (snes->norm - kctx->lresid_last)/kctx->norm_last; 5264 if (rtol < 0.0) rtol = -rtol; 5265 stol = PetscPowReal(kctx->rtol_last,kctx->alpha2); 5266 if (stol > kctx->threshold) rtol = PetscMax(rtol,stol); 5267 } else if (kctx->version == 2) { 5268 rtol = kctx->gamma * PetscPowReal(snes->norm/kctx->norm_last,kctx->alpha); 5269 stol = kctx->gamma * PetscPowReal(kctx->rtol_last,kctx->alpha); 5270 if (stol > kctx->threshold) rtol = PetscMax(rtol,stol); 5271 } else if (kctx->version == 3) { /* contributed by Luis Chacon, June 2006. */ 5272 rtol = kctx->gamma * PetscPowReal(snes->norm/kctx->norm_last,kctx->alpha); 5273 /* safeguard: avoid sharp decrease of rtol */ 5274 stol = kctx->gamma*PetscPowReal(kctx->rtol_last,kctx->alpha); 5275 stol = PetscMax(rtol,stol); 5276 rtol = PetscMin(kctx->rtol_0,stol); 5277 /* safeguard: avoid oversolving */ 5278 stol = kctx->gamma*(kctx->norm_first*snes->rtol)/snes->norm; 5279 stol = PetscMax(rtol,stol); 5280 rtol = PetscMin(kctx->rtol_0,stol); 5281 } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Only versions 1, 2 or 3 are supported: %D",kctx->version); 5282 } 5283 /* safeguard: avoid rtol greater than one */ 5284 rtol = PetscMin(rtol,kctx->rtol_max); 5285 ierr = KSPSetTolerances(ksp,rtol,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT);CHKERRQ(ierr); 5286 ierr = PetscInfo3(snes,"iter %D, Eisenstat-Walker (version %D) KSP rtol=%g\n",snes->iter,kctx->version,(double)rtol);CHKERRQ(ierr); 5287 PetscFunctionReturn(0); 5288 } 5289 5290 PetscErrorCode KSPPostSolve_SNESEW(KSP ksp, Vec b, Vec x, SNES snes) 5291 { 5292 PetscErrorCode ierr; 5293 SNESKSPEW *kctx = (SNESKSPEW*)snes->kspconvctx; 5294 PCSide pcside; 5295 Vec lres; 5296 5297 PetscFunctionBegin; 5298 if (!snes->ksp_ewconv) PetscFunctionReturn(0); 5299 ierr = KSPGetTolerances(ksp,&kctx->rtol_last,0,0,0);CHKERRQ(ierr); 5300 kctx->norm_last = snes->norm; 5301 if (kctx->version == 1) { 5302 PC pc; 5303 PetscBool isNone; 5304 5305 ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr); 5306 ierr = PetscObjectTypeCompare((PetscObject) pc, PCNONE, &isNone);CHKERRQ(ierr); 5307 ierr = KSPGetPCSide(ksp,&pcside);CHKERRQ(ierr); 5308 if (pcside == PC_RIGHT || isNone) { /* XXX Should we also test KSP_UNPRECONDITIONED_NORM ? */ 5309 /* KSP residual is true linear residual */ 5310 ierr = KSPGetResidualNorm(ksp,&kctx->lresid_last);CHKERRQ(ierr); 5311 } else { 5312 /* KSP residual is preconditioned residual */ 5313 /* compute true linear residual norm */ 5314 ierr = VecDuplicate(b,&lres);CHKERRQ(ierr); 5315 ierr = MatMult(snes->jacobian,x,lres);CHKERRQ(ierr); 5316 ierr = VecAYPX(lres,-1.0,b);CHKERRQ(ierr); 5317 ierr = VecNorm(lres,NORM_2,&kctx->lresid_last);CHKERRQ(ierr); 5318 ierr = VecDestroy(&lres);CHKERRQ(ierr); 5319 } 5320 } 5321 PetscFunctionReturn(0); 5322 } 5323 5324 /*@ 5325 SNESGetKSP - Returns the KSP context for a SNES solver. 5326 5327 Not Collective, but if SNES object is parallel, then KSP object is parallel 5328 5329 Input Parameter: 5330 . snes - the SNES context 5331 5332 Output Parameter: 5333 . ksp - the KSP context 5334 5335 Notes: 5336 The user can then directly manipulate the KSP context to set various 5337 options, etc. Likewise, the user can then extract and manipulate the 5338 PC contexts as well. 5339 5340 Level: beginner 5341 5342 .keywords: SNES, nonlinear, get, KSP, context 5343 5344 .seealso: KSPGetPC(), SNESCreate(), KSPCreate(), SNESSetKSP() 5345 @*/ 5346 PetscErrorCode SNESGetKSP(SNES snes,KSP *ksp) 5347 { 5348 PetscErrorCode ierr; 5349 5350 PetscFunctionBegin; 5351 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 5352 PetscValidPointer(ksp,2); 5353 5354 if (!snes->ksp) { 5355 PetscBool monitor = PETSC_FALSE; 5356 5357 ierr = KSPCreate(PetscObjectComm((PetscObject)snes),&snes->ksp);CHKERRQ(ierr); 5358 ierr = PetscObjectIncrementTabLevel((PetscObject)snes->ksp,(PetscObject)snes,1);CHKERRQ(ierr); 5359 ierr = PetscLogObjectParent((PetscObject)snes,(PetscObject)snes->ksp);CHKERRQ(ierr); 5360 5361 ierr = KSPSetPreSolve(snes->ksp,(PetscErrorCode (*)(KSP,Vec,Vec,void*))KSPPreSolve_SNESEW,snes);CHKERRQ(ierr); 5362 ierr = KSPSetPostSolve(snes->ksp,(PetscErrorCode (*)(KSP,Vec,Vec,void*))KSPPostSolve_SNESEW,snes);CHKERRQ(ierr); 5363 5364 ierr = PetscOptionsGetBool(((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-ksp_monitor_snes",&monitor,NULL);CHKERRQ(ierr); 5365 if (monitor) { 5366 ierr = KSPMonitorSet(snes->ksp,KSPMonitorSNES,snes,NULL);CHKERRQ(ierr); 5367 } 5368 monitor = PETSC_FALSE; 5369 ierr = PetscOptionsGetBool(((PetscObject)snes)->options,((PetscObject)snes)->prefix,"-ksp_monitor_snes_lg",&monitor,NULL);CHKERRQ(ierr); 5370 if (monitor) { 5371 PetscObject *objs; 5372 ierr = KSPMonitorSNESLGResidualNormCreate(PetscObjectComm((PetscObject)snes),NULL,NULL,PETSC_DECIDE,PETSC_DECIDE,600,600,&objs);CHKERRQ(ierr); 5373 objs[0] = (PetscObject) snes; 5374 ierr = KSPMonitorSet(snes->ksp,(PetscErrorCode (*)(KSP,PetscInt,PetscReal,void*))KSPMonitorSNESLGResidualNorm,objs,(PetscErrorCode (*)(void**))KSPMonitorSNESLGResidualNormDestroy);CHKERRQ(ierr); 5375 } 5376 ierr = PetscObjectSetOptions((PetscObject)snes->ksp,((PetscObject)snes)->options);CHKERRQ(ierr); 5377 } 5378 *ksp = snes->ksp; 5379 PetscFunctionReturn(0); 5380 } 5381 5382 5383 #include <petsc/private/dmimpl.h> 5384 /*@ 5385 SNESSetDM - Sets the DM that may be used by some nonlinear solvers or their underlying preconditioners 5386 5387 Logically Collective on SNES 5388 5389 Input Parameters: 5390 + snes - the nonlinear solver context 5391 - dm - the dm, cannot be NULL 5392 5393 Notes: 5394 A DM can only be used for solving one problem at a time because information about the problem is stored on the DM, 5395 even when not using interfaces like DMSNESSetFunction(). Use DMClone() to get a distinct DM when solving different 5396 problems using the same function space. 5397 5398 Level: intermediate 5399 5400 .seealso: SNESGetDM(), KSPSetDM(), KSPGetDM() 5401 @*/ 5402 PetscErrorCode SNESSetDM(SNES snes,DM dm) 5403 { 5404 PetscErrorCode ierr; 5405 KSP ksp; 5406 DMSNES sdm; 5407 5408 PetscFunctionBegin; 5409 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 5410 PetscValidHeaderSpecific(dm,DM_CLASSID,2); 5411 ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr); 5412 if (snes->dm) { /* Move the DMSNES context over to the new DM unless the new DM already has one */ 5413 if (snes->dm->dmsnes && !dm->dmsnes) { 5414 ierr = DMCopyDMSNES(snes->dm,dm);CHKERRQ(ierr); 5415 ierr = DMGetDMSNES(snes->dm,&sdm);CHKERRQ(ierr); 5416 if (sdm->originaldm == snes->dm) sdm->originaldm = dm; /* Grant write privileges to the replacement DM */ 5417 } 5418 ierr = DMCoarsenHookRemove(snes->dm,DMCoarsenHook_SNESVecSol,DMRestrictHook_SNESVecSol,snes);CHKERRQ(ierr); 5419 ierr = DMDestroy(&snes->dm);CHKERRQ(ierr); 5420 } 5421 snes->dm = dm; 5422 snes->dmAuto = PETSC_FALSE; 5423 5424 ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr); 5425 ierr = KSPSetDM(ksp,dm);CHKERRQ(ierr); 5426 ierr = KSPSetDMActive(ksp,PETSC_FALSE);CHKERRQ(ierr); 5427 if (snes->npc) { 5428 ierr = SNESSetDM(snes->npc, snes->dm);CHKERRQ(ierr); 5429 ierr = SNESSetNPCSide(snes,snes->npcside);CHKERRQ(ierr); 5430 } 5431 PetscFunctionReturn(0); 5432 } 5433 5434 /*@ 5435 SNESGetDM - Gets the DM that may be used by some preconditioners 5436 5437 Not Collective but DM obtained is parallel on SNES 5438 5439 Input Parameter: 5440 . snes - the preconditioner context 5441 5442 Output Parameter: 5443 . dm - the dm 5444 5445 Level: intermediate 5446 5447 .seealso: SNESSetDM(), KSPSetDM(), KSPGetDM() 5448 @*/ 5449 PetscErrorCode SNESGetDM(SNES snes,DM *dm) 5450 { 5451 PetscErrorCode ierr; 5452 5453 PetscFunctionBegin; 5454 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 5455 if (!snes->dm) { 5456 ierr = DMShellCreate(PetscObjectComm((PetscObject)snes),&snes->dm);CHKERRQ(ierr); 5457 snes->dmAuto = PETSC_TRUE; 5458 } 5459 *dm = snes->dm; 5460 PetscFunctionReturn(0); 5461 } 5462 5463 /*@ 5464 SNESSetNPC - Sets the nonlinear preconditioner to be used. 5465 5466 Collective on SNES 5467 5468 Input Parameters: 5469 + snes - iterative context obtained from SNESCreate() 5470 - pc - the preconditioner object 5471 5472 Notes: 5473 Use SNESGetNPC() to retrieve the preconditioner context (for example, 5474 to configure it using the API). 5475 5476 Level: developer 5477 5478 .keywords: SNES, set, precondition 5479 .seealso: SNESGetNPC(), SNESHasNPC() 5480 @*/ 5481 PetscErrorCode SNESSetNPC(SNES snes, SNES pc) 5482 { 5483 PetscErrorCode ierr; 5484 5485 PetscFunctionBegin; 5486 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5487 PetscValidHeaderSpecific(pc, SNES_CLASSID, 2); 5488 PetscCheckSameComm(snes, 1, pc, 2); 5489 ierr = PetscObjectReference((PetscObject) pc);CHKERRQ(ierr); 5490 ierr = SNESDestroy(&snes->npc);CHKERRQ(ierr); 5491 snes->npc = pc; 5492 ierr = PetscLogObjectParent((PetscObject)snes, (PetscObject)snes->npc);CHKERRQ(ierr); 5493 PetscFunctionReturn(0); 5494 } 5495 5496 /*@ 5497 SNESGetNPC - Creates a nonlinear preconditioning solver (SNES) to be used to precondition the nonlinear solver. 5498 5499 Not Collective; but any changes to the obtained SNES object must be applied collectively 5500 5501 Input Parameter: 5502 . snes - iterative context obtained from SNESCreate() 5503 5504 Output Parameter: 5505 . pc - preconditioner context 5506 5507 Notes: 5508 If a SNES was previously set with SNESSetNPC() then that SNES is returned. 5509 5510 The (preconditioner) SNES returned automatically inherits the same nonlinear function and Jacobian supplied to the original 5511 SNES during SNESSetUp() 5512 5513 Level: developer 5514 5515 .keywords: SNES, get, preconditioner 5516 .seealso: SNESSetNPC(), SNESHasNPC(), SNES, SNESCreate() 5517 @*/ 5518 PetscErrorCode SNESGetNPC(SNES snes, SNES *pc) 5519 { 5520 PetscErrorCode ierr; 5521 const char *optionsprefix; 5522 5523 PetscFunctionBegin; 5524 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5525 PetscValidPointer(pc, 2); 5526 if (!snes->npc) { 5527 ierr = SNESCreate(PetscObjectComm((PetscObject)snes),&snes->npc);CHKERRQ(ierr); 5528 ierr = PetscObjectIncrementTabLevel((PetscObject)snes->npc,(PetscObject)snes,1);CHKERRQ(ierr); 5529 ierr = PetscLogObjectParent((PetscObject)snes,(PetscObject)snes->npc);CHKERRQ(ierr); 5530 ierr = SNESGetOptionsPrefix(snes,&optionsprefix);CHKERRQ(ierr); 5531 ierr = SNESSetOptionsPrefix(snes->npc,optionsprefix);CHKERRQ(ierr); 5532 ierr = SNESAppendOptionsPrefix(snes->npc,"npc_");CHKERRQ(ierr); 5533 ierr = SNESSetCountersReset(snes->npc,PETSC_FALSE);CHKERRQ(ierr); 5534 } 5535 *pc = snes->npc; 5536 PetscFunctionReturn(0); 5537 } 5538 5539 /*@ 5540 SNESHasNPC - Returns whether a nonlinear preconditioner exists 5541 5542 Not Collective 5543 5544 Input Parameter: 5545 . snes - iterative context obtained from SNESCreate() 5546 5547 Output Parameter: 5548 . has_npc - whether the SNES has an NPC or not 5549 5550 Level: developer 5551 5552 .keywords: SNES, has, preconditioner 5553 .seealso: SNESSetNPC(), SNESGetNPC() 5554 @*/ 5555 PetscErrorCode SNESHasNPC(SNES snes, PetscBool *has_npc) 5556 { 5557 PetscFunctionBegin; 5558 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5559 *has_npc = (PetscBool) (snes->npc ? PETSC_TRUE : PETSC_FALSE); 5560 PetscFunctionReturn(0); 5561 } 5562 5563 /*@ 5564 SNESSetNPCSide - Sets the preconditioning side. 5565 5566 Logically Collective on SNES 5567 5568 Input Parameter: 5569 . snes - iterative context obtained from SNESCreate() 5570 5571 Output Parameter: 5572 . side - the preconditioning side, where side is one of 5573 .vb 5574 PC_LEFT - left preconditioning 5575 PC_RIGHT - right preconditioning (default for most nonlinear solvers) 5576 .ve 5577 5578 Options Database Keys: 5579 . -snes_pc_side <right,left> 5580 5581 Notes: 5582 SNESNRICHARDSON and SNESNCG only support left preconditioning. 5583 5584 Level: intermediate 5585 5586 .keywords: SNES, set, right, left, side, preconditioner, flag 5587 5588 .seealso: SNESGetNPCSide(), KSPSetPCSide() 5589 @*/ 5590 PetscErrorCode SNESSetNPCSide(SNES snes,PCSide side) 5591 { 5592 PetscFunctionBegin; 5593 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 5594 PetscValidLogicalCollectiveEnum(snes,side,2); 5595 snes->npcside= side; 5596 PetscFunctionReturn(0); 5597 } 5598 5599 /*@ 5600 SNESGetNPCSide - Gets the preconditioning side. 5601 5602 Not Collective 5603 5604 Input Parameter: 5605 . snes - iterative context obtained from SNESCreate() 5606 5607 Output Parameter: 5608 . side - the preconditioning side, where side is one of 5609 .vb 5610 PC_LEFT - left preconditioning 5611 PC_RIGHT - right preconditioning (default for most nonlinear solvers) 5612 .ve 5613 5614 Level: intermediate 5615 5616 .keywords: SNES, get, right, left, side, preconditioner, flag 5617 5618 .seealso: SNESSetNPCSide(), KSPGetPCSide() 5619 @*/ 5620 PetscErrorCode SNESGetNPCSide(SNES snes,PCSide *side) 5621 { 5622 PetscFunctionBegin; 5623 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 5624 PetscValidPointer(side,2); 5625 *side = snes->npcside; 5626 PetscFunctionReturn(0); 5627 } 5628 5629 /*@ 5630 SNESSetLineSearch - Sets the linesearch on the SNES instance. 5631 5632 Collective on SNES 5633 5634 Input Parameters: 5635 + snes - iterative context obtained from SNESCreate() 5636 - linesearch - the linesearch object 5637 5638 Notes: 5639 Use SNESGetLineSearch() to retrieve the preconditioner context (for example, 5640 to configure it using the API). 5641 5642 Level: developer 5643 5644 .keywords: SNES, set, linesearch 5645 .seealso: SNESGetLineSearch() 5646 @*/ 5647 PetscErrorCode SNESSetLineSearch(SNES snes, SNESLineSearch linesearch) 5648 { 5649 PetscErrorCode ierr; 5650 5651 PetscFunctionBegin; 5652 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5653 PetscValidHeaderSpecific(linesearch, SNESLINESEARCH_CLASSID, 2); 5654 PetscCheckSameComm(snes, 1, linesearch, 2); 5655 ierr = PetscObjectReference((PetscObject) linesearch);CHKERRQ(ierr); 5656 ierr = SNESLineSearchDestroy(&snes->linesearch);CHKERRQ(ierr); 5657 5658 snes->linesearch = linesearch; 5659 5660 ierr = PetscLogObjectParent((PetscObject)snes, (PetscObject)snes->linesearch);CHKERRQ(ierr); 5661 PetscFunctionReturn(0); 5662 } 5663 5664 /*@ 5665 SNESGetLineSearch - Returns a pointer to the line search context set with SNESSetLineSearch() 5666 or creates a default line search instance associated with the SNES and returns it. 5667 5668 Not Collective 5669 5670 Input Parameter: 5671 . snes - iterative context obtained from SNESCreate() 5672 5673 Output Parameter: 5674 . linesearch - linesearch context 5675 5676 Level: beginner 5677 5678 .keywords: SNES, get, linesearch 5679 .seealso: SNESSetLineSearch(), SNESLineSearchCreate() 5680 @*/ 5681 PetscErrorCode SNESGetLineSearch(SNES snes, SNESLineSearch *linesearch) 5682 { 5683 PetscErrorCode ierr; 5684 const char *optionsprefix; 5685 5686 PetscFunctionBegin; 5687 PetscValidHeaderSpecific(snes, SNES_CLASSID, 1); 5688 PetscValidPointer(linesearch, 2); 5689 if (!snes->linesearch) { 5690 ierr = SNESGetOptionsPrefix(snes, &optionsprefix);CHKERRQ(ierr); 5691 ierr = SNESLineSearchCreate(PetscObjectComm((PetscObject)snes), &snes->linesearch);CHKERRQ(ierr); 5692 ierr = SNESLineSearchSetSNES(snes->linesearch, snes);CHKERRQ(ierr); 5693 ierr = SNESLineSearchAppendOptionsPrefix(snes->linesearch, optionsprefix);CHKERRQ(ierr); 5694 ierr = PetscObjectIncrementTabLevel((PetscObject) snes->linesearch, (PetscObject) snes, 1);CHKERRQ(ierr); 5695 ierr = PetscLogObjectParent((PetscObject)snes, (PetscObject)snes->linesearch);CHKERRQ(ierr); 5696 } 5697 *linesearch = snes->linesearch; 5698 PetscFunctionReturn(0); 5699 } 5700 5701 #if defined(PETSC_HAVE_MATLAB_ENGINE) 5702 #include <mex.h> 5703 5704 typedef struct {char *funcname; mxArray *ctx;} SNESMatlabContext; 5705 5706 /* 5707 SNESComputeFunction_Matlab - Calls the function that has been set with SNESSetFunctionMatlab(). 5708 5709 Collective on SNES 5710 5711 Input Parameters: 5712 + snes - the SNES context 5713 - x - input vector 5714 5715 Output Parameter: 5716 . y - function vector, as set by SNESSetFunction() 5717 5718 Notes: 5719 SNESComputeFunction() is typically used within nonlinear solvers 5720 implementations, so most users would not generally call this routine 5721 themselves. 5722 5723 Level: developer 5724 5725 .keywords: SNES, nonlinear, compute, function 5726 5727 .seealso: SNESSetFunction(), SNESGetFunction() 5728 */ 5729 PetscErrorCode SNESComputeFunction_Matlab(SNES snes,Vec x,Vec y, void *ctx) 5730 { 5731 PetscErrorCode ierr; 5732 SNESMatlabContext *sctx = (SNESMatlabContext*)ctx; 5733 int nlhs = 1,nrhs = 5; 5734 mxArray *plhs[1],*prhs[5]; 5735 long long int lx = 0,ly = 0,ls = 0; 5736 5737 PetscFunctionBegin; 5738 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 5739 PetscValidHeaderSpecific(x,VEC_CLASSID,2); 5740 PetscValidHeaderSpecific(y,VEC_CLASSID,3); 5741 PetscCheckSameComm(snes,1,x,2); 5742 PetscCheckSameComm(snes,1,y,3); 5743 5744 /* call Matlab function in ctx with arguments x and y */ 5745 5746 ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr); 5747 ierr = PetscMemcpy(&lx,&x,sizeof(x));CHKERRQ(ierr); 5748 ierr = PetscMemcpy(&ly,&y,sizeof(x));CHKERRQ(ierr); 5749 prhs[0] = mxCreateDoubleScalar((double)ls); 5750 prhs[1] = mxCreateDoubleScalar((double)lx); 5751 prhs[2] = mxCreateDoubleScalar((double)ly); 5752 prhs[3] = mxCreateString(sctx->funcname); 5753 prhs[4] = sctx->ctx; 5754 ierr = mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESComputeFunctionInternal");CHKERRQ(ierr); 5755 ierr = mxGetScalar(plhs[0]);CHKERRQ(ierr); 5756 mxDestroyArray(prhs[0]); 5757 mxDestroyArray(prhs[1]); 5758 mxDestroyArray(prhs[2]); 5759 mxDestroyArray(prhs[3]); 5760 mxDestroyArray(plhs[0]); 5761 PetscFunctionReturn(0); 5762 } 5763 5764 /* 5765 SNESSetFunctionMatlab - Sets the function evaluation routine and function 5766 vector for use by the SNES routines in solving systems of nonlinear 5767 equations from MATLAB. Here the function is a string containing the name of a MATLAB function 5768 5769 Logically Collective on SNES 5770 5771 Input Parameters: 5772 + snes - the SNES context 5773 . r - vector to store function value 5774 - f - function evaluation routine 5775 5776 Notes: 5777 The Newton-like methods typically solve linear systems of the form 5778 $ f'(x) x = -f(x), 5779 where f'(x) denotes the Jacobian matrix and f(x) is the function. 5780 5781 Level: beginner 5782 5783 Developer Note: This bleeds the allocated memory SNESMatlabContext *sctx; 5784 5785 .keywords: SNES, nonlinear, set, function 5786 5787 .seealso: SNESGetFunction(), SNESComputeFunction(), SNESSetJacobian(), SNESSetFunction() 5788 */ 5789 PetscErrorCode SNESSetFunctionMatlab(SNES snes,Vec r,const char *f,mxArray *ctx) 5790 { 5791 PetscErrorCode ierr; 5792 SNESMatlabContext *sctx; 5793 5794 PetscFunctionBegin; 5795 /* currently sctx is memory bleed */ 5796 ierr = PetscNew(&sctx);CHKERRQ(ierr); 5797 ierr = PetscStrallocpy(f,&sctx->funcname);CHKERRQ(ierr); 5798 /* 5799 This should work, but it doesn't 5800 sctx->ctx = ctx; 5801 mexMakeArrayPersistent(sctx->ctx); 5802 */ 5803 sctx->ctx = mxDuplicateArray(ctx); 5804 ierr = SNESSetFunction(snes,r,SNESComputeFunction_Matlab,sctx);CHKERRQ(ierr); 5805 PetscFunctionReturn(0); 5806 } 5807 5808 /* 5809 SNESComputeJacobian_Matlab - Calls the function that has been set with SNESSetJacobianMatlab(). 5810 5811 Collective on SNES 5812 5813 Input Parameters: 5814 + snes - the SNES context 5815 . x - input vector 5816 . A, B - the matrices 5817 - ctx - user context 5818 5819 Level: developer 5820 5821 .keywords: SNES, nonlinear, compute, function 5822 5823 .seealso: SNESSetFunction(), SNESGetFunction() 5824 @*/ 5825 PetscErrorCode SNESComputeJacobian_Matlab(SNES snes,Vec x,Mat A,Mat B,void *ctx) 5826 { 5827 PetscErrorCode ierr; 5828 SNESMatlabContext *sctx = (SNESMatlabContext*)ctx; 5829 int nlhs = 2,nrhs = 6; 5830 mxArray *plhs[2],*prhs[6]; 5831 long long int lx = 0,lA = 0,ls = 0, lB = 0; 5832 5833 PetscFunctionBegin; 5834 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 5835 PetscValidHeaderSpecific(x,VEC_CLASSID,2); 5836 5837 /* call Matlab function in ctx with arguments x and y */ 5838 5839 ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr); 5840 ierr = PetscMemcpy(&lx,&x,sizeof(x));CHKERRQ(ierr); 5841 ierr = PetscMemcpy(&lA,A,sizeof(x));CHKERRQ(ierr); 5842 ierr = PetscMemcpy(&lB,B,sizeof(x));CHKERRQ(ierr); 5843 prhs[0] = mxCreateDoubleScalar((double)ls); 5844 prhs[1] = mxCreateDoubleScalar((double)lx); 5845 prhs[2] = mxCreateDoubleScalar((double)lA); 5846 prhs[3] = mxCreateDoubleScalar((double)lB); 5847 prhs[4] = mxCreateString(sctx->funcname); 5848 prhs[5] = sctx->ctx; 5849 ierr = mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESComputeJacobianInternal");CHKERRQ(ierr); 5850 ierr = mxGetScalar(plhs[0]);CHKERRQ(ierr); 5851 mxDestroyArray(prhs[0]); 5852 mxDestroyArray(prhs[1]); 5853 mxDestroyArray(prhs[2]); 5854 mxDestroyArray(prhs[3]); 5855 mxDestroyArray(prhs[4]); 5856 mxDestroyArray(plhs[0]); 5857 mxDestroyArray(plhs[1]); 5858 PetscFunctionReturn(0); 5859 } 5860 5861 /* 5862 SNESSetJacobianMatlab - Sets the Jacobian function evaluation routine and two empty Jacobian matrices 5863 vector for use by the SNES routines in solving systems of nonlinear 5864 equations from MATLAB. Here the function is a string containing the name of a MATLAB function 5865 5866 Logically Collective on SNES 5867 5868 Input Parameters: 5869 + snes - the SNES context 5870 . A,B - Jacobian matrices 5871 . J - function evaluation routine 5872 - ctx - user context 5873 5874 Level: developer 5875 5876 Developer Note: This bleeds the allocated memory SNESMatlabContext *sctx; 5877 5878 .keywords: SNES, nonlinear, set, function 5879 5880 .seealso: SNESGetFunction(), SNESComputeFunction(), SNESSetJacobian(), SNESSetFunction(), J 5881 */ 5882 PetscErrorCode SNESSetJacobianMatlab(SNES snes,Mat A,Mat B,const char *J,mxArray *ctx) 5883 { 5884 PetscErrorCode ierr; 5885 SNESMatlabContext *sctx; 5886 5887 PetscFunctionBegin; 5888 /* currently sctx is memory bleed */ 5889 ierr = PetscNew(&sctx);CHKERRQ(ierr); 5890 ierr = PetscStrallocpy(J,&sctx->funcname);CHKERRQ(ierr); 5891 /* 5892 This should work, but it doesn't 5893 sctx->ctx = ctx; 5894 mexMakeArrayPersistent(sctx->ctx); 5895 */ 5896 sctx->ctx = mxDuplicateArray(ctx); 5897 ierr = SNESSetJacobian(snes,A,B,SNESComputeJacobian_Matlab,sctx);CHKERRQ(ierr); 5898 PetscFunctionReturn(0); 5899 } 5900 5901 /* 5902 SNESMonitor_Matlab - Calls the function that has been set with SNESMonitorSetMatlab(). 5903 5904 Collective on SNES 5905 5906 .seealso: SNESSetFunction(), SNESGetFunction() 5907 @*/ 5908 PetscErrorCode SNESMonitor_Matlab(SNES snes,PetscInt it, PetscReal fnorm, void *ctx) 5909 { 5910 PetscErrorCode ierr; 5911 SNESMatlabContext *sctx = (SNESMatlabContext*)ctx; 5912 int nlhs = 1,nrhs = 6; 5913 mxArray *plhs[1],*prhs[6]; 5914 long long int lx = 0,ls = 0; 5915 Vec x = snes->vec_sol; 5916 5917 PetscFunctionBegin; 5918 PetscValidHeaderSpecific(snes,SNES_CLASSID,1); 5919 5920 ierr = PetscMemcpy(&ls,&snes,sizeof(snes));CHKERRQ(ierr); 5921 ierr = PetscMemcpy(&lx,&x,sizeof(x));CHKERRQ(ierr); 5922 prhs[0] = mxCreateDoubleScalar((double)ls); 5923 prhs[1] = mxCreateDoubleScalar((double)it); 5924 prhs[2] = mxCreateDoubleScalar((double)fnorm); 5925 prhs[3] = mxCreateDoubleScalar((double)lx); 5926 prhs[4] = mxCreateString(sctx->funcname); 5927 prhs[5] = sctx->ctx; 5928 ierr = mexCallMATLAB(nlhs,plhs,nrhs,prhs,"PetscSNESMonitorInternal");CHKERRQ(ierr); 5929 ierr = mxGetScalar(plhs[0]);CHKERRQ(ierr); 5930 mxDestroyArray(prhs[0]); 5931 mxDestroyArray(prhs[1]); 5932 mxDestroyArray(prhs[2]); 5933 mxDestroyArray(prhs[3]); 5934 mxDestroyArray(prhs[4]); 5935 mxDestroyArray(plhs[0]); 5936 PetscFunctionReturn(0); 5937 } 5938 5939 /* 5940 SNESMonitorSetMatlab - Sets the monitor function from MATLAB 5941 5942 Level: developer 5943 5944 Developer Note: This bleeds the allocated memory SNESMatlabContext *sctx; 5945 5946 .keywords: SNES, nonlinear, set, function 5947 5948 .seealso: SNESGetFunction(), SNESComputeFunction(), SNESSetJacobian(), SNESSetFunction() 5949 */ 5950 PetscErrorCode SNESMonitorSetMatlab(SNES snes,const char *f,mxArray *ctx) 5951 { 5952 PetscErrorCode ierr; 5953 SNESMatlabContext *sctx; 5954 5955 PetscFunctionBegin; 5956 /* currently sctx is memory bleed */ 5957 ierr = PetscNew(&sctx);CHKERRQ(ierr); 5958 ierr = PetscStrallocpy(f,&sctx->funcname);CHKERRQ(ierr); 5959 /* 5960 This should work, but it doesn't 5961 sctx->ctx = ctx; 5962 mexMakeArrayPersistent(sctx->ctx); 5963 */ 5964 sctx->ctx = mxDuplicateArray(ctx); 5965 ierr = SNESMonitorSet(snes,SNESMonitor_Matlab,sctx,NULL);CHKERRQ(ierr); 5966 PetscFunctionReturn(0); 5967 } 5968 5969 #endif 5970