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 2677d968b7SBarry Smith module eptorsion2fmodule 27d8606c27SBarry Smith#include "petsc/finclude/petsctao.h" 28d8606c27SBarry Smith use petscdmda 29d8606c27SBarry Smith use petsctao 30d8606c27SBarry Smith implicit none 31d8606c27SBarry Smith 32392a88c0SBlaise Bourdin type(tVec) localX 33392a88c0SBlaise Bourdin type(tDM) dm 34d8606c27SBarry Smith PetscReal param 35d8606c27SBarry Smith PetscInt mx, my 36d8606c27SBarry Smith end module 37d8606c27SBarry Smith 3877d968b7SBarry 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 47392a88c0SBlaise Bourdin type(tVec) x ! solution vector 48392a88c0SBlaise Bourdin type(tMat) H ! hessian matrix 49d8606c27SBarry Smith PetscInt Nx, Ny ! number of processes in x- and y- directions 50392a88c0SBlaise Bourdin type(tTao) 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 79*5d83a8b1SBarry Smith PetscCallA(DMDACreate2d(PETSC_COMM_WORLD,DM_BOUNDARY_NONE,DM_BOUNDARY_NONE,DMDA_STENCIL_BOX,mx,my,Nx,Ny,i1,i1,PETSC_NULL_INTEGER_ARRAY,PETSC_NULL_INTEGER_ARRAY,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 10810978b7dSBarry Smith PetscCallA(TaoMonitorSet(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) 14777d968b7SBarry 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) 177*5d83a8b1SBarry 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 end 183d8606c27SBarry Smith 184d8606c27SBarry Smith! --------------------------------------------------------------------- 185d8606c27SBarry Smith! 186d8606c27SBarry Smith! FormFunctionGradient - Evaluates gradient G(X). 187d8606c27SBarry Smith! 188d8606c27SBarry Smith! Input Parameters: 189d8606c27SBarry Smith! tao - the Tao context 190d8606c27SBarry Smith! X - input vector 191d8606c27SBarry Smith! dummy - optional user-defined context (not used here) 192d8606c27SBarry Smith! 193d8606c27SBarry Smith! Output Parameters: 194d8606c27SBarry Smith! f - the function value at X 195d8606c27SBarry Smith! G - vector containing the newly evaluated gradient 196d8606c27SBarry Smith! ierr - error code 197d8606c27SBarry Smith! 198d8606c27SBarry Smith! Notes: 199d8606c27SBarry Smith! This routine serves as a wrapper for the lower-level routine 200d8606c27SBarry Smith! "ApplicationGradient", where the actual computations are 201d8606c27SBarry Smith! done using the standard Fortran style of treating the local 202d8606c27SBarry Smith! input vector data as an array over the local mesh. 203d8606c27SBarry Smith! 204d8606c27SBarry Smith subroutine FormFunctionGradient(tao,X,f,G,dummy,ierr) 20577d968b7SBarry Smith use eptorsion2fmodule 206d8606c27SBarry Smith implicit none 207d8606c27SBarry Smith 208d8606c27SBarry Smith! Input/output variables: 209392a88c0SBlaise Bourdin type(tTao) tao 210392a88c0SBlaise Bourdin type(tVec) X, G 211d8606c27SBarry Smith PetscReal f 212d8606c27SBarry Smith PetscErrorCode ierr 213d8606c27SBarry Smith PetscInt dummy 214d8606c27SBarry Smith 215d8606c27SBarry Smith! Declarations for use with local array: 216d8606c27SBarry Smith 21742ce371bSBarry Smith PetscReal, pointer :: lx_v(:) 218d8606c27SBarry Smith 219d8606c27SBarry Smith! Local variables: 220d8606c27SBarry Smith PetscReal zero, p5, area, cdiv3 221d8606c27SBarry Smith PetscReal val, flin, fquad,floc 222d8606c27SBarry Smith PetscReal v, vb, vl, vr, vt, dvdx 223d8606c27SBarry Smith PetscReal dvdy, hx, hy 224d8606c27SBarry Smith PetscInt xe, ye, xsm, ysm 225d8606c27SBarry Smith PetscInt xep, yep, i, j, k, ind 226d8606c27SBarry Smith PetscInt xs, ys, xm, ym 227d8606c27SBarry Smith PetscInt gxs, gys, gxm, gym 228d8606c27SBarry Smith PetscInt i1 229d8606c27SBarry Smith 230d8606c27SBarry Smith i1 = 1 231d8606c27SBarry Smith ierr = 0 232d8606c27SBarry Smith cdiv3 = param/3.0 233d8606c27SBarry Smith zero = 0.0 234d8606c27SBarry Smith p5 = 0.5 235d8606c27SBarry Smith hx = 1.0/real(mx + 1) 236d8606c27SBarry Smith hy = 1.0/real(my + 1) 237d8606c27SBarry Smith fquad = zero 238d8606c27SBarry Smith flin = zero 239d8606c27SBarry Smith 240d8606c27SBarry Smith! Initialize gradient to zero 241d8606c27SBarry Smith PetscCall(VecSet(G,zero,ierr)) 242d8606c27SBarry Smith 243d8606c27SBarry Smith! Scatter ghost points to local vector 244d8606c27SBarry Smith PetscCall(DMGlobalToLocalBegin(dm,X,INSERT_VALUES,localX,ierr)) 245d8606c27SBarry Smith PetscCall(DMGlobalToLocalEnd(dm,X,INSERT_VALUES,localX,ierr)) 246d8606c27SBarry Smith 247d8606c27SBarry Smith! Get corner information 248d8606c27SBarry Smith PetscCall(DMDAGetCorners(dm,xs,ys,PETSC_NULL_INTEGER,xm,ym,PETSC_NULL_INTEGER,ierr)) 249d8606c27SBarry Smith PetscCall(DMDAGetGhostCorners(dm,gxs,gys,PETSC_NULL_INTEGER,gxm,gym,PETSC_NULL_INTEGER,ierr)) 250d8606c27SBarry Smith 251d8606c27SBarry Smith! Get pointer to vector data. 25242ce371bSBarry Smith PetscCall(VecGetArrayReadF90(localX,lx_v,ierr)) 253d8606c27SBarry Smith 254d8606c27SBarry Smith! Set local loop dimensions 255d8606c27SBarry Smith xe = xs+xm 256d8606c27SBarry Smith ye = ys+ym 257d8606c27SBarry Smith if (xs .eq. 0) then 258d8606c27SBarry Smith xsm = xs-1 259d8606c27SBarry Smith else 260d8606c27SBarry Smith xsm = xs 261d8606c27SBarry Smith endif 262d8606c27SBarry Smith if (ys .eq. 0) then 263d8606c27SBarry Smith ysm = ys-1 264d8606c27SBarry Smith else 265d8606c27SBarry Smith ysm = ys 266d8606c27SBarry Smith endif 267d8606c27SBarry Smith if (xe .eq. mx) then 268d8606c27SBarry Smith xep = xe+1 269d8606c27SBarry Smith else 270d8606c27SBarry Smith xep = xe 271d8606c27SBarry Smith endif 272d8606c27SBarry Smith if (ye .eq. my) then 273d8606c27SBarry Smith yep = ye+1 274d8606c27SBarry Smith else 275d8606c27SBarry Smith yep = ye 276d8606c27SBarry Smith endif 277d8606c27SBarry Smith 278d8606c27SBarry Smith! Compute local gradient contributions over the lower triangular elements 279d8606c27SBarry Smith 280d8606c27SBarry Smith do j = ysm, ye-1 281d8606c27SBarry Smith do i = xsm, xe-1 282d8606c27SBarry Smith k = (j-gys)*gxm + i-gxs 283d8606c27SBarry Smith v = zero 284d8606c27SBarry Smith vr = zero 285d8606c27SBarry Smith vt = zero 28642ce371bSBarry Smith if (i .ge. 0 .and. j .ge. 0) v = lx_v(k+1) 28742ce371bSBarry Smith if (i .lt. mx-1 .and. j .gt. -1) vr = lx_v(k+2) 28842ce371bSBarry Smith if (i .gt. -1 .and. j .lt. my-1) vt = lx_v(k+1+gxm) 289d8606c27SBarry Smith dvdx = (vr-v)/hx 290d8606c27SBarry Smith dvdy = (vt-v)/hy 291d8606c27SBarry Smith if (i .ne. -1 .and. j .ne. -1) then 292d8606c27SBarry Smith ind = k 293d8606c27SBarry Smith val = - dvdx/hx - dvdy/hy - cdiv3 294*5d83a8b1SBarry Smith PetscCall(VecSetValuesLocal(G,i1,[k],[val],ADD_VALUES,ierr)) 295d8606c27SBarry Smith endif 296d8606c27SBarry Smith if (i .ne. mx-1 .and. j .ne. -1) then 297d8606c27SBarry Smith ind = k+1 298d8606c27SBarry Smith val = dvdx/hx - cdiv3 299*5d83a8b1SBarry Smith PetscCall(VecSetValuesLocal(G,i1,[ind],[val],ADD_VALUES,ierr)) 300d8606c27SBarry Smith endif 301d8606c27SBarry Smith if (i .ne. -1 .and. j .ne. my-1) then 302d8606c27SBarry Smith ind = k+gxm 303d8606c27SBarry Smith val = dvdy/hy - cdiv3 304*5d83a8b1SBarry Smith PetscCall(VecSetValuesLocal(G,i1,[ind],[val],ADD_VALUES,ierr)) 305d8606c27SBarry Smith endif 306d8606c27SBarry Smith fquad = fquad + dvdx*dvdx + dvdy*dvdy 307d8606c27SBarry Smith flin = flin - cdiv3 * (v+vr+vt) 308d8606c27SBarry Smith end do 309d8606c27SBarry Smith end do 310d8606c27SBarry Smith 311d8606c27SBarry Smith! Compute local gradient contributions over the upper triangular elements 312d8606c27SBarry Smith 313d8606c27SBarry Smith do j = ys, yep-1 314d8606c27SBarry Smith do i = xs, xep-1 315d8606c27SBarry Smith k = (j-gys)*gxm + i-gxs 316d8606c27SBarry Smith vb = zero 317d8606c27SBarry Smith vl = zero 318d8606c27SBarry Smith v = zero 31942ce371bSBarry Smith if (i .lt. mx .and. j .gt. 0) vb = lx_v(k+1-gxm) 32042ce371bSBarry Smith if (i .gt. 0 .and. j .lt. my) vl = lx_v(k) 32142ce371bSBarry Smith if (i .lt. mx .and. j .lt. my) v = lx_v(1+k) 322d8606c27SBarry Smith dvdx = (v-vl)/hx 323d8606c27SBarry Smith dvdy = (v-vb)/hy 324d8606c27SBarry Smith if (i .ne. mx .and. j .ne. 0) then 325d8606c27SBarry Smith ind = k-gxm 326d8606c27SBarry Smith val = - dvdy/hy - cdiv3 327*5d83a8b1SBarry Smith PetscCall(VecSetValuesLocal(G,i1,[ind],[val],ADD_VALUES,ierr)) 328d8606c27SBarry Smith endif 329d8606c27SBarry Smith if (i .ne. 0 .and. j .ne. my) then 330d8606c27SBarry Smith ind = k-1 331d8606c27SBarry Smith val = - dvdx/hx - cdiv3 332*5d83a8b1SBarry Smith PetscCall(VecSetValuesLocal(G,i1,[ind],[val],ADD_VALUES,ierr)) 333d8606c27SBarry Smith endif 334d8606c27SBarry Smith if (i .ne. mx .and. j .ne. my) then 335d8606c27SBarry Smith ind = k 336d8606c27SBarry Smith val = dvdx/hx + dvdy/hy - cdiv3 337*5d83a8b1SBarry Smith PetscCall(VecSetValuesLocal(G,i1,[ind],[val],ADD_VALUES,ierr)) 338d8606c27SBarry Smith endif 339d8606c27SBarry Smith fquad = fquad + dvdx*dvdx + dvdy*dvdy 340d8606c27SBarry Smith flin = flin - cdiv3*(vb + vl + v) 341d8606c27SBarry Smith end do 342d8606c27SBarry Smith end do 343d8606c27SBarry Smith 344d8606c27SBarry Smith! Restore vector 34542ce371bSBarry Smith PetscCall(VecRestoreArrayReadF90(localX,lx_v,ierr)) 346d8606c27SBarry Smith 347d8606c27SBarry Smith! Assemble gradient vector 348d8606c27SBarry Smith PetscCall(VecAssemblyBegin(G,ierr)) 349d8606c27SBarry Smith PetscCall(VecAssemblyEnd(G,ierr)) 350d8606c27SBarry Smith 351d8606c27SBarry Smith! Scale the gradient 352d8606c27SBarry Smith area = p5*hx*hy 353d8606c27SBarry Smith floc = area *(p5*fquad+flin) 354d8606c27SBarry Smith PetscCall(VecScale(G,area,ierr)) 355d8606c27SBarry Smith 356d8606c27SBarry Smith! Sum function contributions from all processes 357d8606c27SBarry Smith PetscCallMPI(MPI_Allreduce(floc,f,1,MPIU_SCALAR,MPIU_SUM,PETSC_COMM_WORLD,ierr)) 358d8606c27SBarry Smith PetscCall(PetscLogFlops(20.0d0*(ye-ysm)*(xe-xsm)+16.0d0*(xep-xs)*(yep-ys),ierr)) 359d8606c27SBarry Smith end 360d8606c27SBarry Smith 361d8606c27SBarry Smith subroutine ComputeHessian(tao, X, H, Hpre, dummy, ierr) 36277d968b7SBarry Smith use eptorsion2fmodule 363d8606c27SBarry Smith implicit none 364d8606c27SBarry Smith 365392a88c0SBlaise Bourdin type(tTao) tao 366392a88c0SBlaise Bourdin type(tVec) X 367392a88c0SBlaise Bourdin type(tMat) H,Hpre 368d8606c27SBarry Smith PetscErrorCode ierr 369d8606c27SBarry Smith PetscInt dummy 370d8606c27SBarry Smith 371d8606c27SBarry Smith PetscInt i,j,k 372d8606c27SBarry Smith PetscInt col(0:4),row 373d8606c27SBarry Smith PetscInt xs,xm,gxs,gxm 374d8606c27SBarry Smith PetscInt ys,ym,gys,gym 375d8606c27SBarry Smith PetscReal v(0:4) 376d8606c27SBarry Smith PetscInt i1 377d8606c27SBarry Smith 378d8606c27SBarry Smith i1 = 1 379d8606c27SBarry Smith 380d8606c27SBarry Smith! Get local grid boundaries 381d8606c27SBarry Smith PetscCall(DMDAGetCorners(dm,xs,ys,PETSC_NULL_INTEGER,xm,ym,PETSC_NULL_INTEGER,ierr)) 382d8606c27SBarry Smith PetscCall(DMDAGetGhostCorners(dm,gxs,gys,PETSC_NULL_INTEGER,gxm,gym,PETSC_NULL_INTEGER,ierr)) 383d8606c27SBarry Smith 384d8606c27SBarry Smith do j=ys,ys+ym-1 385d8606c27SBarry Smith do i=xs,xs+xm-1 386d8606c27SBarry Smith row = (j-gys)*gxm + (i-gxs) 387d8606c27SBarry Smith 388d8606c27SBarry Smith k = 0 389d8606c27SBarry Smith if (j .gt. gys) then 390d8606c27SBarry Smith v(k) = -1.0 391d8606c27SBarry Smith col(k) = row-gxm 392d8606c27SBarry Smith k = k + 1 393d8606c27SBarry Smith endif 394d8606c27SBarry Smith 395d8606c27SBarry Smith if (i .gt. gxs) then 396d8606c27SBarry Smith v(k) = -1.0 397d8606c27SBarry Smith col(k) = row - 1 398d8606c27SBarry Smith k = k +1 399d8606c27SBarry Smith endif 400d8606c27SBarry Smith 401d8606c27SBarry Smith v(k) = 4.0 402d8606c27SBarry Smith col(k) = row 403d8606c27SBarry Smith k = k + 1 404d8606c27SBarry Smith 405d8606c27SBarry Smith if (i+1 .lt. gxs + gxm) then 406d8606c27SBarry Smith v(k) = -1.0 407d8606c27SBarry Smith col(k) = row + 1 408d8606c27SBarry Smith k = k + 1 409d8606c27SBarry Smith endif 410d8606c27SBarry Smith 411d8606c27SBarry Smith if (j+1 .lt. gys + gym) then 412d8606c27SBarry Smith v(k) = -1.0 413d8606c27SBarry Smith col(k) = row + gxm 414d8606c27SBarry Smith k = k + 1 415d8606c27SBarry Smith endif 416d8606c27SBarry Smith 417*5d83a8b1SBarry Smith PetscCall(MatSetValuesLocal(H,i1,[row],k,col,v,INSERT_VALUES,ierr)) 418d8606c27SBarry Smith enddo 419d8606c27SBarry Smith enddo 420d8606c27SBarry Smith 421d8606c27SBarry Smith! Assemble matrix 422d8606c27SBarry Smith PetscCall(MatAssemblyBegin(H,MAT_FINAL_ASSEMBLY,ierr)) 423d8606c27SBarry Smith PetscCall(MatAssemblyEnd(H,MAT_FINAL_ASSEMBLY,ierr)) 424d8606c27SBarry Smith 425d8606c27SBarry Smith! Tell the matrix we will never add a new nonzero location to the 426d8606c27SBarry Smith! matrix. If we do it will generate an error. 427d8606c27SBarry Smith 428d8606c27SBarry Smith PetscCall(MatSetOption(H,MAT_NEW_NONZERO_LOCATION_ERR,PETSC_TRUE,ierr)) 429d8606c27SBarry Smith PetscCall(MatSetOption(H,MAT_SYMMETRIC,PETSC_TRUE,ierr)) 430d8606c27SBarry Smith 431d8606c27SBarry Smith PetscCall(PetscLogFlops(9.0d0*xm*ym + 49.0d0*xm,ierr)) 432d8606c27SBarry Smith 433d8606c27SBarry Smith ierr = 0 434d8606c27SBarry Smith end 435d8606c27SBarry Smith 436d8606c27SBarry Smith subroutine Monitor(tao, dummy, ierr) 43777d968b7SBarry Smith use eptorsion2fmodule 438d8606c27SBarry Smith implicit none 439d8606c27SBarry Smith 440392a88c0SBlaise Bourdin type(tTao) tao 441d8606c27SBarry Smith PetscInt dummy 442d8606c27SBarry Smith PetscErrorCode ierr 443d8606c27SBarry Smith 444d8606c27SBarry Smith PetscInt its 445d8606c27SBarry Smith PetscReal f,gnorm,cnorm,xdiff 446d8606c27SBarry Smith TaoConvergedReason reason 447d8606c27SBarry Smith 448d8606c27SBarry Smith PetscCall(TaoGetSolutionStatus(tao,its,f,gnorm,cnorm,xdiff,reason,ierr)) 449d8606c27SBarry Smith if (mod(its,5) .ne. 0) then 450d8606c27SBarry Smith PetscCall(PetscPrintf(PETSC_COMM_WORLD,'iteration multiple of 5\n',ierr)) 451d8606c27SBarry Smith endif 452d8606c27SBarry Smith 453d8606c27SBarry Smith ierr = 0 454d8606c27SBarry Smith 455d8606c27SBarry Smith end 456d8606c27SBarry Smith 457d8606c27SBarry Smith subroutine ConvergenceTest(tao, dummy, ierr) 45877d968b7SBarry Smith use eptorsion2fmodule 459d8606c27SBarry Smith implicit none 460d8606c27SBarry Smith 461392a88c0SBlaise Bourdin type(tTao) tao 462d8606c27SBarry Smith PetscInt dummy 463d8606c27SBarry Smith PetscErrorCode ierr 464d8606c27SBarry Smith 465d8606c27SBarry Smith PetscInt its 466d8606c27SBarry Smith PetscReal f,gnorm,cnorm,xdiff 467d8606c27SBarry Smith TaoConvergedReason reason 468d8606c27SBarry Smith 469d8606c27SBarry Smith PetscCall(TaoGetSolutionStatus(tao,its,f,gnorm,cnorm,xdiff,reason,ierr)) 470d8606c27SBarry Smith if (its .eq. 7) then 471d8606c27SBarry Smith PetscCall(TaoSetConvergedReason(tao,TAO_DIVERGED_MAXITS,ierr)) 472d8606c27SBarry Smith endif 473d8606c27SBarry Smith 474d8606c27SBarry Smith ierr = 0 475d8606c27SBarry Smith 476d8606c27SBarry Smith end 477d8606c27SBarry Smith 478d8606c27SBarry Smith!/*TEST 479d8606c27SBarry Smith! 480d8606c27SBarry Smith! build: 481d8606c27SBarry Smith! requires: !complex 482d8606c27SBarry Smith! 483d8606c27SBarry Smith! test: 48410978b7dSBarry Smith! args: -tao_monitor_short -tao_type nls -tao_gttol 1.e-2 485d8606c27SBarry Smith! 486d8606c27SBarry Smith! test: 487d8606c27SBarry Smith! suffix: 2 488d8606c27SBarry Smith! nsize: 2 48910978b7dSBarry Smith! args: -tao_monitor_short -tao_type lmvm -tao_gttol 1.e-2 490d8606c27SBarry Smith! 491d8606c27SBarry Smith! test: 492d8606c27SBarry Smith! suffix: 3 493d8606c27SBarry Smith! args: -testmonitor -tao_type lmvm -tao_gttol 1.e-2 494d8606c27SBarry Smith!TEST*/ 495