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