1 static char help[] = "Newton methods to solve u'' + u^{2} = f in parallel.\n\ 2 This example employs a user-defined monitoring routine and optionally a user-defined\n\ 3 routine to check candidate iterates produced by line search routines.\n\ 4 The command line options include:\n\ 5 -pre_check_iterates : activate checking of iterates\n\ 6 -post_check_iterates : activate checking of iterates\n\ 7 -check_tol <tol>: set tolerance for iterate checking\n\ 8 -user_precond : activate a (trivial) user-defined preconditioner\n\n"; 9 10 /*T 11 Concepts: SNES^basic parallel example 12 Concepts: SNES^setting a user-defined monitoring routine 13 Processors: n 14 T*/ 15 16 17 18 /* 19 Include "petscdm.h" so that we can use data management objects (DMs) 20 Include "petscdmda.h" so that we can use distributed arrays (DMDAs). 21 Include "petscsnes.h" so that we can use SNES solvers. Note that this 22 file automatically includes: 23 petscsys.h - base PETSc routines 24 petscvec.h - vectors 25 petscmat.h - matrices 26 petscis.h - index sets 27 petscksp.h - Krylov subspace methods 28 petscviewer.h - viewers 29 petscpc.h - preconditioners 30 petscksp.h - linear solvers 31 */ 32 33 #include <petscdm.h> 34 #include <petscdmda.h> 35 #include <petscsnes.h> 36 37 /* 38 User-defined routines. 39 */ 40 PetscErrorCode FormJacobian(SNES,Vec,Mat,Mat,void*); 41 PetscErrorCode FormFunction(SNES,Vec,Vec,void*); 42 PetscErrorCode FormInitialGuess(Vec); 43 PetscErrorCode Monitor(SNES,PetscInt,PetscReal,void*); 44 PetscErrorCode PreCheck(SNESLineSearch,Vec,Vec,PetscBool*,void*); 45 PetscErrorCode PostCheck(SNESLineSearch,Vec,Vec,Vec,PetscBool*,PetscBool*,void*); 46 PetscErrorCode PostSetSubKSP(SNESLineSearch,Vec,Vec,Vec,PetscBool*,PetscBool*,void*); 47 PetscErrorCode MatrixFreePreconditioner(PC,Vec,Vec); 48 49 /* 50 User-defined application context 51 */ 52 typedef struct { 53 DM da; /* distributed array */ 54 Vec F; /* right-hand-side of PDE */ 55 PetscMPIInt rank; /* rank of processor */ 56 PetscMPIInt size; /* size of communicator */ 57 PetscReal h; /* mesh spacing */ 58 PetscBool sjerr; /* if or not to test jacobian domain error */ 59 } ApplicationCtx; 60 61 /* 62 User-defined context for monitoring 63 */ 64 typedef struct { 65 PetscViewer viewer; 66 } MonitorCtx; 67 68 /* 69 User-defined context for checking candidate iterates that are 70 determined by line search methods 71 */ 72 typedef struct { 73 Vec last_step; /* previous iterate */ 74 PetscReal tolerance; /* tolerance for changes between successive iterates */ 75 ApplicationCtx *user; 76 } StepCheckCtx; 77 78 typedef struct { 79 PetscInt its0; /* num of prevous outer KSP iterations */ 80 } SetSubKSPCtx; 81 82 int main(int argc,char **argv) 83 { 84 SNES snes; /* SNES context */ 85 SNESLineSearch linesearch; /* SNESLineSearch context */ 86 Mat J; /* Jacobian matrix */ 87 ApplicationCtx ctx; /* user-defined context */ 88 Vec x,r,U,F; /* vectors */ 89 MonitorCtx monP; /* monitoring context */ 90 StepCheckCtx checkP; /* step-checking context */ 91 SetSubKSPCtx checkP1; 92 PetscBool pre_check,post_check,post_setsubksp; /* flag indicating whether we're checking candidate iterates */ 93 PetscScalar xp,*FF,*UU,none = -1.0; 94 PetscErrorCode ierr; 95 PetscInt its,N = 5,i,maxit,maxf,xs,xm; 96 PetscReal abstol,rtol,stol,norm; 97 PetscBool flg,viewinitial = PETSC_FALSE; 98 99 100 ierr = PetscInitialize(&argc,&argv,(char*)0,help);if (ierr) return ierr; 101 ierr = MPI_Comm_rank(PETSC_COMM_WORLD,&ctx.rank);CHKERRMPI(ierr); 102 ierr = MPI_Comm_size(PETSC_COMM_WORLD,&ctx.size);CHKERRMPI(ierr); 103 ierr = PetscOptionsGetInt(NULL,NULL,"-n",&N,NULL);CHKERRQ(ierr); 104 ctx.h = 1.0/(N-1); 105 ctx.sjerr = PETSC_FALSE; 106 ierr = PetscOptionsGetBool(NULL,NULL,"-test_jacobian_domain_error",&ctx.sjerr,NULL);CHKERRQ(ierr); 107 ierr = PetscOptionsGetBool(NULL,NULL,"-view_initial",&viewinitial,NULL);CHKERRQ(ierr); 108 109 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 110 Create nonlinear solver context 111 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 112 113 ierr = SNESCreate(PETSC_COMM_WORLD,&snes);CHKERRQ(ierr); 114 115 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 116 Create vector data structures; set function evaluation routine 117 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 118 119 /* 120 Create distributed array (DMDA) to manage parallel grid and vectors 121 */ 122 ierr = DMDACreate1d(PETSC_COMM_WORLD,DM_BOUNDARY_NONE,N,1,1,NULL,&ctx.da);CHKERRQ(ierr); 123 ierr = DMSetFromOptions(ctx.da);CHKERRQ(ierr); 124 ierr = DMSetUp(ctx.da);CHKERRQ(ierr); 125 126 /* 127 Extract global and local vectors from DMDA; then duplicate for remaining 128 vectors that are the same types 129 */ 130 ierr = DMCreateGlobalVector(ctx.da,&x);CHKERRQ(ierr); 131 ierr = VecDuplicate(x,&r);CHKERRQ(ierr); 132 ierr = VecDuplicate(x,&F);CHKERRQ(ierr); ctx.F = F; 133 ierr = VecDuplicate(x,&U);CHKERRQ(ierr); 134 135 /* 136 Set function evaluation routine and vector. Whenever the nonlinear 137 solver needs to compute the nonlinear function, it will call this 138 routine. 139 - Note that the final routine argument is the user-defined 140 context that provides application-specific data for the 141 function evaluation routine. 142 */ 143 ierr = SNESSetFunction(snes,r,FormFunction,&ctx);CHKERRQ(ierr); 144 145 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 146 Create matrix data structure; set Jacobian evaluation routine 147 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 148 149 ierr = MatCreate(PETSC_COMM_WORLD,&J);CHKERRQ(ierr); 150 ierr = MatSetSizes(J,PETSC_DECIDE,PETSC_DECIDE,N,N);CHKERRQ(ierr); 151 ierr = MatSetFromOptions(J);CHKERRQ(ierr); 152 ierr = MatSeqAIJSetPreallocation(J,3,NULL);CHKERRQ(ierr); 153 ierr = MatMPIAIJSetPreallocation(J,3,NULL,3,NULL);CHKERRQ(ierr); 154 155 /* 156 Set Jacobian matrix data structure and default Jacobian evaluation 157 routine. Whenever the nonlinear solver needs to compute the 158 Jacobian matrix, it will call this routine. 159 - Note that the final routine argument is the user-defined 160 context that provides application-specific data for the 161 Jacobian evaluation routine. 162 */ 163 ierr = SNESSetJacobian(snes,J,J,FormJacobian,&ctx);CHKERRQ(ierr); 164 165 /* 166 Optionally allow user-provided preconditioner 167 */ 168 ierr = PetscOptionsHasName(NULL,NULL,"-user_precond",&flg);CHKERRQ(ierr); 169 if (flg) { 170 KSP ksp; 171 PC pc; 172 ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr); 173 ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); 174 ierr = PCSetType(pc,PCSHELL);CHKERRQ(ierr); 175 ierr = PCShellSetApply(pc,MatrixFreePreconditioner);CHKERRQ(ierr); 176 } 177 178 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 179 Customize nonlinear solver; set runtime options 180 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 181 182 /* 183 Set an optional user-defined monitoring routine 184 */ 185 ierr = PetscViewerDrawOpen(PETSC_COMM_WORLD,0,0,0,0,400,400,&monP.viewer);CHKERRQ(ierr); 186 ierr = SNESMonitorSet(snes,Monitor,&monP,0);CHKERRQ(ierr); 187 188 /* 189 Set names for some vectors to facilitate monitoring (optional) 190 */ 191 ierr = PetscObjectSetName((PetscObject)x,"Approximate Solution");CHKERRQ(ierr); 192 ierr = PetscObjectSetName((PetscObject)U,"Exact Solution");CHKERRQ(ierr); 193 194 /* 195 Set SNES/KSP/KSP/PC runtime options, e.g., 196 -snes_view -snes_monitor -ksp_type <ksp> -pc_type <pc> 197 */ 198 ierr = SNESSetFromOptions(snes);CHKERRQ(ierr); 199 200 /* 201 Set an optional user-defined routine to check the validity of candidate 202 iterates that are determined by line search methods 203 */ 204 ierr = SNESGetLineSearch(snes, &linesearch);CHKERRQ(ierr); 205 ierr = PetscOptionsHasName(NULL,NULL,"-post_check_iterates",&post_check);CHKERRQ(ierr); 206 207 if (post_check) { 208 ierr = PetscPrintf(PETSC_COMM_WORLD,"Activating post step checking routine\n");CHKERRQ(ierr); 209 ierr = SNESLineSearchSetPostCheck(linesearch,PostCheck,&checkP);CHKERRQ(ierr); 210 ierr = VecDuplicate(x,&(checkP.last_step));CHKERRQ(ierr); 211 212 checkP.tolerance = 1.0; 213 checkP.user = &ctx; 214 215 ierr = PetscOptionsGetReal(NULL,NULL,"-check_tol",&checkP.tolerance,NULL);CHKERRQ(ierr); 216 } 217 218 ierr = PetscOptionsHasName(NULL,NULL,"-post_setsubksp",&post_setsubksp);CHKERRQ(ierr); 219 if (post_setsubksp) { 220 ierr = PetscPrintf(PETSC_COMM_WORLD,"Activating post setsubksp\n");CHKERRQ(ierr); 221 ierr = SNESLineSearchSetPostCheck(linesearch,PostSetSubKSP,&checkP1);CHKERRQ(ierr); 222 } 223 224 ierr = PetscOptionsHasName(NULL,NULL,"-pre_check_iterates",&pre_check);CHKERRQ(ierr); 225 if (pre_check) { 226 ierr = PetscPrintf(PETSC_COMM_WORLD,"Activating pre step checking routine\n");CHKERRQ(ierr); 227 ierr = SNESLineSearchSetPreCheck(linesearch,PreCheck,&checkP);CHKERRQ(ierr); 228 } 229 230 /* 231 Print parameters used for convergence testing (optional) ... just 232 to demonstrate this routine; this information is also printed with 233 the option -snes_view 234 */ 235 ierr = SNESGetTolerances(snes,&abstol,&rtol,&stol,&maxit,&maxf);CHKERRQ(ierr); 236 ierr = PetscPrintf(PETSC_COMM_WORLD,"atol=%g, rtol=%g, stol=%g, maxit=%D, maxf=%D\n",(double)abstol,(double)rtol,(double)stol,maxit,maxf);CHKERRQ(ierr); 237 238 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 239 Initialize application: 240 Store right-hand-side of PDE and exact solution 241 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 242 243 /* 244 Get local grid boundaries (for 1-dimensional DMDA): 245 xs, xm - starting grid index, width of local grid (no ghost points) 246 */ 247 ierr = DMDAGetCorners(ctx.da,&xs,NULL,NULL,&xm,NULL,NULL);CHKERRQ(ierr); 248 249 /* 250 Get pointers to vector data 251 */ 252 ierr = DMDAVecGetArray(ctx.da,F,&FF);CHKERRQ(ierr); 253 ierr = DMDAVecGetArray(ctx.da,U,&UU);CHKERRQ(ierr); 254 255 /* 256 Compute local vector entries 257 */ 258 xp = ctx.h*xs; 259 for (i=xs; i<xs+xm; i++) { 260 FF[i] = 6.0*xp + PetscPowScalar(xp+1.e-12,6.0); /* +1.e-12 is to prevent 0^6 */ 261 UU[i] = xp*xp*xp; 262 xp += ctx.h; 263 } 264 265 /* 266 Restore vectors 267 */ 268 ierr = DMDAVecRestoreArray(ctx.da,F,&FF);CHKERRQ(ierr); 269 ierr = DMDAVecRestoreArray(ctx.da,U,&UU);CHKERRQ(ierr); 270 if (viewinitial) { 271 ierr = VecView(U,0);CHKERRQ(ierr); 272 ierr = VecView(F,0);CHKERRQ(ierr); 273 } 274 275 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 276 Evaluate initial guess; then solve nonlinear system 277 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 278 279 /* 280 Note: The user should initialize the vector, x, with the initial guess 281 for the nonlinear solver prior to calling SNESSolve(). In particular, 282 to employ an initial guess of zero, the user should explicitly set 283 this vector to zero by calling VecSet(). 284 */ 285 ierr = FormInitialGuess(x);CHKERRQ(ierr); 286 ierr = SNESSolve(snes,NULL,x);CHKERRQ(ierr); 287 ierr = SNESGetIterationNumber(snes,&its);CHKERRQ(ierr); 288 ierr = PetscPrintf(PETSC_COMM_WORLD,"Number of SNES iterations = %D\n",its);CHKERRQ(ierr); 289 290 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 291 Check solution and clean up 292 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ 293 294 /* 295 Check the error 296 */ 297 ierr = VecAXPY(x,none,U);CHKERRQ(ierr); 298 ierr = VecNorm(x,NORM_2,&norm);CHKERRQ(ierr); 299 ierr = PetscPrintf(PETSC_COMM_WORLD,"Norm of error %g Iterations %D\n",(double)norm,its);CHKERRQ(ierr); 300 if (ctx.sjerr) { 301 SNESType snestype; 302 ierr = SNESGetType(snes,&snestype);CHKERRQ(ierr); 303 ierr = PetscPrintf(PETSC_COMM_WORLD,"SNES Type %s\n",snestype);CHKERRQ(ierr); 304 } 305 306 /* 307 Free work space. All PETSc objects should be destroyed when they 308 are no longer needed. 309 */ 310 ierr = PetscViewerDestroy(&monP.viewer);CHKERRQ(ierr); 311 if (post_check) {ierr = VecDestroy(&checkP.last_step);CHKERRQ(ierr);} 312 ierr = VecDestroy(&x);CHKERRQ(ierr); 313 ierr = VecDestroy(&r);CHKERRQ(ierr); 314 ierr = VecDestroy(&U);CHKERRQ(ierr); 315 ierr = VecDestroy(&F);CHKERRQ(ierr); 316 ierr = MatDestroy(&J);CHKERRQ(ierr); 317 ierr = SNESDestroy(&snes);CHKERRQ(ierr); 318 ierr = DMDestroy(&ctx.da);CHKERRQ(ierr); 319 ierr = PetscFinalize(); 320 return ierr; 321 } 322 323 /* ------------------------------------------------------------------- */ 324 /* 325 FormInitialGuess - Computes initial guess. 326 327 Input/Output Parameter: 328 . x - the solution vector 329 */ 330 PetscErrorCode FormInitialGuess(Vec x) 331 { 332 PetscErrorCode ierr; 333 PetscScalar pfive = .50; 334 335 PetscFunctionBeginUser; 336 ierr = VecSet(x,pfive);CHKERRQ(ierr); 337 PetscFunctionReturn(0); 338 } 339 340 /* ------------------------------------------------------------------- */ 341 /* 342 FormFunction - Evaluates nonlinear function, F(x). 343 344 Input Parameters: 345 . snes - the SNES context 346 . x - input vector 347 . ctx - optional user-defined context, as set by SNESSetFunction() 348 349 Output Parameter: 350 . f - function vector 351 352 Note: 353 The user-defined context can contain any application-specific 354 data needed for the function evaluation. 355 */ 356 PetscErrorCode FormFunction(SNES snes,Vec x,Vec f,void *ctx) 357 { 358 ApplicationCtx *user = (ApplicationCtx*) ctx; 359 DM da = user->da; 360 PetscScalar *xx,*ff,*FF,d; 361 PetscErrorCode ierr; 362 PetscInt i,M,xs,xm; 363 Vec xlocal; 364 365 PetscFunctionBeginUser; 366 ierr = DMGetLocalVector(da,&xlocal);CHKERRQ(ierr); 367 /* 368 Scatter ghost points to local vector, using the 2-step process 369 DMGlobalToLocalBegin(), DMGlobalToLocalEnd(). 370 By placing code between these two statements, computations can 371 be done while messages are in transition. 372 */ 373 ierr = DMGlobalToLocalBegin(da,x,INSERT_VALUES,xlocal);CHKERRQ(ierr); 374 ierr = DMGlobalToLocalEnd(da,x,INSERT_VALUES,xlocal);CHKERRQ(ierr); 375 376 /* 377 Get pointers to vector data. 378 - The vector xlocal includes ghost point; the vectors x and f do 379 NOT include ghost points. 380 - Using DMDAVecGetArray() allows accessing the values using global ordering 381 */ 382 ierr = DMDAVecGetArray(da,xlocal,&xx);CHKERRQ(ierr); 383 ierr = DMDAVecGetArray(da,f,&ff);CHKERRQ(ierr); 384 ierr = DMDAVecGetArray(da,user->F,&FF);CHKERRQ(ierr); 385 386 /* 387 Get local grid boundaries (for 1-dimensional DMDA): 388 xs, xm - starting grid index, width of local grid (no ghost points) 389 */ 390 ierr = DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL);CHKERRQ(ierr); 391 ierr = DMDAGetInfo(da,NULL,&M,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr); 392 393 /* 394 Set function values for boundary points; define local interior grid point range: 395 xsi - starting interior grid index 396 xei - ending interior grid index 397 */ 398 if (xs == 0) { /* left boundary */ 399 ff[0] = xx[0]; 400 xs++;xm--; 401 } 402 if (xs+xm == M) { /* right boundary */ 403 ff[xs+xm-1] = xx[xs+xm-1] - 1.0; 404 xm--; 405 } 406 407 /* 408 Compute function over locally owned part of the grid (interior points only) 409 */ 410 d = 1.0/(user->h*user->h); 411 for (i=xs; i<xs+xm; i++) ff[i] = d*(xx[i-1] - 2.0*xx[i] + xx[i+1]) + xx[i]*xx[i] - FF[i]; 412 413 /* 414 Restore vectors 415 */ 416 ierr = DMDAVecRestoreArray(da,xlocal,&xx);CHKERRQ(ierr); 417 ierr = DMDAVecRestoreArray(da,f,&ff);CHKERRQ(ierr); 418 ierr = DMDAVecRestoreArray(da,user->F,&FF);CHKERRQ(ierr); 419 ierr = DMRestoreLocalVector(da,&xlocal);CHKERRQ(ierr); 420 PetscFunctionReturn(0); 421 } 422 423 /* ------------------------------------------------------------------- */ 424 /* 425 FormJacobian - Evaluates Jacobian matrix. 426 427 Input Parameters: 428 . snes - the SNES context 429 . x - input vector 430 . dummy - optional user-defined context (not used here) 431 432 Output Parameters: 433 . jac - Jacobian matrix 434 . B - optionally different preconditioning matrix 435 . flag - flag indicating matrix structure 436 */ 437 PetscErrorCode FormJacobian(SNES snes,Vec x,Mat jac,Mat B,void *ctx) 438 { 439 ApplicationCtx *user = (ApplicationCtx*) ctx; 440 PetscScalar *xx,d,A[3]; 441 PetscErrorCode ierr; 442 PetscInt i,j[3],M,xs,xm; 443 DM da = user->da; 444 445 PetscFunctionBeginUser; 446 if (user->sjerr) { 447 ierr = SNESSetJacobianDomainError(snes);CHKERRQ(ierr); 448 PetscFunctionReturn(0); 449 } 450 /* 451 Get pointer to vector data 452 */ 453 ierr = DMDAVecGetArrayRead(da,x,&xx);CHKERRQ(ierr); 454 ierr = DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL);CHKERRQ(ierr); 455 456 /* 457 Get range of locally owned matrix 458 */ 459 ierr = DMDAGetInfo(da,NULL,&M,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr); 460 461 /* 462 Determine starting and ending local indices for interior grid points. 463 Set Jacobian entries for boundary points. 464 */ 465 466 if (xs == 0) { /* left boundary */ 467 i = 0; A[0] = 1.0; 468 469 ierr = MatSetValues(jac,1,&i,1,&i,A,INSERT_VALUES);CHKERRQ(ierr); 470 xs++;xm--; 471 } 472 if (xs+xm == M) { /* right boundary */ 473 i = M-1; 474 A[0] = 1.0; 475 ierr = MatSetValues(jac,1,&i,1,&i,A,INSERT_VALUES);CHKERRQ(ierr); 476 xm--; 477 } 478 479 /* 480 Interior grid points 481 - Note that in this case we set all elements for a particular 482 row at once. 483 */ 484 d = 1.0/(user->h*user->h); 485 for (i=xs; i<xs+xm; i++) { 486 j[0] = i - 1; j[1] = i; j[2] = i + 1; 487 A[0] = A[2] = d; A[1] = -2.0*d + 2.0*xx[i]; 488 ierr = MatSetValues(jac,1,&i,3,j,A,INSERT_VALUES);CHKERRQ(ierr); 489 } 490 491 /* 492 Assemble matrix, using the 2-step process: 493 MatAssemblyBegin(), MatAssemblyEnd(). 494 By placing code between these two statements, computations can be 495 done while messages are in transition. 496 497 Also, restore vector. 498 */ 499 500 ierr = MatAssemblyBegin(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 501 ierr = DMDAVecRestoreArrayRead(da,x,&xx);CHKERRQ(ierr); 502 ierr = MatAssemblyEnd(jac,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 503 504 PetscFunctionReturn(0); 505 } 506 507 /* ------------------------------------------------------------------- */ 508 /* 509 Monitor - Optional user-defined monitoring routine that views the 510 current iterate with an x-window plot. Set by SNESMonitorSet(). 511 512 Input Parameters: 513 snes - the SNES context 514 its - iteration number 515 norm - 2-norm function value (may be estimated) 516 ctx - optional user-defined context for private data for the 517 monitor routine, as set by SNESMonitorSet() 518 519 Note: 520 See the manpage for PetscViewerDrawOpen() for useful runtime options, 521 such as -nox to deactivate all x-window output. 522 */ 523 PetscErrorCode Monitor(SNES snes,PetscInt its,PetscReal fnorm,void *ctx) 524 { 525 PetscErrorCode ierr; 526 MonitorCtx *monP = (MonitorCtx*) ctx; 527 Vec x; 528 529 PetscFunctionBeginUser; 530 ierr = PetscPrintf(PETSC_COMM_WORLD,"iter = %D,SNES Function norm %g\n",its,(double)fnorm);CHKERRQ(ierr); 531 ierr = SNESGetSolution(snes,&x);CHKERRQ(ierr); 532 ierr = VecView(x,monP->viewer);CHKERRQ(ierr); 533 PetscFunctionReturn(0); 534 } 535 536 /* ------------------------------------------------------------------- */ 537 /* 538 PreCheck - Optional user-defined routine that checks the validity of 539 candidate steps of a line search method. Set by SNESLineSearchSetPreCheck(). 540 541 Input Parameters: 542 snes - the SNES context 543 xcurrent - current solution 544 y - search direction and length 545 546 Output Parameters: 547 y - proposed step (search direction and length) (possibly changed) 548 changed_y - tells if the step has changed or not 549 */ 550 PetscErrorCode PreCheck(SNESLineSearch linesearch,Vec xcurrent,Vec y, PetscBool *changed_y, void * ctx) 551 { 552 PetscFunctionBeginUser; 553 *changed_y = PETSC_FALSE; 554 PetscFunctionReturn(0); 555 } 556 557 /* ------------------------------------------------------------------- */ 558 /* 559 PostCheck - Optional user-defined routine that checks the validity of 560 candidate steps of a line search method. Set by SNESLineSearchSetPostCheck(). 561 562 Input Parameters: 563 snes - the SNES context 564 ctx - optional user-defined context for private data for the 565 monitor routine, as set by SNESLineSearchSetPostCheck() 566 xcurrent - current solution 567 y - search direction and length 568 x - the new candidate iterate 569 570 Output Parameters: 571 y - proposed step (search direction and length) (possibly changed) 572 x - current iterate (possibly modified) 573 574 */ 575 PetscErrorCode PostCheck(SNESLineSearch linesearch,Vec xcurrent,Vec y,Vec x,PetscBool *changed_y,PetscBool *changed_x, void * ctx) 576 { 577 PetscErrorCode ierr; 578 PetscInt i,iter,xs,xm; 579 StepCheckCtx *check; 580 ApplicationCtx *user; 581 PetscScalar *xa,*xa_last,tmp; 582 PetscReal rdiff; 583 DM da; 584 SNES snes; 585 586 PetscFunctionBeginUser; 587 *changed_x = PETSC_FALSE; 588 *changed_y = PETSC_FALSE; 589 590 ierr = SNESLineSearchGetSNES(linesearch, &snes);CHKERRQ(ierr); 591 check = (StepCheckCtx*)ctx; 592 user = check->user; 593 ierr = SNESGetIterationNumber(snes,&iter);CHKERRQ(ierr); 594 595 /* iteration 1 indicates we are working on the second iteration */ 596 if (iter > 0) { 597 da = user->da; 598 ierr = PetscPrintf(PETSC_COMM_WORLD,"Checking candidate step at iteration %D with tolerance %g\n",iter,(double)check->tolerance);CHKERRQ(ierr); 599 600 /* Access local array data */ 601 ierr = DMDAVecGetArray(da,check->last_step,&xa_last);CHKERRQ(ierr); 602 ierr = DMDAVecGetArray(da,x,&xa);CHKERRQ(ierr); 603 ierr = DMDAGetCorners(da,&xs,NULL,NULL,&xm,NULL,NULL);CHKERRQ(ierr); 604 605 /* 606 If we fail the user-defined check for validity of the candidate iterate, 607 then modify the iterate as we like. (Note that the particular modification 608 below is intended simply to demonstrate how to manipulate this data, not 609 as a meaningful or appropriate choice.) 610 */ 611 for (i=xs; i<xs+xm; i++) { 612 if (!PetscAbsScalar(xa[i])) rdiff = 2*check->tolerance; 613 else rdiff = PetscAbsScalar((xa[i] - xa_last[i])/xa[i]); 614 if (rdiff > check->tolerance) { 615 tmp = xa[i]; 616 xa[i] = .5*(xa[i] + xa_last[i]); 617 *changed_x = PETSC_TRUE; 618 ierr = PetscPrintf(PETSC_COMM_WORLD," Altering entry %D: x=%g, x_last=%g, diff=%g, x_new=%g\n",i,(double)PetscAbsScalar(tmp),(double)PetscAbsScalar(xa_last[i]),(double)rdiff,(double)PetscAbsScalar(xa[i]));CHKERRQ(ierr); 619 } 620 } 621 ierr = DMDAVecRestoreArray(da,check->last_step,&xa_last);CHKERRQ(ierr); 622 ierr = DMDAVecRestoreArray(da,x,&xa);CHKERRQ(ierr); 623 } 624 ierr = VecCopy(x,check->last_step);CHKERRQ(ierr); 625 PetscFunctionReturn(0); 626 } 627 628 /* ------------------------------------------------------------------- */ 629 /* 630 PostSetSubKSP - Optional user-defined routine that reset SubKSP options when hierarchical bjacobi PC is used 631 e.g, 632 mpiexec -n 8 ./ex3 -nox -n 10000 -ksp_type fgmres -pc_type bjacobi -pc_bjacobi_blocks 4 -sub_ksp_type gmres -sub_ksp_max_it 3 -post_setsubksp -sub_ksp_rtol 1.e-16 633 Set by SNESLineSearchSetPostCheck(). 634 635 Input Parameters: 636 linesearch - the LineSearch context 637 xcurrent - current solution 638 y - search direction and length 639 x - the new candidate iterate 640 641 Output Parameters: 642 y - proposed step (search direction and length) (possibly changed) 643 x - current iterate (possibly modified) 644 645 */ 646 PetscErrorCode PostSetSubKSP(SNESLineSearch linesearch,Vec xcurrent,Vec y,Vec x,PetscBool *changed_y,PetscBool *changed_x, void * ctx) 647 { 648 PetscErrorCode ierr; 649 SetSubKSPCtx *check; 650 PetscInt iter,its,sub_its,maxit; 651 KSP ksp,sub_ksp,*sub_ksps; 652 PC pc; 653 PetscReal ksp_ratio; 654 SNES snes; 655 656 PetscFunctionBeginUser; 657 ierr = SNESLineSearchGetSNES(linesearch, &snes);CHKERRQ(ierr); 658 check = (SetSubKSPCtx*)ctx; 659 ierr = SNESGetIterationNumber(snes,&iter);CHKERRQ(ierr); 660 ierr = SNESGetKSP(snes,&ksp);CHKERRQ(ierr); 661 ierr = KSPGetPC(ksp,&pc);CHKERRQ(ierr); 662 ierr = PCBJacobiGetSubKSP(pc,NULL,NULL,&sub_ksps);CHKERRQ(ierr); 663 sub_ksp = sub_ksps[0]; 664 ierr = KSPGetIterationNumber(ksp,&its);CHKERRQ(ierr); /* outer KSP iteration number */ 665 ierr = KSPGetIterationNumber(sub_ksp,&sub_its);CHKERRQ(ierr); /* inner KSP iteration number */ 666 667 if (iter) { 668 ierr = PetscPrintf(PETSC_COMM_WORLD," ...PostCheck snes iteration %D, ksp_it %D %D, subksp_it %D\n",iter,check->its0,its,sub_its);CHKERRQ(ierr); 669 ksp_ratio = ((PetscReal)(its))/check->its0; 670 maxit = (PetscInt)(ksp_ratio*sub_its + 0.5); 671 if (maxit < 2) maxit = 2; 672 ierr = KSPSetTolerances(sub_ksp,PETSC_DEFAULT,PETSC_DEFAULT,PETSC_DEFAULT,maxit);CHKERRQ(ierr); 673 ierr = PetscPrintf(PETSC_COMM_WORLD," ...ksp_ratio %g, new maxit %D\n\n",(double)ksp_ratio,maxit);CHKERRQ(ierr); 674 } 675 check->its0 = its; /* save current outer KSP iteration number */ 676 PetscFunctionReturn(0); 677 } 678 679 /* ------------------------------------------------------------------- */ 680 /* 681 MatrixFreePreconditioner - This routine demonstrates the use of a 682 user-provided preconditioner. This code implements just the null 683 preconditioner, which of course is not recommended for general use. 684 685 Input Parameters: 686 + pc - preconditioner 687 - x - input vector 688 689 Output Parameter: 690 . y - preconditioned vector 691 */ 692 PetscErrorCode MatrixFreePreconditioner(PC pc,Vec x,Vec y) 693 { 694 PetscErrorCode ierr; 695 ierr = VecCopy(x,y);CHKERRQ(ierr); 696 return 0; 697 } 698 699 700 /*TEST 701 702 test: 703 args: -nox -snes_monitor_cancel -snes_monitor_short -ksp_gmres_cgs_refinement_type refine_always 704 705 test: 706 suffix: 2 707 nsize: 3 708 args: -nox -pc_type asm -mat_type mpiaij -snes_monitor_cancel -snes_monitor_short -ksp_gmres_cgs_refinement_type refine_always 709 710 test: 711 suffix: 3 712 nsize: 2 713 args: -nox -snes_monitor_cancel -snes_monitor_short -ksp_gmres_cgs_refinement_type refine_always 714 715 test: 716 suffix: 4 717 args: -nox -pre_check_iterates -post_check_iterates 718 719 test: 720 suffix: 5 721 requires: double !complex !single 722 nsize: 2 723 args: -nox -snes_test_jacobian -snes_test_jacobian_view 724 725 test: 726 suffix: 6 727 requires: double !complex !single 728 nsize: 4 729 args: -test_jacobian_domain_error -snes_converged_reason -snes_check_jacobian_domain_error 1 730 731 test: 732 suffix: 7 733 requires: double !complex !single 734 nsize: 4 735 args: -test_jacobian_domain_error -snes_converged_reason -snes_type newtontr -snes_check_jacobian_domain_error 1 736 737 test: 738 suffix: 8 739 requires: double !complex !single 740 nsize: 4 741 args: -test_jacobian_domain_error -snes_converged_reason -snes_type vinewtonrsls -snes_check_jacobian_domain_error 1 742 743 test: 744 suffix: 9 745 requires: double !complex !single 746 nsize: 4 747 args: -test_jacobian_domain_error -snes_converged_reason -snes_type vinewtonssls -snes_check_jacobian_domain_error 1 748 749 test: 750 suffix: 10 751 requires: double !complex !single 752 nsize: 4 753 args: -test_jacobian_domain_error -snes_converged_reason -snes_type qn -snes_qn_scale_type jacobian -snes_check_jacobian_domain_error 1 754 755 test: 756 suffix: 11 757 requires: double !complex !single 758 nsize: 4 759 args: -test_jacobian_domain_error -snes_converged_reason -snes_type ms -snes_ms_type m62 -snes_ms_damping 0.9 -snes_check_jacobian_domain_error 1 760 761 test: 762 suffix: 12 763 args: -view_initial 764 filter: grep -v "type:" 765 766 TEST*/ 767