1d8606c27SBarry Smith! Program usage: mpiexec -n <proc> eptorsion2f [all TAO options] 2d8606c27SBarry Smith! 3d8606c27SBarry Smith! Description: This example demonstrates use of the TAO package to solve 4d8606c27SBarry Smith! unconstrained minimization problems in parallel. This example is based 5d8606c27SBarry Smith! on the Elastic-Plastic Torsion (dept) problem from the MINPACK-2 test suite. 6d8606c27SBarry Smith! The command line options are: 7d8606c27SBarry Smith! -mx <xg>, where <xg> = number of grid points in the 1st coordinate direction 8d8606c27SBarry Smith! -my <yg>, where <yg> = number of grid points in the 2nd coordinate direction 9d8606c27SBarry Smith! -par <param>, where <param> = angle of twist per unit length 10d8606c27SBarry Smith! 11d8606c27SBarry Smith! 12d8606c27SBarry Smith! ---------------------------------------------------------------------- 13d8606c27SBarry Smith! 14d8606c27SBarry Smith! Elastic-plastic torsion problem. 15d8606c27SBarry Smith! 16d8606c27SBarry Smith! The elastic plastic torsion problem arises from the deconverged 17d8606c27SBarry Smith! of the stress field on an infinitely long cylindrical bar, which is 18d8606c27SBarry Smith! equivalent to the solution of the following problem: 19d8606c27SBarry Smith! min{ .5 * integral(||gradient(v(x))||^2 dx) - C * integral(v(x) dx)} 20d8606c27SBarry Smith! where C is the torsion angle per unit length. 21d8606c27SBarry Smith! 22d8606c27SBarry Smith! The C version of this code is eptorsion2.c 23d8606c27SBarry Smith! 24d8606c27SBarry Smith! ---------------------------------------------------------------------- 25d8606c27SBarry Smith 26*77d968b7SBarry Smith module eptorsion2fmodule 27d8606c27SBarry Smith#include "petsc/finclude/petsctao.h" 28d8606c27SBarry Smith use petscdmda 29d8606c27SBarry Smith use petsctao 30d8606c27SBarry Smith implicit none 31d8606c27SBarry Smith 32d8606c27SBarry Smith Vec localX 33d8606c27SBarry Smith DM dm 34d8606c27SBarry Smith PetscReal param 35d8606c27SBarry Smith PetscInt mx, my 36d8606c27SBarry Smith end module 37d8606c27SBarry Smith 38*77d968b7SBarry Smith use eptorsion2fmodule 39d8606c27SBarry Smith implicit none 40d8606c27SBarry Smith! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 41d8606c27SBarry Smith! Variable declarations 42d8606c27SBarry Smith! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 43d8606c27SBarry Smith! 44d8606c27SBarry Smith! See additional variable declarations in the file eptorsion2f.h 45d8606c27SBarry Smith! 46d8606c27SBarry Smith PetscErrorCode ierr ! used to check for functions returning nonzeros 47d8606c27SBarry Smith Vec x ! solution vector 48d8606c27SBarry Smith Mat H ! hessian matrix 49d8606c27SBarry Smith PetscInt Nx, Ny ! number of processes in x- and y- directions 50d8606c27SBarry Smith Tao tao ! Tao solver context 51d8606c27SBarry Smith PetscBool flg 52d8606c27SBarry Smith PetscInt i1 53d8606c27SBarry Smith PetscInt dummy 54d8606c27SBarry Smith 55d8606c27SBarry Smith! Note: Any user-defined Fortran routines (such as FormGradient) 56d8606c27SBarry Smith! MUST be declared as external. 57d8606c27SBarry Smith 58d8606c27SBarry Smith external FormInitialGuess,FormFunctionGradient,ComputeHessian 59d8606c27SBarry Smith external Monitor,ConvergenceTest 60d8606c27SBarry Smith 61d8606c27SBarry Smith i1 = 1 62d8606c27SBarry Smith 63d8606c27SBarry Smith! Initialize TAO, PETSc contexts 64d8606c27SBarry Smith PetscCallA(PetscInitialize(ierr)) 65d8606c27SBarry Smith 66d8606c27SBarry Smith! Specify default parameters 67d8606c27SBarry Smith param = 5.0 68d8606c27SBarry Smith mx = 10 69d8606c27SBarry Smith my = 10 70d8606c27SBarry Smith Nx = PETSC_DECIDE 71d8606c27SBarry Smith Ny = PETSC_DECIDE 72d8606c27SBarry Smith 73d8606c27SBarry Smith! Check for any command line arguments that might override defaults 74d8606c27SBarry Smith PetscCallA(PetscOptionsGetInt(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-mx',mx,flg,ierr)) 75d8606c27SBarry Smith PetscCallA(PetscOptionsGetInt(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-my',my,flg,ierr)) 76d8606c27SBarry Smith PetscCallA(PetscOptionsGetReal(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-par',param,flg,ierr)) 77d8606c27SBarry Smith 78d8606c27SBarry Smith! Set up distributed array and vectors 79d8606c27SBarry Smith PetscCallA(DMDACreate2d(PETSC_COMM_WORLD,DM_BOUNDARY_NONE,DM_BOUNDARY_NONE,DMDA_STENCIL_BOX,mx,my,Nx,Ny,i1,i1,PETSC_NULL_INTEGER,PETSC_NULL_INTEGER,dm,ierr)) 80d8606c27SBarry Smith PetscCallA(DMSetFromOptions(dm,ierr)) 81d8606c27SBarry Smith PetscCallA(DMSetUp(dm,ierr)) 82d8606c27SBarry Smith 83d8606c27SBarry Smith! Create vectors 84d8606c27SBarry Smith PetscCallA(DMCreateGlobalVector(dm,x,ierr)) 85d8606c27SBarry Smith PetscCallA(DMCreateLocalVector(dm,localX,ierr)) 86d8606c27SBarry Smith 87d8606c27SBarry Smith! Create Hessian 88d8606c27SBarry Smith PetscCallA(DMCreateMatrix(dm,H,ierr)) 89d8606c27SBarry Smith PetscCallA(MatSetOption(H,MAT_SYMMETRIC,PETSC_TRUE,ierr)) 90d8606c27SBarry Smith 91d8606c27SBarry Smith! The TAO code begins here 92d8606c27SBarry Smith 93d8606c27SBarry Smith! Create TAO solver 94d8606c27SBarry Smith PetscCallA(TaoCreate(PETSC_COMM_WORLD,tao,ierr)) 95d8606c27SBarry Smith PetscCallA(TaoSetType(tao,TAOCG,ierr)) 96d8606c27SBarry Smith 97d8606c27SBarry Smith! Set routines for function and gradient evaluation 98d8606c27SBarry Smith 99d8606c27SBarry Smith PetscCallA(TaoSetObjectiveAndGradient(tao,PETSC_NULL_VEC,FormFunctionGradient,0,ierr)) 100d8606c27SBarry Smith PetscCallA(TaoSetHessian(tao,H,H,ComputeHessian,0,ierr)) 101d8606c27SBarry Smith 102d8606c27SBarry Smith! Set initial guess 103d8606c27SBarry Smith PetscCallA(FormInitialGuess(x,ierr)) 104d8606c27SBarry Smith PetscCallA(TaoSetSolution(tao,x,ierr)) 105d8606c27SBarry Smith 106d8606c27SBarry Smith PetscCallA(PetscOptionsHasName(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-testmonitor',flg,ierr)) 107d8606c27SBarry Smith if (flg) then 108d8606c27SBarry Smith PetscCallA(TaoSetMonitor(tao,Monitor,dummy,PETSC_NULL_FUNCTION,ierr)) 109d8606c27SBarry Smith endif 110d8606c27SBarry Smith 111d8606c27SBarry Smith PetscCallA(PetscOptionsHasName(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-testconvergence',flg, ierr)) 112d8606c27SBarry Smith if (flg) then 113d8606c27SBarry Smith PetscCallA(TaoSetConvergenceTest(tao,ConvergenceTest,dummy,ierr)) 114d8606c27SBarry Smith endif 115d8606c27SBarry Smith 116d8606c27SBarry Smith! Check for any TAO command line options 117d8606c27SBarry Smith PetscCallA(TaoSetFromOptions(tao,ierr)) 118d8606c27SBarry Smith 119d8606c27SBarry Smith! SOLVE THE APPLICATION 120d8606c27SBarry Smith PetscCallA(TaoSolve(tao,ierr)) 121d8606c27SBarry Smith 122d8606c27SBarry Smith! Free TAO data structures 123d8606c27SBarry Smith PetscCallA(TaoDestroy(tao,ierr)) 124d8606c27SBarry Smith 125d8606c27SBarry Smith! Free PETSc data structures 126d8606c27SBarry Smith PetscCallA(VecDestroy(x,ierr)) 127d8606c27SBarry Smith PetscCallA(VecDestroy(localX,ierr)) 128d8606c27SBarry Smith PetscCallA(MatDestroy(H,ierr)) 129d8606c27SBarry Smith PetscCallA(DMDestroy(dm,ierr)) 130d8606c27SBarry Smith 131d8606c27SBarry Smith! Finalize TAO and PETSc 132d8606c27SBarry Smith PetscCallA(PetscFinalize(ierr)) 133d8606c27SBarry Smith end 134d8606c27SBarry Smith 135d8606c27SBarry Smith! --------------------------------------------------------------------- 136d8606c27SBarry Smith! 137d8606c27SBarry Smith! FormInitialGuess - Computes an initial approximation to the solution. 138d8606c27SBarry Smith! 139d8606c27SBarry Smith! Input Parameters: 140d8606c27SBarry Smith! X - vector 141d8606c27SBarry Smith! 142d8606c27SBarry Smith! Output Parameters: 143d8606c27SBarry Smith! X - vector 144d8606c27SBarry Smith! ierr - error code 145d8606c27SBarry Smith! 146d8606c27SBarry Smith subroutine FormInitialGuess(X,ierr) 147*77d968b7SBarry Smith use eptorsion2fmodule 148d8606c27SBarry Smith implicit none 149d8606c27SBarry Smith 150d8606c27SBarry Smith! Input/output variables: 151d8606c27SBarry Smith Vec X 152d8606c27SBarry Smith PetscErrorCode ierr 153d8606c27SBarry Smith 154d8606c27SBarry Smith! Local variables: 155d8606c27SBarry Smith PetscInt i, j, k, xe, ye 156d8606c27SBarry Smith PetscReal temp, val, hx, hy 157d8606c27SBarry Smith PetscInt xs, ys, xm, ym 158d8606c27SBarry Smith PetscInt gxm, gym, gxs, gys 159d8606c27SBarry Smith PetscInt i1 160d8606c27SBarry Smith 161d8606c27SBarry Smith i1 = 1 162d8606c27SBarry Smith hx = 1.0/real(mx + 1) 163d8606c27SBarry Smith hy = 1.0/real(my + 1) 164d8606c27SBarry Smith 165d8606c27SBarry Smith! Get corner information 166d8606c27SBarry Smith PetscCall(DMDAGetCorners(dm,xs,ys,PETSC_NULL_INTEGER,xm,ym,PETSC_NULL_INTEGER,ierr)) 167d8606c27SBarry Smith PetscCall(DMDAGetGhostCorners(dm,gxs,gys,PETSC_NULL_INTEGER,gxm,gym,PETSC_NULL_INTEGER,ierr)) 168d8606c27SBarry Smith 169d8606c27SBarry Smith! Compute initial guess over locally owned part of mesh 170d8606c27SBarry Smith xe = xs+xm 171d8606c27SBarry Smith ye = ys+ym 172d8606c27SBarry Smith do j=ys,ye-1 173d8606c27SBarry Smith temp = min(j+1,my-j)*hy 174d8606c27SBarry Smith do i=xs,xe-1 175d8606c27SBarry Smith k = (j-gys)*gxm + i-gxs 176d8606c27SBarry Smith val = min((min(i+1,mx-i))*hx,temp) 177d8606c27SBarry Smith PetscCall(VecSetValuesLocal(X,i1,k,val,ADD_VALUES,ierr)) 178d8606c27SBarry Smith end do 179d8606c27SBarry Smith end do 180d8606c27SBarry Smith PetscCall(VecAssemblyBegin(X,ierr)) 181d8606c27SBarry Smith PetscCall(VecAssemblyEnd(X,ierr)) 182d8606c27SBarry Smith return 183d8606c27SBarry Smith end 184d8606c27SBarry Smith 185d8606c27SBarry Smith! --------------------------------------------------------------------- 186d8606c27SBarry Smith! 187d8606c27SBarry Smith! FormFunctionGradient - Evaluates gradient G(X). 188d8606c27SBarry Smith! 189d8606c27SBarry Smith! Input Parameters: 190d8606c27SBarry Smith! tao - the Tao context 191d8606c27SBarry Smith! X - input vector 192d8606c27SBarry Smith! dummy - optional user-defined context (not used here) 193d8606c27SBarry Smith! 194d8606c27SBarry Smith! Output Parameters: 195d8606c27SBarry Smith! f - the function value at X 196d8606c27SBarry Smith! G - vector containing the newly evaluated gradient 197d8606c27SBarry Smith! ierr - error code 198d8606c27SBarry Smith! 199d8606c27SBarry Smith! Notes: 200d8606c27SBarry Smith! This routine serves as a wrapper for the lower-level routine 201d8606c27SBarry Smith! "ApplicationGradient", where the actual computations are 202d8606c27SBarry Smith! done using the standard Fortran style of treating the local 203d8606c27SBarry Smith! input vector data as an array over the local mesh. 204d8606c27SBarry Smith! 205d8606c27SBarry Smith subroutine FormFunctionGradient(tao,X,f,G,dummy,ierr) 206*77d968b7SBarry Smith use eptorsion2fmodule 207d8606c27SBarry Smith implicit none 208d8606c27SBarry Smith 209d8606c27SBarry Smith! Input/output variables: 210d8606c27SBarry Smith Tao tao 211d8606c27SBarry Smith Vec X, G 212d8606c27SBarry Smith PetscReal f 213d8606c27SBarry Smith PetscErrorCode ierr 214d8606c27SBarry Smith PetscInt dummy 215d8606c27SBarry Smith 216d8606c27SBarry Smith! Declarations for use with local array: 217d8606c27SBarry Smith 218d8606c27SBarry Smith! PETSc's VecGetArray acts differently in Fortran than it does in C. 219d8606c27SBarry Smith! Calling VecGetArray((Vec) X, (PetscReal) x_array(0:1), (PetscOffset) x_index, ierr) 220d8606c27SBarry Smith! will return an array of doubles referenced by x_array offset by x_index. 221d8606c27SBarry Smith! i.e., to reference the kth element of X, use x_array(k + x_index). 222d8606c27SBarry Smith! Notice that by declaring the arrays with range (0:1), we are using the C 0-indexing practice. 223d8606c27SBarry Smith PetscReal lx_v(0:1) 224d8606c27SBarry Smith PetscOffset lx_i 225d8606c27SBarry Smith 226d8606c27SBarry Smith! Local variables: 227d8606c27SBarry Smith PetscReal zero, p5, area, cdiv3 228d8606c27SBarry Smith PetscReal val, flin, fquad,floc 229d8606c27SBarry Smith PetscReal v, vb, vl, vr, vt, dvdx 230d8606c27SBarry Smith PetscReal dvdy, hx, hy 231d8606c27SBarry Smith PetscInt xe, ye, xsm, ysm 232d8606c27SBarry Smith PetscInt xep, yep, i, j, k, ind 233d8606c27SBarry Smith PetscInt xs, ys, xm, ym 234d8606c27SBarry Smith PetscInt gxs, gys, gxm, gym 235d8606c27SBarry Smith PetscInt i1 236d8606c27SBarry Smith 237d8606c27SBarry Smith i1 = 1 238d8606c27SBarry Smith ierr = 0 239d8606c27SBarry Smith cdiv3 = param/3.0 240d8606c27SBarry Smith zero = 0.0 241d8606c27SBarry Smith p5 = 0.5 242d8606c27SBarry Smith hx = 1.0/real(mx + 1) 243d8606c27SBarry Smith hy = 1.0/real(my + 1) 244d8606c27SBarry Smith fquad = zero 245d8606c27SBarry Smith flin = zero 246d8606c27SBarry Smith 247d8606c27SBarry Smith! Initialize gradient to zero 248d8606c27SBarry Smith PetscCall(VecSet(G,zero,ierr)) 249d8606c27SBarry Smith 250d8606c27SBarry Smith! Scatter ghost points to local vector 251d8606c27SBarry Smith PetscCall(DMGlobalToLocalBegin(dm,X,INSERT_VALUES,localX,ierr)) 252d8606c27SBarry Smith PetscCall(DMGlobalToLocalEnd(dm,X,INSERT_VALUES,localX,ierr)) 253d8606c27SBarry Smith 254d8606c27SBarry Smith! Get corner information 255d8606c27SBarry Smith PetscCall(DMDAGetCorners(dm,xs,ys,PETSC_NULL_INTEGER,xm,ym,PETSC_NULL_INTEGER,ierr)) 256d8606c27SBarry Smith PetscCall(DMDAGetGhostCorners(dm,gxs,gys,PETSC_NULL_INTEGER,gxm,gym,PETSC_NULL_INTEGER,ierr)) 257d8606c27SBarry Smith 258d8606c27SBarry Smith! Get pointer to vector data. 259d8606c27SBarry Smith PetscCall(VecGetArray(localX,lx_v,lx_i,ierr)) 260d8606c27SBarry Smith 261d8606c27SBarry Smith! Set local loop dimensions 262d8606c27SBarry Smith xe = xs+xm 263d8606c27SBarry Smith ye = ys+ym 264d8606c27SBarry Smith if (xs .eq. 0) then 265d8606c27SBarry Smith xsm = xs-1 266d8606c27SBarry Smith else 267d8606c27SBarry Smith xsm = xs 268d8606c27SBarry Smith endif 269d8606c27SBarry Smith if (ys .eq. 0) then 270d8606c27SBarry Smith ysm = ys-1 271d8606c27SBarry Smith else 272d8606c27SBarry Smith ysm = ys 273d8606c27SBarry Smith endif 274d8606c27SBarry Smith if (xe .eq. mx) then 275d8606c27SBarry Smith xep = xe+1 276d8606c27SBarry Smith else 277d8606c27SBarry Smith xep = xe 278d8606c27SBarry Smith endif 279d8606c27SBarry Smith if (ye .eq. my) then 280d8606c27SBarry Smith yep = ye+1 281d8606c27SBarry Smith else 282d8606c27SBarry Smith yep = ye 283d8606c27SBarry Smith endif 284d8606c27SBarry Smith 285d8606c27SBarry Smith! Compute local gradient contributions over the lower triangular elements 286d8606c27SBarry Smith 287d8606c27SBarry Smith do j = ysm, ye-1 288d8606c27SBarry Smith do i = xsm, xe-1 289d8606c27SBarry Smith k = (j-gys)*gxm + i-gxs 290d8606c27SBarry Smith v = zero 291d8606c27SBarry Smith vr = zero 292d8606c27SBarry Smith vt = zero 293d8606c27SBarry Smith if (i .ge. 0 .and. j .ge. 0) v = lx_v(lx_i+k) 294d8606c27SBarry Smith if (i .lt. mx-1 .and. j .gt. -1) vr = lx_v(lx_i+k+1) 295d8606c27SBarry Smith if (i .gt. -1 .and. j .lt. my-1) vt = lx_v(lx_i+k+gxm) 296d8606c27SBarry Smith dvdx = (vr-v)/hx 297d8606c27SBarry Smith dvdy = (vt-v)/hy 298d8606c27SBarry Smith if (i .ne. -1 .and. j .ne. -1) then 299d8606c27SBarry Smith ind = k 300d8606c27SBarry Smith val = - dvdx/hx - dvdy/hy - cdiv3 301d8606c27SBarry Smith PetscCall(VecSetValuesLocal(G,i1,k,val,ADD_VALUES,ierr)) 302d8606c27SBarry Smith endif 303d8606c27SBarry Smith if (i .ne. mx-1 .and. j .ne. -1) then 304d8606c27SBarry Smith ind = k+1 305d8606c27SBarry Smith val = dvdx/hx - cdiv3 306d8606c27SBarry Smith PetscCall(VecSetValuesLocal(G,i1,ind,val,ADD_VALUES,ierr)) 307d8606c27SBarry Smith endif 308d8606c27SBarry Smith if (i .ne. -1 .and. j .ne. my-1) then 309d8606c27SBarry Smith ind = k+gxm 310d8606c27SBarry Smith val = dvdy/hy - cdiv3 311d8606c27SBarry Smith PetscCall(VecSetValuesLocal(G,i1,ind,val,ADD_VALUES,ierr)) 312d8606c27SBarry Smith endif 313d8606c27SBarry Smith fquad = fquad + dvdx*dvdx + dvdy*dvdy 314d8606c27SBarry Smith flin = flin - cdiv3 * (v+vr+vt) 315d8606c27SBarry Smith end do 316d8606c27SBarry Smith end do 317d8606c27SBarry Smith 318d8606c27SBarry Smith! Compute local gradient contributions over the upper triangular elements 319d8606c27SBarry Smith 320d8606c27SBarry Smith do j = ys, yep-1 321d8606c27SBarry Smith do i = xs, xep-1 322d8606c27SBarry Smith k = (j-gys)*gxm + i-gxs 323d8606c27SBarry Smith vb = zero 324d8606c27SBarry Smith vl = zero 325d8606c27SBarry Smith v = zero 326d8606c27SBarry Smith if (i .lt. mx .and. j .gt. 0) vb = lx_v(lx_i+k-gxm) 327d8606c27SBarry Smith if (i .gt. 0 .and. j .lt. my) vl = lx_v(lx_i+k-1) 328d8606c27SBarry Smith if (i .lt. mx .and. j .lt. my) v = lx_v(lx_i+k) 329d8606c27SBarry Smith dvdx = (v-vl)/hx 330d8606c27SBarry Smith dvdy = (v-vb)/hy 331d8606c27SBarry Smith if (i .ne. mx .and. j .ne. 0) then 332d8606c27SBarry Smith ind = k-gxm 333d8606c27SBarry Smith val = - dvdy/hy - cdiv3 334d8606c27SBarry Smith PetscCall(VecSetValuesLocal(G,i1,ind,val,ADD_VALUES,ierr)) 335d8606c27SBarry Smith endif 336d8606c27SBarry Smith if (i .ne. 0 .and. j .ne. my) then 337d8606c27SBarry Smith ind = k-1 338d8606c27SBarry Smith val = - dvdx/hx - cdiv3 339d8606c27SBarry Smith PetscCall(VecSetValuesLocal(G,i1,ind,val,ADD_VALUES,ierr)) 340d8606c27SBarry Smith endif 341d8606c27SBarry Smith if (i .ne. mx .and. j .ne. my) then 342d8606c27SBarry Smith ind = k 343d8606c27SBarry Smith val = dvdx/hx + dvdy/hy - cdiv3 344d8606c27SBarry Smith PetscCall(VecSetValuesLocal(G,i1,ind,val,ADD_VALUES,ierr)) 345d8606c27SBarry Smith endif 346d8606c27SBarry Smith fquad = fquad + dvdx*dvdx + dvdy*dvdy 347d8606c27SBarry Smith flin = flin - cdiv3*(vb + vl + v) 348d8606c27SBarry Smith end do 349d8606c27SBarry Smith end do 350d8606c27SBarry Smith 351d8606c27SBarry Smith! Restore vector 352d8606c27SBarry Smith PetscCall(VecRestoreArray(localX,lx_v,lx_i,ierr)) 353d8606c27SBarry Smith 354d8606c27SBarry Smith! Assemble gradient vector 355d8606c27SBarry Smith PetscCall(VecAssemblyBegin(G,ierr)) 356d8606c27SBarry Smith PetscCall(VecAssemblyEnd(G,ierr)) 357d8606c27SBarry Smith 358d8606c27SBarry Smith! Scale the gradient 359d8606c27SBarry Smith area = p5*hx*hy 360d8606c27SBarry Smith floc = area *(p5*fquad+flin) 361d8606c27SBarry Smith PetscCall(VecScale(G,area,ierr)) 362d8606c27SBarry Smith 363d8606c27SBarry Smith! Sum function contributions from all processes 364d8606c27SBarry Smith PetscCallMPI(MPI_Allreduce(floc,f,1,MPIU_SCALAR,MPIU_SUM,PETSC_COMM_WORLD,ierr)) 365d8606c27SBarry Smith PetscCall(PetscLogFlops(20.0d0*(ye-ysm)*(xe-xsm)+16.0d0*(xep-xs)*(yep-ys),ierr)) 366d8606c27SBarry Smith return 367d8606c27SBarry Smith end 368d8606c27SBarry Smith 369d8606c27SBarry Smith subroutine ComputeHessian(tao, X, H, Hpre, dummy, ierr) 370*77d968b7SBarry Smith use eptorsion2fmodule 371d8606c27SBarry Smith implicit none 372d8606c27SBarry Smith 373d8606c27SBarry Smith Tao tao 374d8606c27SBarry Smith Vec X 375d8606c27SBarry Smith Mat H,Hpre 376d8606c27SBarry Smith PetscErrorCode ierr 377d8606c27SBarry Smith PetscInt dummy 378d8606c27SBarry Smith 379d8606c27SBarry Smith PetscInt i,j,k 380d8606c27SBarry Smith PetscInt col(0:4),row 381d8606c27SBarry Smith PetscInt xs,xm,gxs,gxm 382d8606c27SBarry Smith PetscInt ys,ym,gys,gym 383d8606c27SBarry Smith PetscReal v(0:4) 384d8606c27SBarry Smith PetscInt i1 385d8606c27SBarry Smith 386d8606c27SBarry Smith i1 = 1 387d8606c27SBarry Smith 388d8606c27SBarry Smith! Get local grid boundaries 389d8606c27SBarry Smith PetscCall(DMDAGetCorners(dm,xs,ys,PETSC_NULL_INTEGER,xm,ym,PETSC_NULL_INTEGER,ierr)) 390d8606c27SBarry Smith PetscCall(DMDAGetGhostCorners(dm,gxs,gys,PETSC_NULL_INTEGER,gxm,gym,PETSC_NULL_INTEGER,ierr)) 391d8606c27SBarry Smith 392d8606c27SBarry Smith do j=ys,ys+ym-1 393d8606c27SBarry Smith do i=xs,xs+xm-1 394d8606c27SBarry Smith row = (j-gys)*gxm + (i-gxs) 395d8606c27SBarry Smith 396d8606c27SBarry Smith k = 0 397d8606c27SBarry Smith if (j .gt. gys) then 398d8606c27SBarry Smith v(k) = -1.0 399d8606c27SBarry Smith col(k) = row-gxm 400d8606c27SBarry Smith k = k + 1 401d8606c27SBarry Smith endif 402d8606c27SBarry Smith 403d8606c27SBarry Smith if (i .gt. gxs) then 404d8606c27SBarry Smith v(k) = -1.0 405d8606c27SBarry Smith col(k) = row - 1 406d8606c27SBarry Smith k = k +1 407d8606c27SBarry Smith endif 408d8606c27SBarry Smith 409d8606c27SBarry Smith v(k) = 4.0 410d8606c27SBarry Smith col(k) = row 411d8606c27SBarry Smith k = k + 1 412d8606c27SBarry Smith 413d8606c27SBarry Smith if (i+1 .lt. gxs + gxm) then 414d8606c27SBarry Smith v(k) = -1.0 415d8606c27SBarry Smith col(k) = row + 1 416d8606c27SBarry Smith k = k + 1 417d8606c27SBarry Smith endif 418d8606c27SBarry Smith 419d8606c27SBarry Smith if (j+1 .lt. gys + gym) then 420d8606c27SBarry Smith v(k) = -1.0 421d8606c27SBarry Smith col(k) = row + gxm 422d8606c27SBarry Smith k = k + 1 423d8606c27SBarry Smith endif 424d8606c27SBarry Smith 425d8606c27SBarry Smith PetscCall(MatSetValuesLocal(H,i1,row,k,col,v,INSERT_VALUES,ierr)) 426d8606c27SBarry Smith enddo 427d8606c27SBarry Smith enddo 428d8606c27SBarry Smith 429d8606c27SBarry Smith! Assemble matrix 430d8606c27SBarry Smith PetscCall(MatAssemblyBegin(H,MAT_FINAL_ASSEMBLY,ierr)) 431d8606c27SBarry Smith PetscCall(MatAssemblyEnd(H,MAT_FINAL_ASSEMBLY,ierr)) 432d8606c27SBarry Smith 433d8606c27SBarry Smith! Tell the matrix we will never add a new nonzero location to the 434d8606c27SBarry Smith! matrix. If we do it will generate an error. 435d8606c27SBarry Smith 436d8606c27SBarry Smith PetscCall(MatSetOption(H,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE,ierr)) 437d8606c27SBarry Smith PetscCall(MatSetOption(H,MAT_SYMMETRIC,PETSC_TRUE,ierr)) 438d8606c27SBarry Smith 439d8606c27SBarry Smith PetscCall(PetscLogFlops(9.0d0*xm*ym + 49.0d0*xm,ierr)) 440d8606c27SBarry Smith 441d8606c27SBarry Smith ierr = 0 442d8606c27SBarry Smith return 443d8606c27SBarry Smith end 444d8606c27SBarry Smith 445d8606c27SBarry Smith subroutine Monitor(tao, dummy, ierr) 446*77d968b7SBarry Smith use eptorsion2fmodule 447d8606c27SBarry Smith implicit none 448d8606c27SBarry Smith 449d8606c27SBarry Smith Tao tao 450d8606c27SBarry Smith PetscInt dummy 451d8606c27SBarry Smith PetscErrorCode ierr 452d8606c27SBarry Smith 453d8606c27SBarry Smith PetscInt its 454d8606c27SBarry Smith PetscReal f,gnorm,cnorm,xdiff 455d8606c27SBarry Smith TaoConvergedReason reason 456d8606c27SBarry Smith 457d8606c27SBarry Smith PetscCall(TaoGetSolutionStatus(tao,its,f,gnorm,cnorm,xdiff,reason,ierr)) 458d8606c27SBarry Smith if (mod(its,5) .ne. 0) then 459d8606c27SBarry Smith PetscCall(PetscPrintf(PETSC_COMM_WORLD,'iteration multiple of 5\n',ierr)) 460d8606c27SBarry Smith endif 461d8606c27SBarry Smith 462d8606c27SBarry Smith ierr = 0 463d8606c27SBarry Smith 464d8606c27SBarry Smith return 465d8606c27SBarry Smith end 466d8606c27SBarry Smith 467d8606c27SBarry Smith subroutine ConvergenceTest(tao, dummy, ierr) 468*77d968b7SBarry Smith use eptorsion2fmodule 469d8606c27SBarry Smith implicit none 470d8606c27SBarry Smith 471d8606c27SBarry Smith Tao tao 472d8606c27SBarry Smith PetscInt dummy 473d8606c27SBarry Smith PetscErrorCode ierr 474d8606c27SBarry Smith 475d8606c27SBarry Smith PetscInt its 476d8606c27SBarry Smith PetscReal f,gnorm,cnorm,xdiff 477d8606c27SBarry Smith TaoConvergedReason reason 478d8606c27SBarry Smith 479d8606c27SBarry Smith PetscCall(TaoGetSolutionStatus(tao,its,f,gnorm,cnorm,xdiff,reason,ierr)) 480d8606c27SBarry Smith if (its .eq. 7) then 481d8606c27SBarry Smith PetscCall(TaoSetConvergedReason(tao,TAO_DIVERGED_MAXITS,ierr)) 482d8606c27SBarry Smith endif 483d8606c27SBarry Smith 484d8606c27SBarry Smith ierr = 0 485d8606c27SBarry Smith 486d8606c27SBarry Smith return 487d8606c27SBarry Smith end 488d8606c27SBarry Smith 489d8606c27SBarry Smith!/*TEST 490d8606c27SBarry Smith! 491d8606c27SBarry Smith! build: 492d8606c27SBarry Smith! requires: !complex 493d8606c27SBarry Smith! 494d8606c27SBarry Smith! test: 495d8606c27SBarry Smith! args: -tao_smonitor -tao_type nls -tao_gttol 1.e-2 496d8606c27SBarry Smith! 497d8606c27SBarry Smith! test: 498d8606c27SBarry Smith! suffix: 2 499d8606c27SBarry Smith! nsize: 2 500d8606c27SBarry Smith! args: -tao_smonitor -tao_type lmvm -tao_gttol 1.e-2 501d8606c27SBarry Smith! 502d8606c27SBarry Smith! test: 503d8606c27SBarry Smith! suffix: 3 504d8606c27SBarry Smith! args: -testmonitor -tao_type lmvm -tao_gttol 1.e-2 505d8606c27SBarry Smith!TEST*/ 506