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