xref: /petsc/src/tao/unconstrained/tutorials/eptorsion2f.F90 (revision c5e229c2f66f66995aed5443a26600af2aec4a3f)
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! ----------------------------------------------------------------------
25ce78bad3SBarry Smith#include "petsc/finclude/petscdmda.h"
26d8606c27SBarry Smith#include "petsc/finclude/petsctao.h"
27*c5e229c2SMartin Diehlmodule eptorsion2fmodule
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 Smithend module
37d8606c27SBarry Smith
3877d968b7SBarry Smithuse eptorsion2fmodule
39d8606c27SBarry Smithimplicit 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 SmithPetscErrorCode ierr           ! used to check for functions returning nonzeros
47392a88c0SBlaise Bourdintype(tVec) x              ! solution vector
48392a88c0SBlaise Bourdintype(tMat) H              ! hessian matrix
49d8606c27SBarry SmithPetscInt Nx, Ny         ! number of processes in x- and y- directions
50ce78bad3SBarry Smithtype(tTao) ta            ! Tao solver context
51d8606c27SBarry SmithPetscBool flg
52d8606c27SBarry SmithPetscInt i1
53d8606c27SBarry SmithPetscInt dummy
54d8606c27SBarry Smith
55d8606c27SBarry Smith!  Note: Any user-defined Fortran routines (such as FormGradient)
56d8606c27SBarry Smith!  MUST be declared as external.
57d8606c27SBarry Smith
58d8606c27SBarry Smithexternal FormInitialGuess, FormFunctionGradient, ComputeHessian
59d8606c27SBarry Smithexternal Monitor, ConvergenceTest
60d8606c27SBarry Smith
61d8606c27SBarry Smithi1 = 1
62d8606c27SBarry Smith
63d8606c27SBarry Smith!     Initialize TAO, PETSc  contexts
64d8606c27SBarry SmithPetscCallA(PetscInitialize(ierr))
65d8606c27SBarry Smith
66d8606c27SBarry Smith!     Specify default parameters
67d8606c27SBarry Smithparam = 5.0
68d8606c27SBarry Smithmx = 10
69d8606c27SBarry Smithmy = 10
70d8606c27SBarry SmithNx = PETSC_DECIDE
71d8606c27SBarry SmithNy = PETSC_DECIDE
72d8606c27SBarry Smith
73d8606c27SBarry Smith!     Check for any command line arguments that might override defaults
74d8606c27SBarry SmithPetscCallA(PetscOptionsGetInt(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-mx', mx, flg, ierr))
75d8606c27SBarry SmithPetscCallA(PetscOptionsGetInt(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-my', my, flg, ierr))
76d8606c27SBarry SmithPetscCallA(PetscOptionsGetReal(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-par', param, flg, ierr))
77d8606c27SBarry Smith
78d8606c27SBarry Smith!     Set up distributed array and vectors
795d83a8b1SBarry SmithPetscCallA(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 SmithPetscCallA(DMSetFromOptions(dm, ierr))
81d8606c27SBarry SmithPetscCallA(DMSetUp(dm, ierr))
82d8606c27SBarry Smith
83d8606c27SBarry Smith!     Create vectors
84d8606c27SBarry SmithPetscCallA(DMCreateGlobalVector(dm, x, ierr))
85d8606c27SBarry SmithPetscCallA(DMCreateLocalVector(dm, localX, ierr))
86d8606c27SBarry Smith
87d8606c27SBarry Smith!     Create Hessian
88d8606c27SBarry SmithPetscCallA(DMCreateMatrix(dm, H, ierr))
89d8606c27SBarry SmithPetscCallA(MatSetOption(H, MAT_SYMMETRIC, PETSC_TRUE, ierr))
90d8606c27SBarry Smith
91d8606c27SBarry Smith!     The TAO code begins here
92d8606c27SBarry Smith
93d8606c27SBarry Smith!     Create TAO solver
94ce78bad3SBarry SmithPetscCallA(TaoCreate(PETSC_COMM_WORLD, ta, ierr))
95ce78bad3SBarry SmithPetscCallA(TaoSetType(ta, TAOCG, ierr))
96d8606c27SBarry Smith
97d8606c27SBarry Smith!     Set routines for function and gradient evaluation
98d8606c27SBarry Smith
99ce78bad3SBarry SmithPetscCallA(TaoSetObjectiveAndGradient(ta, PETSC_NULL_VEC, FormFunctionGradient, 0, ierr))
100ce78bad3SBarry SmithPetscCallA(TaoSetHessian(ta, H, H, ComputeHessian, 0, ierr))
101d8606c27SBarry Smith
102d8606c27SBarry Smith!     Set initial guess
103d8606c27SBarry SmithPetscCallA(FormInitialGuess(x, ierr))
104ce78bad3SBarry SmithPetscCallA(TaoSetSolution(ta, x, ierr))
105d8606c27SBarry Smith
106d8606c27SBarry SmithPetscCallA(PetscOptionsHasName(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-testmonitor', flg, ierr))
107d8606c27SBarry Smithif (flg) then
108ce78bad3SBarry Smith  PetscCallA(TaoMonitorSet(ta, Monitor, dummy, PETSC_NULL_FUNCTION, ierr))
109d8606c27SBarry Smithend if
110d8606c27SBarry Smith
111d8606c27SBarry SmithPetscCallA(PetscOptionsHasName(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-testconvergence', flg, ierr))
112d8606c27SBarry Smithif (flg) then
113ce78bad3SBarry Smith  PetscCallA(TaoSetConvergenceTest(ta, ConvergenceTest, dummy, ierr))
114d8606c27SBarry Smithend if
115d8606c27SBarry Smith
116d8606c27SBarry Smith!     Check for any TAO command line options
117ce78bad3SBarry SmithPetscCallA(TaoSetFromOptions(ta, ierr))
118d8606c27SBarry Smith
119d8606c27SBarry Smith!     SOLVE THE APPLICATION
120ce78bad3SBarry SmithPetscCallA(TaoSolve(ta, ierr))
121d8606c27SBarry Smith
122d8606c27SBarry Smith!     Free TAO data structures
123ce78bad3SBarry SmithPetscCallA(TaoDestroy(ta, ierr))
124d8606c27SBarry Smith
125d8606c27SBarry Smith!     Free PETSc data structures
126d8606c27SBarry SmithPetscCallA(VecDestroy(x, ierr))
127d8606c27SBarry SmithPetscCallA(VecDestroy(localX, ierr))
128d8606c27SBarry SmithPetscCallA(MatDestroy(H, ierr))
129d8606c27SBarry SmithPetscCallA(DMDestroy(dm, ierr))
130d8606c27SBarry Smith
131d8606c27SBarry Smith!     Finalize TAO and PETSc
132d8606c27SBarry SmithPetscCallA(PetscFinalize(ierr))
133d8606c27SBarry Smithend
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 Smithsubroutine 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)
1775d83a8b1SBarry 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 Smithend
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!
204ce78bad3SBarry Smithsubroutine FormFunctionGradient(ta, X, f, G, dummy, ierr)
20577d968b7SBarry Smith  use eptorsion2fmodule
206d8606c27SBarry Smith  implicit none
207d8606c27SBarry Smith
208d8606c27SBarry Smith!  Input/output variables:
209ce78bad3SBarry Smith  type(tTao) ta
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.
252ce78bad3SBarry Smith  PetscCall(VecGetArrayRead(localX, lx_v, ierr))
253d8606c27SBarry Smith
254d8606c27SBarry Smith!  Set local loop dimensions
255d8606c27SBarry Smith  xe = xs + xm
256d8606c27SBarry Smith  ye = ys + ym
2574820e4eaSBarry Smith  if (xs == 0) then
258d8606c27SBarry Smith    xsm = xs - 1
259d8606c27SBarry Smith  else
260d8606c27SBarry Smith    xsm = xs
261d8606c27SBarry Smith  end if
2624820e4eaSBarry Smith  if (ys == 0) then
263d8606c27SBarry Smith    ysm = ys - 1
264d8606c27SBarry Smith  else
265d8606c27SBarry Smith    ysm = ys
266d8606c27SBarry Smith  end if
2674820e4eaSBarry Smith  if (xe == mx) then
268d8606c27SBarry Smith    xep = xe + 1
269d8606c27SBarry Smith  else
270d8606c27SBarry Smith    xep = xe
271d8606c27SBarry Smith  end if
2724820e4eaSBarry Smith  if (ye == my) then
273d8606c27SBarry Smith    yep = ye + 1
274d8606c27SBarry Smith  else
275d8606c27SBarry Smith    yep = ye
276d8606c27SBarry Smith  end if
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
2864820e4eaSBarry Smith      if (i >= 0 .and. j >= 0) v = lx_v(k + 1)
2874820e4eaSBarry Smith      if (i < mx - 1 .and. j > -1) vr = lx_v(k + 2)
2884820e4eaSBarry Smith      if (i > -1 .and. j < my - 1) vt = lx_v(k + 1 + gxm)
289d8606c27SBarry Smith      dvdx = (vr - v)/hx
290d8606c27SBarry Smith      dvdy = (vt - v)/hy
2914820e4eaSBarry Smith      if (i /= -1 .and. j /= -1) then
292d8606c27SBarry Smith        ind = k
293d8606c27SBarry Smith        val = -dvdx/hx - dvdy/hy - cdiv3
2945d83a8b1SBarry Smith        PetscCall(VecSetValuesLocal(G, i1, [k], [val], ADD_VALUES, ierr))
295d8606c27SBarry Smith      end if
2964820e4eaSBarry Smith      if (i /= mx - 1 .and. j /= -1) then
297d8606c27SBarry Smith        ind = k + 1
298d8606c27SBarry Smith        val = dvdx/hx - cdiv3
2995d83a8b1SBarry Smith        PetscCall(VecSetValuesLocal(G, i1, [ind], [val], ADD_VALUES, ierr))
300d8606c27SBarry Smith      end if
3014820e4eaSBarry Smith      if (i /= -1 .and. j /= my - 1) then
302d8606c27SBarry Smith        ind = k + gxm
303d8606c27SBarry Smith        val = dvdy/hy - cdiv3
3045d83a8b1SBarry Smith        PetscCall(VecSetValuesLocal(G, i1, [ind], [val], ADD_VALUES, ierr))
305d8606c27SBarry Smith      end if
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
3194820e4eaSBarry Smith      if (i < mx .and. j > 0) vb = lx_v(k + 1 - gxm)
3204820e4eaSBarry Smith      if (i > 0 .and. j < my) vl = lx_v(k)
3214820e4eaSBarry Smith      if (i < mx .and. j < my) v = lx_v(1 + k)
322d8606c27SBarry Smith      dvdx = (v - vl)/hx
323d8606c27SBarry Smith      dvdy = (v - vb)/hy
3244820e4eaSBarry Smith      if (i /= mx .and. j /= 0) then
325d8606c27SBarry Smith        ind = k - gxm
326d8606c27SBarry Smith        val = -dvdy/hy - cdiv3
3275d83a8b1SBarry Smith        PetscCall(VecSetValuesLocal(G, i1, [ind], [val], ADD_VALUES, ierr))
328d8606c27SBarry Smith      end if
3294820e4eaSBarry Smith      if (i /= 0 .and. j /= my) then
330d8606c27SBarry Smith        ind = k - 1
331d8606c27SBarry Smith        val = -dvdx/hx - cdiv3
3325d83a8b1SBarry Smith        PetscCall(VecSetValuesLocal(G, i1, [ind], [val], ADD_VALUES, ierr))
333d8606c27SBarry Smith      end if
3344820e4eaSBarry Smith      if (i /= mx .and. j /= my) then
335d8606c27SBarry Smith        ind = k
336d8606c27SBarry Smith        val = dvdx/hx + dvdy/hy - cdiv3
3375d83a8b1SBarry Smith        PetscCall(VecSetValuesLocal(G, i1, [ind], [val], ADD_VALUES, ierr))
338d8606c27SBarry Smith      end if
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
345ce78bad3SBarry Smith  PetscCall(VecRestoreArrayRead(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 Smithend
360d8606c27SBarry Smith
361ce78bad3SBarry Smithsubroutine ComputeHessian(ta, X, H, Hpre, dummy, ierr)
36277d968b7SBarry Smith  use eptorsion2fmodule
363d8606c27SBarry Smith  implicit none
364d8606c27SBarry Smith
365ce78bad3SBarry Smith  type(tTao) ta
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
3894820e4eaSBarry Smith      if (j > gys) then
390d8606c27SBarry Smith        v(k) = -1.0
391d8606c27SBarry Smith        col(k) = row - gxm
392d8606c27SBarry Smith        k = k + 1
393d8606c27SBarry Smith      end if
394d8606c27SBarry Smith
3954820e4eaSBarry Smith      if (i > gxs) then
396d8606c27SBarry Smith        v(k) = -1.0
397d8606c27SBarry Smith        col(k) = row - 1
398d8606c27SBarry Smith        k = k + 1
399d8606c27SBarry Smith      end if
400d8606c27SBarry Smith
401d8606c27SBarry Smith      v(k) = 4.0
402d8606c27SBarry Smith      col(k) = row
403d8606c27SBarry Smith      k = k + 1
404d8606c27SBarry Smith
4054820e4eaSBarry Smith      if (i + 1 < gxs + gxm) then
406d8606c27SBarry Smith        v(k) = -1.0
407d8606c27SBarry Smith        col(k) = row + 1
408d8606c27SBarry Smith        k = k + 1
409d8606c27SBarry Smith      end if
410d8606c27SBarry Smith
4114820e4eaSBarry Smith      if (j + 1 < gys + gym) then
412d8606c27SBarry Smith        v(k) = -1.0
413d8606c27SBarry Smith        col(k) = row + gxm
414d8606c27SBarry Smith        k = k + 1
415d8606c27SBarry Smith      end if
416d8606c27SBarry Smith
4175d83a8b1SBarry Smith      PetscCall(MatSetValuesLocal(H, i1, [row], k, col, v, INSERT_VALUES, ierr))
418d8606c27SBarry Smith    end do
419d8606c27SBarry Smith  end do
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 Smithend
435d8606c27SBarry Smith
436ce78bad3SBarry Smithsubroutine Monitor(ta, dummy, ierr)
43777d968b7SBarry Smith  use eptorsion2fmodule
438d8606c27SBarry Smith  implicit none
439d8606c27SBarry Smith
440ce78bad3SBarry Smith  type(tTao) ta
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
448ce78bad3SBarry Smith  PetscCall(TaoGetSolutionStatus(ta, its, f, gnorm, cnorm, xdiff, reason, ierr))
4494820e4eaSBarry Smith  if (mod(its, 5) /= 0) then
450d8606c27SBarry Smith    PetscCall(PetscPrintf(PETSC_COMM_WORLD, 'iteration multiple of 5\n', ierr))
451d8606c27SBarry Smith  end if
452d8606c27SBarry Smith
453d8606c27SBarry Smith  ierr = 0
454d8606c27SBarry Smith
455d8606c27SBarry Smithend
456d8606c27SBarry Smith
457ce78bad3SBarry Smithsubroutine ConvergenceTest(ta, dummy, ierr)
45877d968b7SBarry Smith  use eptorsion2fmodule
459d8606c27SBarry Smith  implicit none
460d8606c27SBarry Smith
461ce78bad3SBarry Smith  type(tTao) ta
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
469ce78bad3SBarry Smith  PetscCall(TaoGetSolutionStatus(ta, its, f, gnorm, cnorm, xdiff, reason, ierr))
4704820e4eaSBarry Smith  if (its == 7) then
471ce78bad3SBarry Smith    PetscCall(TaoSetConvergedReason(ta, TAO_DIVERGED_MAXITS, ierr))
472d8606c27SBarry Smith  end if
473d8606c27SBarry Smith
474d8606c27SBarry Smith  ierr = 0
475d8606c27SBarry Smith
476d8606c27SBarry Smithend
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