xref: /petsc/src/tao/unconstrained/tutorials/eptorsion2f.F90 (revision 77d968b72e8e27b79bcc994c018975de390644ed)
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