1 /* Program usage: mpiexec -n 1 eptorsion1 [-help] [all TAO options] */ 2 3 /* ---------------------------------------------------------------------- 4 5 Elastic-plastic torsion problem. 6 7 The elastic plastic torsion problem arises from the determination 8 of the stress field on an infinitely long cylindrical bar, which is 9 equivalent to the solution of the following problem: 10 11 min{ .5 * integral(||gradient(v(x))||^2 dx) - C * integral(v(x) dx)} 12 13 where C is the torsion angle per unit length. 14 15 The multiprocessor version of this code is eptorsion2.c. 16 17 ---------------------------------------------------------------------- */ 18 19 /* 20 Include "petsctao.h" so that we can use TAO solvers. Note that this 21 file automatically includes files for lower-level support, such as those 22 provided by the PETSc library: 23 petsc.h - base PETSc routines petscvec.h - vectors 24 petscsys.h - sysem routines petscmat.h - matrices 25 petscis.h - index sets petscksp.h - Krylov subspace methods 26 petscviewer.h - viewers petscpc.h - preconditioners 27 */ 28 29 #include <petsctao.h> 30 31 32 static char help[]= 33 "Demonstrates use of the TAO package to solve \n\ 34 unconstrained minimization problems on a single processor. This example \n\ 35 is based on the Elastic-Plastic Torsion (dept) problem from the MINPACK-2 \n\ 36 test suite.\n\ 37 The command line options are:\n\ 38 -mx <xg>, where <xg> = number of grid points in the 1st coordinate direction\n\ 39 -my <yg>, where <yg> = number of grid points in the 2nd coordinate direction\n\ 40 -par <param>, where <param> = angle of twist per unit length\n\n"; 41 42 /*T 43 Concepts: TAO^Solving an unconstrained minimization problem 44 Routines: TaoCreate(); TaoSetType(); 45 Routines: TaoSetInitialVector(); 46 Routines: TaoSetObjectiveAndGradientRoutine(); 47 Routines: TaoSetHessianRoutine(); TaoSetFromOptions(); 48 Routines: TaoGetKSP(); TaoSolve(); 49 Routines: TaoDestroy(); 50 Processors: 1 51 T*/ 52 53 /* 54 User-defined application context - contains data needed by the 55 application-provided call-back routines, FormFunction(), 56 FormGradient(), and FormHessian(). 57 */ 58 59 typedef struct { 60 PetscReal param; /* nonlinearity parameter */ 61 PetscInt mx, my; /* discretization in x- and y-directions */ 62 PetscInt ndim; /* problem dimension */ 63 Vec s, y, xvec; /* work space for computing Hessian */ 64 PetscReal hx, hy; /* mesh spacing in x- and y-directions */ 65 } AppCtx; 66 67 /* -------- User-defined Routines --------- */ 68 69 PetscErrorCode FormInitialGuess(AppCtx*,Vec); 70 PetscErrorCode FormFunction(Tao,Vec,PetscReal*,void*); 71 PetscErrorCode FormGradient(Tao,Vec,Vec,void*); 72 PetscErrorCode FormHessian(Tao,Vec,Mat,Mat, void*); 73 PetscErrorCode HessianProductMat(Mat,Vec,Vec); 74 PetscErrorCode HessianProduct(void*,Vec,Vec); 75 PetscErrorCode MatrixFreeHessian(Tao,Vec,Mat,Mat,void*); 76 PetscErrorCode FormFunctionGradient(Tao,Vec,PetscReal *,Vec,void *); 77 78 PetscErrorCode main(int argc,char **argv) 79 { 80 PetscErrorCode ierr; /* used to check for functions returning nonzeros */ 81 PetscInt mx=10; /* discretization in x-direction */ 82 PetscInt my=10; /* discretization in y-direction */ 83 Vec x; /* solution, gradient vectors */ 84 PetscBool flg; /* A return value when checking for use options */ 85 Tao tao; /* Tao solver context */ 86 Mat H; /* Hessian matrix */ 87 AppCtx user; /* application context */ 88 PetscMPIInt size; /* number of processes */ 89 PetscReal one=1.0; 90 91 PetscBool test_lmvm = PETSC_FALSE; 92 KSP ksp; 93 PC pc; 94 Mat M; 95 Vec in, out, out2; 96 PetscReal mult_solve_dist; 97 98 /* Initialize TAO,PETSc */ 99 ierr = PetscInitialize(&argc,&argv,(char *)0,help);if (ierr) return ierr; 100 ierr = MPI_Comm_size(MPI_COMM_WORLD,&size);CHKERRQ(ierr); 101 if (size >1) SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_WRONG_MPI_SIZE,"Incorrect number of processors"); 102 103 /* Specify default parameters for the problem, check for command-line overrides */ 104 user.param = 5.0; 105 ierr = PetscOptionsGetInt(NULL,NULL,"-my",&my,&flg);CHKERRQ(ierr); 106 ierr = PetscOptionsGetInt(NULL,NULL,"-mx",&mx,&flg);CHKERRQ(ierr); 107 ierr = PetscOptionsGetReal(NULL,NULL,"-par",&user.param,&flg);CHKERRQ(ierr); 108 ierr = PetscOptionsGetBool(NULL,NULL,"-test_lmvm",&test_lmvm,&flg);CHKERRQ(ierr); 109 110 ierr = PetscPrintf(PETSC_COMM_SELF,"\n---- Elastic-Plastic Torsion Problem -----\n");CHKERRQ(ierr); 111 ierr = PetscPrintf(PETSC_COMM_SELF,"mx: %D my: %D \n\n",mx,my); CHKERRQ(ierr); 112 user.ndim = mx * my; user.mx = mx; user.my = my; 113 user.hx = one/(mx+1); user.hy = one/(my+1); 114 115 /* Allocate vectors */ 116 ierr = VecCreateSeq(PETSC_COMM_SELF,user.ndim,&user.y);CHKERRQ(ierr); 117 ierr = VecDuplicate(user.y,&user.s);CHKERRQ(ierr); 118 ierr = VecDuplicate(user.y,&x);CHKERRQ(ierr); 119 120 /* Create TAO solver and set desired solution method */ 121 ierr = TaoCreate(PETSC_COMM_SELF,&tao);CHKERRQ(ierr); 122 ierr = TaoSetType(tao,TAOLMVM);CHKERRQ(ierr); 123 124 /* Set solution vector with an initial guess */ 125 ierr = FormInitialGuess(&user,x);CHKERRQ(ierr); 126 ierr = TaoSetInitialVector(tao,x);CHKERRQ(ierr); 127 128 /* Set routine for function and gradient evaluation */ 129 ierr = TaoSetObjectiveAndGradientRoutine(tao,FormFunctionGradient,(void *)&user);CHKERRQ(ierr); 130 131 /* From command line options, determine if using matrix-free hessian */ 132 ierr = PetscOptionsHasName(NULL,NULL,"-my_tao_mf",&flg);CHKERRQ(ierr); 133 if (flg) { 134 ierr = MatCreateShell(PETSC_COMM_SELF,user.ndim,user.ndim,user.ndim,user.ndim,(void*)&user,&H);CHKERRQ(ierr); 135 ierr = MatShellSetOperation(H,MATOP_MULT,(void(*)(void))HessianProductMat);CHKERRQ(ierr); 136 ierr = MatSetOption(H,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr); 137 138 ierr = TaoSetHessianRoutine(tao,H,H,MatrixFreeHessian,(void *)&user);CHKERRQ(ierr); 139 } else { 140 ierr = MatCreateSeqAIJ(PETSC_COMM_SELF,user.ndim,user.ndim,5,NULL,&H);CHKERRQ(ierr); 141 ierr = MatSetOption(H,MAT_SYMMETRIC,PETSC_TRUE);CHKERRQ(ierr); 142 ierr = TaoSetHessianRoutine(tao,H,H,FormHessian,(void *)&user);CHKERRQ(ierr); 143 } 144 145 /* Test the LMVM matrix */ 146 if (test_lmvm) { 147 ierr = PetscOptionsSetValue(NULL, "-tao_type", "bntr");CHKERRQ(ierr); 148 ierr = PetscOptionsSetValue(NULL, "-tao_bnk_pc_type", "lmvm");CHKERRQ(ierr); 149 } 150 151 /* Check for any TAO command line options */ 152 ierr = TaoSetFromOptions(tao);CHKERRQ(ierr); 153 154 /* SOLVE THE APPLICATION */ 155 ierr = TaoSolve(tao); CHKERRQ(ierr); 156 157 /* Test the LMVM matrix */ 158 if (test_lmvm) { 159 ierr = TaoGetKSP(tao, &ksp);CHKERRQ(ierr); 160 ierr = KSPGetPC(ksp, &pc);CHKERRQ(ierr); 161 ierr = PCLMVMGetMatLMVM(pc, &M);CHKERRQ(ierr); 162 ierr = VecDuplicate(x, &in);CHKERRQ(ierr); 163 ierr = VecDuplicate(x, &out);CHKERRQ(ierr); 164 ierr = VecDuplicate(x, &out2);CHKERRQ(ierr); 165 ierr = VecSet(in, 5.0);CHKERRQ(ierr); 166 ierr = MatMult(M, in, out);CHKERRQ(ierr); 167 ierr = MatSolve(M, out, out2);CHKERRQ(ierr); 168 ierr = VecAXPY(out2, -1.0, in);CHKERRQ(ierr); 169 ierr = VecNorm(out2, NORM_2, &mult_solve_dist);CHKERRQ(ierr); 170 ierr = PetscPrintf(PetscObjectComm((PetscObject)tao), "error between MatMult and MatSolve: %e\n", mult_solve_dist);CHKERRQ(ierr); 171 ierr = VecDestroy(&in);CHKERRQ(ierr); 172 ierr = VecDestroy(&out);CHKERRQ(ierr); 173 ierr = VecDestroy(&out2);CHKERRQ(ierr); 174 } 175 176 ierr = TaoDestroy(&tao);CHKERRQ(ierr); 177 ierr = VecDestroy(&user.s);CHKERRQ(ierr); 178 ierr = VecDestroy(&user.y);CHKERRQ(ierr); 179 ierr = VecDestroy(&x);CHKERRQ(ierr); 180 ierr = MatDestroy(&H);CHKERRQ(ierr); 181 182 ierr = PetscFinalize(); 183 return ierr; 184 } 185 186 /* ------------------------------------------------------------------- */ 187 /* 188 FormInitialGuess - Computes an initial approximation to the solution. 189 190 Input Parameters: 191 . user - user-defined application context 192 . X - vector 193 194 Output Parameters: 195 . X - vector 196 */ 197 PetscErrorCode FormInitialGuess(AppCtx *user,Vec X) 198 { 199 PetscReal hx = user->hx, hy = user->hy, temp; 200 PetscReal val; 201 PetscErrorCode ierr; 202 PetscInt i, j, k, nx = user->mx, ny = user->my; 203 204 /* Compute initial guess */ 205 PetscFunctionBeginUser; 206 for (j=0; j<ny; j++) { 207 temp = PetscMin(j+1,ny-j)*hy; 208 for (i=0; i<nx; i++) { 209 k = nx*j + i; 210 val = PetscMin((PetscMin(i+1,nx-i))*hx,temp); 211 ierr = VecSetValues(X,1,&k,&val,ADD_VALUES);CHKERRQ(ierr); 212 } 213 } 214 ierr = VecAssemblyBegin(X);CHKERRQ(ierr); 215 ierr = VecAssemblyEnd(X);CHKERRQ(ierr); 216 PetscFunctionReturn(0); 217 } 218 219 /* ------------------------------------------------------------------- */ 220 /* 221 FormFunctionGradient - Evaluates the function and corresponding gradient. 222 223 Input Parameters: 224 tao - the Tao context 225 X - the input vector 226 ptr - optional user-defined context, as set by TaoSetFunction() 227 228 Output Parameters: 229 f - the newly evaluated function 230 G - the newly evaluated gradient 231 */ 232 PetscErrorCode FormFunctionGradient(Tao tao,Vec X,PetscReal *f,Vec G,void *ptr) 233 { 234 PetscErrorCode ierr; 235 236 PetscFunctionBeginUser; 237 ierr = FormFunction(tao,X,f,ptr);CHKERRQ(ierr); 238 ierr = FormGradient(tao,X,G,ptr);CHKERRQ(ierr); 239 PetscFunctionReturn(0); 240 } 241 242 /* ------------------------------------------------------------------- */ 243 /* 244 FormFunction - Evaluates the function, f(X). 245 246 Input Parameters: 247 . tao - the Tao context 248 . X - the input vector 249 . ptr - optional user-defined context, as set by TaoSetFunction() 250 251 Output Parameters: 252 . f - the newly evaluated function 253 */ 254 PetscErrorCode FormFunction(Tao tao,Vec X,PetscReal *f,void *ptr) 255 { 256 AppCtx *user = (AppCtx *) ptr; 257 PetscReal hx = user->hx, hy = user->hy, area, three = 3.0, p5 = 0.5; 258 PetscReal zero = 0.0, vb, vl, vr, vt, dvdx, dvdy, flin = 0.0, fquad = 0.0; 259 PetscReal v, cdiv3 = user->param/three; 260 const PetscScalar *x; 261 PetscErrorCode ierr; 262 PetscInt nx = user->mx, ny = user->my, i, j, k; 263 264 PetscFunctionBeginUser; 265 /* Get pointer to vector data */ 266 ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 267 268 /* Compute function contributions over the lower triangular elements */ 269 for (j=-1; j<ny; j++) { 270 for (i=-1; i<nx; i++) { 271 k = nx*j + i; 272 v = zero; 273 vr = zero; 274 vt = zero; 275 if (i >= 0 && j >= 0) v = x[k]; 276 if (i < nx-1 && j > -1) vr = x[k+1]; 277 if (i > -1 && j < ny-1) vt = x[k+nx]; 278 dvdx = (vr-v)/hx; 279 dvdy = (vt-v)/hy; 280 fquad += dvdx*dvdx + dvdy*dvdy; 281 flin -= cdiv3*(v+vr+vt); 282 } 283 } 284 285 /* Compute function contributions over the upper triangular elements */ 286 for (j=0; j<=ny; j++) { 287 for (i=0; i<=nx; i++) { 288 k = nx*j + i; 289 vb = zero; 290 vl = zero; 291 v = zero; 292 if (i < nx && j > 0) vb = x[k-nx]; 293 if (i > 0 && j < ny) vl = x[k-1]; 294 if (i < nx && j < ny) v = x[k]; 295 dvdx = (v-vl)/hx; 296 dvdy = (v-vb)/hy; 297 fquad = fquad + dvdx*dvdx + dvdy*dvdy; 298 flin = flin - cdiv3*(vb+vl+v); 299 } 300 } 301 302 /* Restore vector */ 303 ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 304 305 /* Scale the function */ 306 area = p5*hx*hy; 307 *f = area*(p5*fquad+flin); 308 309 ierr = PetscLogFlops(24.0*nx*ny);CHKERRQ(ierr); 310 PetscFunctionReturn(0); 311 } 312 313 /* ------------------------------------------------------------------- */ 314 /* 315 FormGradient - Evaluates the gradient, G(X). 316 317 Input Parameters: 318 . tao - the Tao context 319 . X - input vector 320 . ptr - optional user-defined context 321 322 Output Parameters: 323 . G - vector containing the newly evaluated gradient 324 */ 325 PetscErrorCode FormGradient(Tao tao,Vec X,Vec G,void *ptr) 326 { 327 AppCtx *user = (AppCtx *) ptr; 328 PetscReal zero=0.0, p5=0.5, three = 3.0, area, val; 329 PetscErrorCode ierr; 330 PetscInt nx = user->mx, ny = user->my, ind, i, j, k; 331 PetscReal hx = user->hx, hy = user->hy; 332 PetscReal vb, vl, vr, vt, dvdx, dvdy; 333 PetscReal v, cdiv3 = user->param/three; 334 const PetscScalar *x; 335 336 PetscFunctionBeginUser; 337 /* Initialize gradient to zero */ 338 ierr = VecSet(G, zero);CHKERRQ(ierr); 339 340 /* Get pointer to vector data */ 341 ierr = VecGetArrayRead(X,&x);CHKERRQ(ierr); 342 343 /* Compute gradient contributions over the lower triangular elements */ 344 for (j=-1; j<ny; j++) { 345 for (i=-1; i<nx; i++) { 346 k = nx*j + i; 347 v = zero; 348 vr = zero; 349 vt = zero; 350 if (i >= 0 && j >= 0) v = x[k]; 351 if (i < nx-1 && j > -1) vr = x[k+1]; 352 if (i > -1 && j < ny-1) vt = x[k+nx]; 353 dvdx = (vr-v)/hx; 354 dvdy = (vt-v)/hy; 355 if (i != -1 && j != -1) { 356 ind = k; val = - dvdx/hx - dvdy/hy - cdiv3; 357 ierr = VecSetValues(G,1,&ind,&val,ADD_VALUES);CHKERRQ(ierr); 358 } 359 if (i != nx-1 && j != -1) { 360 ind = k+1; val = dvdx/hx - cdiv3; 361 ierr = VecSetValues(G,1,&ind,&val,ADD_VALUES);CHKERRQ(ierr); 362 } 363 if (i != -1 && j != ny-1) { 364 ind = k+nx; val = dvdy/hy - cdiv3; 365 ierr = VecSetValues(G,1,&ind,&val,ADD_VALUES);CHKERRQ(ierr); 366 } 367 } 368 } 369 370 /* Compute gradient contributions over the upper triangular elements */ 371 for (j=0; j<=ny; j++) { 372 for (i=0; i<=nx; i++) { 373 k = nx*j + i; 374 vb = zero; 375 vl = zero; 376 v = zero; 377 if (i < nx && j > 0) vb = x[k-nx]; 378 if (i > 0 && j < ny) vl = x[k-1]; 379 if (i < nx && j < ny) v = x[k]; 380 dvdx = (v-vl)/hx; 381 dvdy = (v-vb)/hy; 382 if (i != nx && j != 0) { 383 ind = k-nx; val = - dvdy/hy - cdiv3; 384 ierr = VecSetValues(G,1,&ind,&val,ADD_VALUES);CHKERRQ(ierr); 385 } 386 if (i != 0 && j != ny) { 387 ind = k-1; val = - dvdx/hx - cdiv3; 388 ierr = VecSetValues(G,1,&ind,&val,ADD_VALUES);CHKERRQ(ierr); 389 } 390 if (i != nx && j != ny) { 391 ind = k; val = dvdx/hx + dvdy/hy - cdiv3; 392 ierr = VecSetValues(G,1,&ind,&val,ADD_VALUES);CHKERRQ(ierr); 393 } 394 } 395 } 396 ierr = VecRestoreArrayRead(X,&x);CHKERRQ(ierr); 397 398 /* Assemble gradient vector */ 399 ierr = VecAssemblyBegin(G);CHKERRQ(ierr); 400 ierr = VecAssemblyEnd(G);CHKERRQ(ierr); 401 402 /* Scale the gradient */ 403 area = p5*hx*hy; 404 ierr = VecScale(G, area);CHKERRQ(ierr); 405 ierr = PetscLogFlops(24.0*nx*ny);CHKERRQ(ierr); 406 PetscFunctionReturn(0); 407 } 408 409 /* ------------------------------------------------------------------- */ 410 /* 411 FormHessian - Forms the Hessian matrix. 412 413 Input Parameters: 414 . tao - the Tao context 415 . X - the input vector 416 . ptr - optional user-defined context, as set by TaoSetHessian() 417 418 Output Parameters: 419 . H - Hessian matrix 420 . PrecH - optionally different preconditioning Hessian 421 . flag - flag indicating matrix structure 422 423 Notes: 424 This routine is intended simply as an example of the interface 425 to a Hessian evaluation routine. Since this example compute the 426 Hessian a column at a time, it is not particularly efficient and 427 is not recommended. 428 */ 429 PetscErrorCode FormHessian(Tao tao,Vec X,Mat H,Mat Hpre, void *ptr) 430 { 431 AppCtx *user = (AppCtx *) ptr; 432 PetscErrorCode ierr; 433 PetscInt i,j, ndim = user->ndim; 434 PetscReal *y, zero = 0.0, one = 1.0; 435 PetscBool assembled; 436 437 PetscFunctionBeginUser; 438 user->xvec = X; 439 440 /* Initialize Hessian entries and work vector to zero */ 441 ierr = MatAssembled(H,&assembled);CHKERRQ(ierr); 442 if (assembled){ierr = MatZeroEntries(H); CHKERRQ(ierr);} 443 444 ierr = VecSet(user->s, zero);CHKERRQ(ierr); 445 446 /* Loop over matrix columns to compute entries of the Hessian */ 447 for (j=0; j<ndim; j++) { 448 ierr = VecSetValues(user->s,1,&j,&one,INSERT_VALUES);CHKERRQ(ierr); 449 ierr = VecAssemblyBegin(user->s);CHKERRQ(ierr); 450 ierr = VecAssemblyEnd(user->s);CHKERRQ(ierr); 451 452 ierr = HessianProduct(ptr,user->s,user->y);CHKERRQ(ierr); 453 454 ierr = VecSetValues(user->s,1,&j,&zero,INSERT_VALUES);CHKERRQ(ierr); 455 ierr = VecAssemblyBegin(user->s);CHKERRQ(ierr); 456 ierr = VecAssemblyEnd(user->s);CHKERRQ(ierr); 457 458 ierr = VecGetArray(user->y,&y);CHKERRQ(ierr); 459 for (i=0; i<ndim; i++) { 460 if (y[i] != zero) { 461 ierr = MatSetValues(H,1,&i,1,&j,&y[i],ADD_VALUES);CHKERRQ(ierr); 462 } 463 } 464 ierr = VecRestoreArray(user->y,&y);CHKERRQ(ierr); 465 } 466 ierr = MatAssemblyBegin(H,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 467 ierr = MatAssemblyEnd(H,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr); 468 PetscFunctionReturn(0); 469 } 470 471 /* ------------------------------------------------------------------- */ 472 /* 473 MatrixFreeHessian - Sets a pointer for use in computing Hessian-vector 474 products. 475 476 Input Parameters: 477 . tao - the Tao context 478 . X - the input vector 479 . ptr - optional user-defined context, as set by TaoSetHessian() 480 481 Output Parameters: 482 . H - Hessian matrix 483 . PrecH - optionally different preconditioning Hessian 484 . flag - flag indicating matrix structure 485 */ 486 PetscErrorCode MatrixFreeHessian(Tao tao,Vec X,Mat H,Mat PrecH, void *ptr) 487 { 488 AppCtx *user = (AppCtx *) ptr; 489 490 /* Sets location of vector for use in computing matrix-vector products of the form H(X)*y */ 491 user->xvec = X; 492 PetscFunctionReturn(0); 493 } 494 495 /* ------------------------------------------------------------------- */ 496 /* 497 HessianProductMat - Computes the matrix-vector product 498 y = mat*svec. 499 500 Input Parameters: 501 . mat - input matrix 502 . svec - input vector 503 504 Output Parameters: 505 . y - solution vector 506 */ 507 PetscErrorCode HessianProductMat(Mat mat,Vec svec,Vec y) 508 { 509 void *ptr; 510 PetscErrorCode ierr; 511 512 PetscFunctionBeginUser; 513 ierr = MatShellGetContext(mat,&ptr);CHKERRQ(ierr); 514 ierr = HessianProduct(ptr,svec,y);CHKERRQ(ierr); 515 PetscFunctionReturn(0); 516 } 517 518 /* ------------------------------------------------------------------- */ 519 /* 520 Hessian Product - Computes the matrix-vector product: 521 y = f''(x)*svec. 522 523 Input Parameters: 524 . ptr - pointer to the user-defined context 525 . svec - input vector 526 527 Output Parameters: 528 . y - product vector 529 */ 530 PetscErrorCode HessianProduct(void *ptr,Vec svec,Vec y) 531 { 532 AppCtx *user = (AppCtx *)ptr; 533 PetscReal p5 = 0.5, zero = 0.0, one = 1.0, hx, hy, val, area; 534 const PetscScalar *x, *s; 535 PetscReal v, vb, vl, vr, vt, hxhx, hyhy; 536 PetscErrorCode ierr; 537 PetscInt nx, ny, i, j, k, ind; 538 539 PetscFunctionBeginUser; 540 nx = user->mx; 541 ny = user->my; 542 hx = user->hx; 543 hy = user->hy; 544 hxhx = one/(hx*hx); 545 hyhy = one/(hy*hy); 546 547 /* Get pointers to vector data */ 548 ierr = VecGetArrayRead(user->xvec,&x);CHKERRQ(ierr); 549 ierr = VecGetArrayRead(svec,&s);CHKERRQ(ierr); 550 551 /* Initialize product vector to zero */ 552 ierr = VecSet(y, zero);CHKERRQ(ierr); 553 554 /* Compute f''(x)*s over the lower triangular elements */ 555 for (j=-1; j<ny; j++) { 556 for (i=-1; i<nx; i++) { 557 k = nx*j + i; 558 v = zero; 559 vr = zero; 560 vt = zero; 561 if (i != -1 && j != -1) v = s[k]; 562 if (i != nx-1 && j != -1) { 563 vr = s[k+1]; 564 ind = k+1; val = hxhx*(vr-v); 565 ierr = VecSetValues(y,1,&ind,&val,ADD_VALUES);CHKERRQ(ierr); 566 } 567 if (i != -1 && j != ny-1) { 568 vt = s[k+nx]; 569 ind = k+nx; val = hyhy*(vt-v); 570 ierr = VecSetValues(y,1,&ind,&val,ADD_VALUES);CHKERRQ(ierr); 571 } 572 if (i != -1 && j != -1) { 573 ind = k; val = hxhx*(v-vr) + hyhy*(v-vt); 574 ierr = VecSetValues(y,1,&ind,&val,ADD_VALUES);CHKERRQ(ierr); 575 } 576 } 577 } 578 579 /* Compute f''(x)*s over the upper triangular elements */ 580 for (j=0; j<=ny; j++) { 581 for (i=0; i<=nx; i++) { 582 k = nx*j + i; 583 v = zero; 584 vl = zero; 585 vb = zero; 586 if (i != nx && j != ny) v = s[k]; 587 if (i != nx && j != 0) { 588 vb = s[k-nx]; 589 ind = k-nx; val = hyhy*(vb-v); 590 ierr = VecSetValues(y,1,&ind,&val,ADD_VALUES);CHKERRQ(ierr); 591 } 592 if (i != 0 && j != ny) { 593 vl = s[k-1]; 594 ind = k-1; val = hxhx*(vl-v); 595 ierr = VecSetValues(y,1,&ind,&val,ADD_VALUES);CHKERRQ(ierr); 596 } 597 if (i != nx && j != ny) { 598 ind = k; val = hxhx*(v-vl) + hyhy*(v-vb); 599 ierr = VecSetValues(y,1,&ind,&val,ADD_VALUES);CHKERRQ(ierr); 600 } 601 } 602 } 603 /* Restore vector data */ 604 ierr = VecRestoreArrayRead(svec,&s);CHKERRQ(ierr); 605 ierr = VecRestoreArrayRead(user->xvec,&x);CHKERRQ(ierr); 606 607 /* Assemble vector */ 608 ierr = VecAssemblyBegin(y);CHKERRQ(ierr); 609 ierr = VecAssemblyEnd(y);CHKERRQ(ierr); 610 611 /* Scale resulting vector by area */ 612 area = p5*hx*hy; 613 ierr = VecScale(y, area);CHKERRQ(ierr); 614 ierr = PetscLogFlops(18.0*nx*ny);CHKERRQ(ierr); 615 PetscFunctionReturn(0); 616 } 617 618 619 /*TEST 620 621 build: 622 requires: !complex 623 624 test: 625 suffix: 1 626 args: -tao_smonitor -tao_type ntl -tao_gatol 1.e-4 627 628 test: 629 suffix: 2 630 args: -tao_smonitor -tao_type ntr -tao_gatol 1.e-4 631 632 test: 633 suffix: 3 634 args: -tao_smonitor -tao_type bntr -tao_gatol 1.e-4 -my_tao_mf -tao_test_hessian 635 636 test: 637 suffix: 4 638 args: -tao_smonitor -tao_gatol 1e-3 -tao_type bqnls 639 640 test: 641 suffix: 5 642 args: -tao_smonitor -tao_gatol 1e-3 -tao_type blmvm 643 644 test: 645 suffix: 6 646 args: -tao_smonitor -tao_gatol 1e-3 -tao_type bqnktr -tao_bqnk_mat_type lmvmsr1 647 648 TEST*/ 649