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