xref: /petsc/src/tao/bound/tutorials/plate2f.F90 (revision 5d83a8b16d06840f96948f1a43aa9c83c769a60a)
1c4762a1bSJed Brown!  Program usage: mpiexec -n <proc> plate2f [all TAO options]
2c4762a1bSJed Brown!
3c4762a1bSJed Brown!  This example demonstrates use of the TAO package to solve a bound constrained
4c4762a1bSJed Brown!  minimization problem.  This example is based on a problem from the
5c4762a1bSJed Brown!  MINPACK-2 test suite.  Given a rectangular 2-D domain and boundary values
6c4762a1bSJed Brown!  along the edges of the domain, the objective is to find the surface
7c4762a1bSJed Brown!  with the minimal area that satisfies the boundary conditions.
8c4762a1bSJed Brown!  The command line options are:
9c4762a1bSJed Brown!    -mx <xg>, where <xg> = number of grid points in the 1st coordinate direction
10c4762a1bSJed Brown!    -my <yg>, where <yg> = number of grid points in the 2nd coordinate direction
11c4762a1bSJed Brown!    -bmx <bxg>, where <bxg> = number of grid points under plate in 1st direction
12c4762a1bSJed Brown!    -bmy <byg>, where <byg> = number of grid points under plate in 2nd direction
13c4762a1bSJed Brown!    -bheight <ht>, where <ht> = height of the plate
14c4762a1bSJed Brown!
15c4762a1bSJed Brown
1677d968b7SBarry Smith      module plate2fmodule
17c4762a1bSJed Brown#include "petsc/finclude/petscdmda.h"
18c4762a1bSJed Brown#include "petsc/finclude/petsctao.h"
19c4762a1bSJed Brown      use petscdmda
20c4762a1bSJed Brown      use petsctao
21c4762a1bSJed Brown
22c4762a1bSJed Brown      Vec              localX, localV
23c4762a1bSJed Brown      Vec              Top, Left
24c4762a1bSJed Brown      Vec              Right, Bottom
25c4762a1bSJed Brown      DM               dm
26c4762a1bSJed Brown      PetscReal      bheight
27c4762a1bSJed Brown      PetscInt         bmx, bmy
28c4762a1bSJed Brown      PetscInt         mx, my, Nx, Ny, N
29c4762a1bSJed Brown      end module
30c4762a1bSJed Brown
31c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
32c4762a1bSJed Brown!                   Variable declarations
33c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
34c4762a1bSJed Brown!
35c4762a1bSJed Brown!  Variables:
36c4762a1bSJed Brown!    (common from plate2f.h):
37c4762a1bSJed Brown!    Nx, Ny           number of processors in x- and y- directions
38c4762a1bSJed Brown!    mx, my           number of grid points in x,y directions
39c4762a1bSJed Brown!    N    global dimension of vector
4077d968b7SBarry Smith      use plate2fmodule
41c4762a1bSJed Brown      implicit none
42c4762a1bSJed Brown
43c4762a1bSJed Brown      PetscErrorCode   ierr          ! used to check for functions returning nonzeros
44c4762a1bSJed Brown      Vec              x             ! solution vector
45c4762a1bSJed Brown      PetscInt         m             ! number of local elements in vector
46c4762a1bSJed Brown      Tao              tao           ! Tao solver context
47c4762a1bSJed Brown      Mat              H             ! Hessian matrix
48c4762a1bSJed Brown      ISLocalToGlobalMapping isltog  ! local to global mapping object
49c4762a1bSJed Brown      PetscBool        flg
50c4762a1bSJed Brown      PetscInt         i1,i3,i7
51c4762a1bSJed Brown
52c4762a1bSJed Brown      external FormFunctionGradient
53c4762a1bSJed Brown      external FormHessian
54c4762a1bSJed Brown      external MSA_BoundaryConditions
55c4762a1bSJed Brown      external MSA_Plate
56c4762a1bSJed Brown      external MSA_InitialPoint
57c4762a1bSJed Brown! Initialize Tao
58c4762a1bSJed Brown
59c4762a1bSJed Brown      i1=1
60c4762a1bSJed Brown      i3=3
61c4762a1bSJed Brown      i7=7
62c4762a1bSJed Brown
63d8606c27SBarry Smith      PetscCallA(PetscInitialize(ierr))
64c4762a1bSJed Brown
65c4762a1bSJed Brown! Specify default dimensions of the problem
66c4762a1bSJed Brown      mx = 10
67c4762a1bSJed Brown      my = 10
68c4762a1bSJed Brown      bheight = 0.1
69c4762a1bSJed Brown
70c4762a1bSJed Brown! Check for any command line arguments that override defaults
71c4762a1bSJed Brown
72d8606c27SBarry Smith      PetscCallA(PetscOptionsGetInt(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-mx',mx,flg,ierr))
73d8606c27SBarry Smith      PetscCallA(PetscOptionsGetInt(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-my',my,flg,ierr))
74c4762a1bSJed Brown
75c4762a1bSJed Brown      bmx = mx/2
76c4762a1bSJed Brown      bmy = my/2
77c4762a1bSJed Brown
78d8606c27SBarry Smith      PetscCallA(PetscOptionsGetInt(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-bmx',bmx,flg,ierr))
79d8606c27SBarry Smith      PetscCallA(PetscOptionsGetInt(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-bmy',bmy,flg,ierr))
80d8606c27SBarry Smith      PetscCallA(PetscOptionsGetReal(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-bheight',bheight,flg,ierr))
81c4762a1bSJed Brown
82c4762a1bSJed Brown! Calculate any derived values from parameters
83c4762a1bSJed Brown      N = mx*my
84c4762a1bSJed Brown
85c4762a1bSJed Brown! Let Petsc determine the dimensions of the local vectors
86c4762a1bSJed Brown      Nx = PETSC_DECIDE
87c4762a1bSJed Brown      NY = PETSC_DECIDE
88c4762a1bSJed Brown
89c4762a1bSJed Brown! A two dimensional distributed array will help define this problem, which
90c4762a1bSJed Brown! derives from an elliptic PDE on a two-dimensional domain.  From the
91c4762a1bSJed Brown! distributed array, create the vectors
92c4762a1bSJed Brown
93*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))
94d8606c27SBarry Smith      PetscCallA(DMSetFromOptions(dm,ierr))
95d8606c27SBarry Smith      PetscCallA(DMSetUp(dm,ierr))
96c4762a1bSJed Brown
97c4762a1bSJed Brown! Extract global and local vectors from DM; The local vectors are
98c4762a1bSJed Brown! used solely as work space for the evaluation of the function,
99c4762a1bSJed Brown! gradient, and Hessian.  Duplicate for remaining vectors that are
100c4762a1bSJed Brown! the same types.
101c4762a1bSJed Brown
102d8606c27SBarry Smith      PetscCallA(DMCreateGlobalVector(dm,x,ierr))
103d8606c27SBarry Smith      PetscCallA(DMCreateLocalVector(dm,localX,ierr))
104d8606c27SBarry Smith      PetscCallA(VecDuplicate(localX,localV,ierr))
105c4762a1bSJed Brown
106c4762a1bSJed Brown! Create a matrix data structure to store the Hessian.
107c4762a1bSJed Brown! Here we (optionally) also associate the local numbering scheme
108c4762a1bSJed Brown! with the matrix so that later we can use local indices for matrix
109c4762a1bSJed Brown! assembly
110c4762a1bSJed Brown
111d8606c27SBarry Smith      PetscCallA(VecGetLocalSize(x,m,ierr))
112*5d83a8b1SBarry Smith      PetscCallA(MatCreateAIJ(PETSC_COMM_WORLD,m,m,N,N,i7,PETSC_NULL_INTEGER_ARRAY,i3,PETSC_NULL_INTEGER_ARRAY,H,ierr))
113c4762a1bSJed Brown
114d8606c27SBarry Smith      PetscCallA(MatSetOption(H,MAT_SYMMETRIC,PETSC_TRUE,ierr))
115d8606c27SBarry Smith      PetscCallA(DMGetLocalToGlobalMapping(dm,isltog,ierr))
116d8606c27SBarry Smith      PetscCallA(MatSetLocalToGlobalMapping(H,isltog,isltog,ierr))
117c4762a1bSJed Brown
118c4762a1bSJed Brown! The Tao code begins here
119c4762a1bSJed Brown! Create TAO solver and set desired solution method.
120c4762a1bSJed Brown! This problems uses bounded variables, so the
121c4762a1bSJed Brown! method must either be 'tao_tron' or 'tao_blmvm'
122c4762a1bSJed Brown
123d8606c27SBarry Smith      PetscCallA(TaoCreate(PETSC_COMM_WORLD,tao,ierr))
124d8606c27SBarry Smith      PetscCallA(TaoSetType(tao,TAOBLMVM,ierr))
125c4762a1bSJed Brown
126c4762a1bSJed Brown!     Set minimization function and gradient, hessian evaluation functions
127c4762a1bSJed Brown
128d8606c27SBarry Smith      PetscCallA(TaoSetObjectiveAndGradient(tao,PETSC_NULL_VEC,FormFunctionGradient,0,ierr))
129c4762a1bSJed Brown
130d8606c27SBarry Smith      PetscCallA(TaoSetHessian(tao,H,H,FormHessian,0, ierr))
131c4762a1bSJed Brown
132c4762a1bSJed Brown! Set Variable bounds
133d8606c27SBarry Smith      PetscCallA(MSA_BoundaryConditions(ierr))
134d8606c27SBarry Smith      PetscCallA(TaoSetVariableBoundsRoutine(tao,MSA_Plate,0,ierr))
135c4762a1bSJed Brown
136c4762a1bSJed Brown! Set the initial solution guess
137d8606c27SBarry Smith      PetscCallA(MSA_InitialPoint(x, ierr))
138d8606c27SBarry Smith      PetscCallA(TaoSetSolution(tao,x,ierr))
139c4762a1bSJed Brown
140c4762a1bSJed Brown! Check for any tao command line options
141d8606c27SBarry Smith      PetscCallA(TaoSetFromOptions(tao,ierr))
142c4762a1bSJed Brown
143c4762a1bSJed Brown! Solve the application
144d8606c27SBarry Smith      PetscCallA(TaoSolve(tao,ierr))
145c4762a1bSJed Brown
146c4762a1bSJed Brown! Free TAO data structures
147d8606c27SBarry Smith      PetscCallA(TaoDestroy(tao,ierr))
148c4762a1bSJed Brown
149c4762a1bSJed Brown! Free PETSc data structures
150d8606c27SBarry Smith      PetscCallA(VecDestroy(x,ierr))
151d8606c27SBarry Smith      PetscCallA(VecDestroy(Top,ierr))
152d8606c27SBarry Smith      PetscCallA(VecDestroy(Bottom,ierr))
153d8606c27SBarry Smith      PetscCallA(VecDestroy(Left,ierr))
154d8606c27SBarry Smith      PetscCallA(VecDestroy(Right,ierr))
155d8606c27SBarry Smith      PetscCallA(MatDestroy(H,ierr))
156d8606c27SBarry Smith      PetscCallA(VecDestroy(localX,ierr))
157d8606c27SBarry Smith      PetscCallA(VecDestroy(localV,ierr))
158d8606c27SBarry Smith      PetscCallA(DMDestroy(dm,ierr))
159c4762a1bSJed Brown
160c4762a1bSJed Brown! Finalize TAO
161c4762a1bSJed Brown
162d8606c27SBarry Smith      PetscCallA(PetscFinalize(ierr))
163c4762a1bSJed Brown
164c4762a1bSJed Brown      end
165c4762a1bSJed Brown
166c4762a1bSJed Brown! ---------------------------------------------------------------------
167c4762a1bSJed Brown!
168c4762a1bSJed Brown!  FormFunctionGradient - Evaluates function f(X).
169c4762a1bSJed Brown!
170c4762a1bSJed Brown!  Input Parameters:
171c4762a1bSJed Brown!  tao   - the Tao context
172c4762a1bSJed Brown!  X     - the input vector
173c4762a1bSJed Brown!  dummy - optional user-defined context, as set by TaoSetFunction()
174c4762a1bSJed Brown!          (not used here)
175c4762a1bSJed Brown!
176c4762a1bSJed Brown!  Output Parameters:
177c4762a1bSJed Brown!  fcn     - the newly evaluated function
178c4762a1bSJed Brown!  G       - the gradient vector
179c4762a1bSJed Brown!  info  - error code
180c4762a1bSJed Brown!
181c4762a1bSJed Brown
182c4762a1bSJed Brown      subroutine FormFunctionGradient(tao,X,fcn,G,dummy,ierr)
18377d968b7SBarry Smith      use plate2fmodule
184c4762a1bSJed Brown      implicit none
185c4762a1bSJed Brown
186c4762a1bSJed Brown! Input/output variables
187c4762a1bSJed Brown
188c4762a1bSJed Brown      Tao        tao
189c4762a1bSJed Brown      PetscReal      fcn
190c4762a1bSJed Brown      Vec              X, G
191c4762a1bSJed Brown      PetscErrorCode   ierr
192c4762a1bSJed Brown      PetscInt         dummy
193c4762a1bSJed Brown
194c4762a1bSJed Brown      PetscInt         i,j,row
195c4762a1bSJed Brown      PetscInt         xs, xm
196c4762a1bSJed Brown      PetscInt         gxs, gxm
197c4762a1bSJed Brown      PetscInt         ys, ym
198c4762a1bSJed Brown      PetscInt         gys, gym
199c4762a1bSJed Brown      PetscReal      ft,zero,hx,hy,hydhx,hxdhy
200c4762a1bSJed Brown      PetscReal      area,rhx,rhy
201c4762a1bSJed Brown      PetscReal      f1,f2,f3,f4,f5,f6,d1,d2,d3
202c4762a1bSJed Brown      PetscReal      d4,d5,d6,d7,d8
203c4762a1bSJed Brown      PetscReal      df1dxc,df2dxc,df3dxc,df4dxc
204c4762a1bSJed Brown      PetscReal      df5dxc,df6dxc
205c4762a1bSJed Brown      PetscReal      xc,xl,xr,xt,xb,xlt,xrb
206c4762a1bSJed Brown
20742ce371bSBarry Smith      PetscReal, pointer :: g_v(:),x_v(:)
20842ce371bSBarry Smith      PetscReal, pointer :: top_v(:),left_v(:)
20942ce371bSBarry Smith      PetscReal, pointer :: right_v(:),bottom_v(:)
210c4762a1bSJed Brown
211c4762a1bSJed Brown      ft = 0.0
212c4762a1bSJed Brown      zero = 0.0
213c4762a1bSJed Brown      hx = 1.0/real(mx + 1)
214c4762a1bSJed Brown      hy = 1.0/real(my + 1)
215c4762a1bSJed Brown      hydhx = hy/hx
216c4762a1bSJed Brown      hxdhy = hx/hy
217c4762a1bSJed Brown      area = 0.5 * hx * hy
218c4762a1bSJed Brown      rhx = real(mx) + 1.0
219c4762a1bSJed Brown      rhy = real(my) + 1.0
220c4762a1bSJed Brown
221c4762a1bSJed Brown! Get local mesh boundaries
222d8606c27SBarry Smith      PetscCall(DMDAGetCorners(dm,xs,ys,PETSC_NULL_INTEGER,xm,ym,PETSC_NULL_INTEGER,ierr))
223d8606c27SBarry Smith      PetscCall(DMDAGetGhostCorners(dm,gxs,gys,PETSC_NULL_INTEGER,gxm,gym,PETSC_NULL_INTEGER,ierr))
224c4762a1bSJed Brown
225c4762a1bSJed Brown! Scatter ghost points to local vector
226d8606c27SBarry Smith      PetscCall(DMGlobalToLocalBegin(dm,X,INSERT_VALUES,localX,ierr))
227d8606c27SBarry Smith      PetscCall(DMGlobalToLocalEnd(dm,X,INSERT_VALUES,localX,ierr))
228c4762a1bSJed Brown
229c4762a1bSJed Brown! Initialize the vector to zero
230d8606c27SBarry Smith      PetscCall(VecSet(localV,zero,ierr))
231c4762a1bSJed Brown
23242ce371bSBarry Smith! Get arrays to vector data (See note above about using VecGetArrayF90 in Fortran)
23342ce371bSBarry Smith      PetscCall(VecGetArrayF90(localX,x_v,ierr))
23442ce371bSBarry Smith      PetscCall(VecGetArrayF90(localV,g_v,ierr))
23542ce371bSBarry Smith      PetscCall(VecGetArrayF90(Top,top_v,ierr))
23642ce371bSBarry Smith      PetscCall(VecGetArrayF90(Bottom,bottom_v,ierr))
23742ce371bSBarry Smith      PetscCall(VecGetArrayF90(Left,left_v,ierr))
23842ce371bSBarry Smith      PetscCall(VecGetArrayF90(Right,right_v,ierr))
239c4762a1bSJed Brown
240c4762a1bSJed Brown! Compute function over the locally owned part of the mesh
241c4762a1bSJed Brown      do j = ys,ys+ym-1
242c4762a1bSJed Brown         do i = xs,xs+xm-1
243c4762a1bSJed Brown            row = (j-gys)*gxm + (i-gxs)
24442ce371bSBarry Smith            xc = x_v(1+row)
245c4762a1bSJed Brown            xt = xc
246c4762a1bSJed Brown            xb = xc
247c4762a1bSJed Brown            xr = xc
248c4762a1bSJed Brown            xl = xc
249c4762a1bSJed Brown            xrb = xc
250c4762a1bSJed Brown            xlt = xc
251c4762a1bSJed Brown
252c4762a1bSJed Brown            if (i .eq. 0) then !left side
25342ce371bSBarry Smith               xl = left_v(1+j - ys + 1)
25442ce371bSBarry Smith               xlt = left_v(1+j - ys + 2)
255c4762a1bSJed Brown            else
25642ce371bSBarry Smith               xl = x_v(1+row - 1)
257c4762a1bSJed Brown            endif
258c4762a1bSJed Brown
259c4762a1bSJed Brown            if (j .eq. 0) then !bottom side
26042ce371bSBarry Smith               xb = bottom_v(1+i - xs + 1)
26142ce371bSBarry Smith               xrb = bottom_v(1+i - xs + 2)
262c4762a1bSJed Brown            else
26342ce371bSBarry Smith               xb = x_v(1+row - gxm)
264c4762a1bSJed Brown            endif
265c4762a1bSJed Brown
266c4762a1bSJed Brown            if (i + 1 .eq. gxs + gxm) then !right side
26742ce371bSBarry Smith               xr = right_v(1+j - ys + 1)
26842ce371bSBarry Smith               xrb = right_v(1+j - ys)
269c4762a1bSJed Brown            else
27042ce371bSBarry Smith               xr = x_v(1+row + 1)
271c4762a1bSJed Brown            endif
272c4762a1bSJed Brown
273c4762a1bSJed Brown            if (j + 1 .eq. gys + gym) then !top side
27442ce371bSBarry Smith               xt = top_v(1+i - xs + 1)
27542ce371bSBarry Smith               xlt = top_v(1+i - xs)
276c4762a1bSJed Brown            else
27742ce371bSBarry Smith               xt = x_v(1+row + gxm)
278c4762a1bSJed Brown            endif
279c4762a1bSJed Brown
280c4762a1bSJed Brown            if ((i .gt. gxs) .and. (j + 1 .lt. gys + gym)) then
28142ce371bSBarry Smith               xlt = x_v(1+row - 1 + gxm)
282c4762a1bSJed Brown            endif
283c4762a1bSJed Brown
284c4762a1bSJed Brown            if ((j .gt. gys) .and. (i + 1 .lt. gxs + gxm)) then
28542ce371bSBarry Smith               xrb = x_v(1+row + 1 - gxm)
286c4762a1bSJed Brown            endif
287c4762a1bSJed Brown
288c4762a1bSJed Brown            d1 = xc-xl
289c4762a1bSJed Brown            d2 = xc-xr
290c4762a1bSJed Brown            d3 = xc-xt
291c4762a1bSJed Brown            d4 = xc-xb
292c4762a1bSJed Brown            d5 = xr-xrb
293c4762a1bSJed Brown            d6 = xrb-xb
294c4762a1bSJed Brown            d7 = xlt-xl
295c4762a1bSJed Brown            d8 = xt-xlt
296c4762a1bSJed Brown
297c4762a1bSJed Brown            df1dxc = d1 * hydhx
298c4762a1bSJed Brown            df2dxc = d1 * hydhx + d4 * hxdhy
299c4762a1bSJed Brown            df3dxc = d3 * hxdhy
300c4762a1bSJed Brown            df4dxc = d2 * hydhx + d3 * hxdhy
301c4762a1bSJed Brown            df5dxc = d2 * hydhx
302c4762a1bSJed Brown            df6dxc = d4 * hxdhy
303c4762a1bSJed Brown
304c4762a1bSJed Brown            d1 = d1 * rhx
305c4762a1bSJed Brown            d2 = d2 * rhx
306c4762a1bSJed Brown            d3 = d3 * rhy
307c4762a1bSJed Brown            d4 = d4 * rhy
308c4762a1bSJed Brown            d5 = d5 * rhy
309c4762a1bSJed Brown            d6 = d6 * rhx
310c4762a1bSJed Brown            d7 = d7 * rhy
311c4762a1bSJed Brown            d8 = d8 * rhx
312c4762a1bSJed Brown
313c4762a1bSJed Brown            f1 = sqrt(1.0 + d1*d1 + d7*d7)
314c4762a1bSJed Brown            f2 = sqrt(1.0 + d1*d1 + d4*d4)
315c4762a1bSJed Brown            f3 = sqrt(1.0 + d3*d3 + d8*d8)
316c4762a1bSJed Brown            f4 = sqrt(1.0 + d3*d3 + d2*d2)
317c4762a1bSJed Brown            f5 = sqrt(1.0 + d2*d2 + d5*d5)
318c4762a1bSJed Brown            f6 = sqrt(1.0 + d4*d4 + d6*d6)
319c4762a1bSJed Brown
320c4762a1bSJed Brown            ft = ft + f2 + f4
321c4762a1bSJed Brown
322c4762a1bSJed Brown            df1dxc = df1dxc / f1
323c4762a1bSJed Brown            df2dxc = df2dxc / f2
324c4762a1bSJed Brown            df3dxc = df3dxc / f3
325c4762a1bSJed Brown            df4dxc = df4dxc / f4
326c4762a1bSJed Brown            df5dxc = df5dxc / f5
327c4762a1bSJed Brown            df6dxc = df6dxc / f6
328c4762a1bSJed Brown
32942ce371bSBarry Smith            g_v(1+row) = 0.5 * (df1dxc + df2dxc + df3dxc + df4dxc + df5dxc + df6dxc)
330c4762a1bSJed Brown         enddo
331c4762a1bSJed Brown      enddo
332c4762a1bSJed Brown
333c4762a1bSJed Brown! Compute triangular areas along the border of the domain.
334c4762a1bSJed Brown      if (xs .eq. 0) then  ! left side
335c4762a1bSJed Brown         do j=ys,ys+ym-1
33642ce371bSBarry Smith            d3 = (left_v(1+j-ys+1) - left_v(1+j-ys+2)) * rhy
33742ce371bSBarry Smith            d2 = (left_v(1+j-ys+1) - x_v(1+(j-gys)*gxm)) * rhx
338c4762a1bSJed Brown            ft = ft + sqrt(1.0 + d3*d3 + d2*d2)
339c4762a1bSJed Brown         enddo
340c4762a1bSJed Brown      endif
341c4762a1bSJed Brown
342c4762a1bSJed Brown      if (ys .eq. 0) then !bottom side
343c4762a1bSJed Brown         do i=xs,xs+xm-1
34442ce371bSBarry Smith            d2 = (bottom_v(1+i+1-xs)-bottom_v(1+i-xs+2)) * rhx
34542ce371bSBarry Smith            d3 = (bottom_v(1+i-xs+1)-x_v(1+i-gxs))*rhy
346c4762a1bSJed Brown            ft = ft + sqrt(1.0 + d3*d3 + d2*d2)
347c4762a1bSJed Brown         enddo
348c4762a1bSJed Brown      endif
349c4762a1bSJed Brown
350c4762a1bSJed Brown      if (xs + xm .eq. mx) then ! right side
351c4762a1bSJed Brown         do j=ys,ys+ym-1
35242ce371bSBarry Smith            d1 = (x_v(1+(j+1-gys)*gxm-1)-right_v(1+j-ys+1))*rhx
35342ce371bSBarry Smith            d4 = (right_v(1+j-ys) - right_v(1+j-ys+1))*rhy
354c4762a1bSJed Brown            ft = ft + sqrt(1.0 + d1*d1 + d4*d4)
355c4762a1bSJed Brown         enddo
356c4762a1bSJed Brown      endif
357c4762a1bSJed Brown
358c4762a1bSJed Brown      if (ys + ym .eq. my) then
359c4762a1bSJed Brown         do i=xs,xs+xm-1
36042ce371bSBarry Smith            d1 = (x_v(1+(gym-1)*gxm+i-gxs) - top_v(1+i-xs+1))*rhy
36142ce371bSBarry Smith            d4 = (top_v(1+i-xs+1) - top_v(1+i-xs))*rhx
362c4762a1bSJed Brown            ft = ft + sqrt(1.0 + d1*d1 + d4*d4)
363c4762a1bSJed Brown         enddo
364c4762a1bSJed Brown      endif
365c4762a1bSJed Brown
366c4762a1bSJed Brown      if ((ys .eq. 0) .and. (xs .eq. 0)) then
36742ce371bSBarry Smith         d1 = (left_v(1+0) - left_v(1+1)) * rhy
36842ce371bSBarry Smith         d2 = (bottom_v(1+0)-bottom_v(1+1))*rhx
369c4762a1bSJed Brown         ft = ft + sqrt(1.0 + d1*d1 + d2*d2)
370c4762a1bSJed Brown      endif
371c4762a1bSJed Brown
372c4762a1bSJed Brown      if ((ys + ym .eq. my) .and. (xs + xm .eq. mx)) then
37342ce371bSBarry Smith         d1 = (right_v(1+ym+1) - right_v(1+ym))*rhy
37442ce371bSBarry Smith         d2 = (top_v(1+xm+1) - top_v(1+xm))*rhx
375c4762a1bSJed Brown         ft = ft + sqrt(1.0 + d1*d1 + d2*d2)
376c4762a1bSJed Brown      endif
377c4762a1bSJed Brown
378c4762a1bSJed Brown      ft = ft * area
379d8606c27SBarry Smith      PetscCallMPI(MPI_Allreduce(ft,fcn,1,MPIU_SCALAR,MPIU_SUM,PETSC_COMM_WORLD,ierr))
380c4762a1bSJed Brown
381c4762a1bSJed Brown! Restore vectors
38242ce371bSBarry Smith      PetscCall(VecRestoreArrayF90(localX,x_v,ierr))
38342ce371bSBarry Smith      PetscCall(VecRestoreArrayF90(localV,g_v,ierr))
38442ce371bSBarry Smith      PetscCall(VecRestoreArrayF90(Left,left_v,ierr))
38542ce371bSBarry Smith      PetscCall(VecRestoreArrayF90(Top,top_v,ierr))
38642ce371bSBarry Smith      PetscCall(VecRestoreArrayF90(Bottom,bottom_v,ierr))
38742ce371bSBarry Smith      PetscCall(VecRestoreArrayF90(Right,right_v,ierr))
388c4762a1bSJed Brown
389c4762a1bSJed Brown! Scatter values to global vector
390d8606c27SBarry Smith      PetscCall(DMLocalToGlobalBegin(dm,localV,INSERT_VALUES,G,ierr))
391d8606c27SBarry Smith      PetscCall(DMLocalToGlobalEnd(dm,localV,INSERT_VALUES,G,ierr))
392c4762a1bSJed Brown
393d8606c27SBarry Smith      PetscCall(PetscLogFlops(70.0d0*xm*ym,ierr))
394c4762a1bSJed Brown
395c4762a1bSJed Brown      end  !FormFunctionGradient
396c4762a1bSJed Brown
397c4762a1bSJed Brown! ----------------------------------------------------------------------------
398c4762a1bSJed Brown!
399c4762a1bSJed Brown!
400c4762a1bSJed Brown!   FormHessian - Evaluates Hessian matrix.
401c4762a1bSJed Brown!
402c4762a1bSJed Brown!   Input Parameters:
403c4762a1bSJed Brown!.  tao  - the Tao context
404c4762a1bSJed Brown!.  X    - input vector
405c4762a1bSJed Brown!.  dummy  - not used
406c4762a1bSJed Brown!
407c4762a1bSJed Brown!   Output Parameters:
408c4762a1bSJed Brown!.  Hessian    - Hessian matrix
409c4762a1bSJed Brown!.  Hpc    - optionally different preconditioning matrix
410c4762a1bSJed Brown!.  flag - flag indicating matrix structure
411c4762a1bSJed Brown!
412c4762a1bSJed Brown!   Notes:
413c4762a1bSJed Brown!   Due to mesh point reordering with DMs, we must always work
414c4762a1bSJed Brown!   with the local mesh points, and then transform them to the new
415c4762a1bSJed Brown!   global numbering with the local-to-global mapping.  We cannot work
416c4762a1bSJed Brown!   directly with the global numbers for the original uniprocessor mesh!
417c4762a1bSJed Brown!
418c4762a1bSJed Brown!      MatSetValuesLocal(), using the local ordering (including
419c4762a1bSJed Brown!         ghost points!)
420c4762a1bSJed Brown!         - Then set matrix entries using the local ordering
421c4762a1bSJed Brown!           by calling MatSetValuesLocal()
422c4762a1bSJed Brown
423c4762a1bSJed Brown      subroutine FormHessian(tao, X, Hessian, Hpc, dummy, ierr)
42477d968b7SBarry Smith      use plate2fmodule
425c4762a1bSJed Brown      implicit none
426c4762a1bSJed Brown
427c4762a1bSJed Brown      Tao     tao
428c4762a1bSJed Brown      Vec            X
429c4762a1bSJed Brown      Mat            Hessian,Hpc
430c4762a1bSJed Brown      PetscInt       dummy
431c4762a1bSJed Brown      PetscErrorCode ierr
432c4762a1bSJed Brown
433c4762a1bSJed Brown      PetscInt       i,j,k,row
434c4762a1bSJed Brown      PetscInt       xs,xm,gxs,gxm
435c4762a1bSJed Brown      PetscInt       ys,ym,gys,gym
436c4762a1bSJed Brown      PetscInt       col(0:6)
437c4762a1bSJed Brown      PetscReal    hx,hy,hydhx,hxdhy,rhx,rhy
438c4762a1bSJed Brown      PetscReal    f1,f2,f3,f4,f5,f6,d1,d2,d3
439c4762a1bSJed Brown      PetscReal    d4,d5,d6,d7,d8
440c4762a1bSJed Brown      PetscReal    xc,xl,xr,xt,xb,xlt,xrb
441c4762a1bSJed Brown      PetscReal    hl,hr,ht,hb,hc,htl,hbr
442c4762a1bSJed Brown
44342ce371bSBarry Smith      PetscReal,pointer ::  right_v(:),left_v(:)
44442ce371bSBarry Smith      PetscReal,pointer ::  bottom_v(:),top_v(:)
44542ce371bSBarry Smith      PetscReal,pointer ::  x_v(:)
446c4762a1bSJed Brown      PetscReal   v(0:6)
447c4762a1bSJed Brown      PetscBool     assembled
448c4762a1bSJed Brown      PetscInt      i1
449c4762a1bSJed Brown
450c4762a1bSJed Brown      i1=1
451c4762a1bSJed Brown
452c4762a1bSJed Brown! Set various matrix options
453d8606c27SBarry Smith      PetscCall(MatSetOption(Hessian,MAT_IGNORE_OFF_PROC_ENTRIES,PETSC_TRUE,ierr))
454c4762a1bSJed Brown
455c4762a1bSJed Brown! Get local mesh boundaries
456d8606c27SBarry Smith      PetscCall(DMDAGetCorners(dm,xs,ys,PETSC_NULL_INTEGER,xm,ym,PETSC_NULL_INTEGER,ierr))
457d8606c27SBarry Smith      PetscCall(DMDAGetGhostCorners(dm,gxs,gys,PETSC_NULL_INTEGER,gxm,gym,PETSC_NULL_INTEGER,ierr))
458c4762a1bSJed Brown
459c4762a1bSJed Brown! Scatter ghost points to local vectors
460d8606c27SBarry Smith      PetscCall(DMGlobalToLocalBegin(dm,X,INSERT_VALUES,localX,ierr))
461d8606c27SBarry Smith      PetscCall(DMGlobalToLocalEnd(dm,X,INSERT_VALUES,localX,ierr))
462c4762a1bSJed Brown
463c4762a1bSJed Brown! Get pointers to vector data (see note on Fortran arrays above)
46442ce371bSBarry Smith      PetscCall(VecGetArrayF90(localX,x_v,ierr))
46542ce371bSBarry Smith      PetscCall(VecGetArrayF90(Top,top_v,ierr))
46642ce371bSBarry Smith      PetscCall(VecGetArrayF90(Bottom,bottom_v,ierr))
46742ce371bSBarry Smith      PetscCall(VecGetArrayF90(Left,left_v,ierr))
46842ce371bSBarry Smith      PetscCall(VecGetArrayF90(Right,right_v,ierr))
469c4762a1bSJed Brown
470c4762a1bSJed Brown! Initialize matrix entries to zero
471d8606c27SBarry Smith      PetscCall(MatAssembled(Hessian,assembled,ierr))
472d8606c27SBarry Smith      if (assembled .eqv. PETSC_TRUE) PetscCall(MatZeroEntries(Hessian,ierr))
473c4762a1bSJed Brown
474c4762a1bSJed Brown      rhx = real(mx) + 1.0
475c4762a1bSJed Brown      rhy = real(my) + 1.0
476c4762a1bSJed Brown      hx = 1.0/rhx
477c4762a1bSJed Brown      hy = 1.0/rhy
478c4762a1bSJed Brown      hydhx = hy/hx
479c4762a1bSJed Brown      hxdhy = hx/hy
480c4762a1bSJed Brown! compute Hessian over the locally owned part of the mesh
481c4762a1bSJed Brown
482c4762a1bSJed Brown      do  i=xs,xs+xm-1
483c4762a1bSJed Brown         do  j=ys,ys+ym-1
484c4762a1bSJed Brown            row = (j-gys)*gxm + (i-gxs)
485c4762a1bSJed Brown
48642ce371bSBarry Smith            xc = x_v(1+row)
487c4762a1bSJed Brown            xt = xc
488c4762a1bSJed Brown            xb = xc
489c4762a1bSJed Brown            xr = xc
490c4762a1bSJed Brown            xl = xc
491c4762a1bSJed Brown            xrb = xc
492c4762a1bSJed Brown            xlt = xc
493c4762a1bSJed Brown
494c4762a1bSJed Brown            if (i .eq. gxs) then   ! Left side
49542ce371bSBarry Smith               xl = left_v(1+j - ys + 1)
49642ce371bSBarry Smith               xlt = left_v(1+j - ys + 2)
497c4762a1bSJed Brown            else
49842ce371bSBarry Smith               xl = x_v(1+row -1)
499c4762a1bSJed Brown            endif
500c4762a1bSJed Brown
501c4762a1bSJed Brown            if (j .eq. gys) then ! bottom side
50242ce371bSBarry Smith               xb = bottom_v(1+i - xs + 1)
50342ce371bSBarry Smith               xrb = bottom_v(1+i - xs + 2)
504c4762a1bSJed Brown            else
50542ce371bSBarry Smith               xb = x_v(1+row - gxm)
506c4762a1bSJed Brown            endif
507c4762a1bSJed Brown
508c4762a1bSJed Brown            if (i+1 .eq. gxs + gxm) then !right side
50942ce371bSBarry Smith               xr = right_v(1+j - ys + 1)
51042ce371bSBarry Smith               xrb = right_v(1+j - ys)
511c4762a1bSJed Brown            else
51242ce371bSBarry Smith               xr = x_v(1+row + 1)
513c4762a1bSJed Brown            endif
514c4762a1bSJed Brown
515c4762a1bSJed Brown            if (j+1 .eq. gym+gys) then !top side
51642ce371bSBarry Smith               xt = top_v(1+i - xs + 1)
51742ce371bSBarry Smith               xlt = top_v(1+i - xs)
518c4762a1bSJed Brown            else
51942ce371bSBarry Smith               xt = x_v(1+row + gxm)
520c4762a1bSJed Brown            endif
521c4762a1bSJed Brown
522c4762a1bSJed Brown            if ((i .gt. gxs) .and. (j+1 .lt. gys+gym)) then
52342ce371bSBarry Smith               xlt = x_v(1+row - 1 + gxm)
524c4762a1bSJed Brown            endif
525c4762a1bSJed Brown
526c4762a1bSJed Brown            if ((i+1 .lt. gxs+gxm) .and. (j .gt. gys)) then
52742ce371bSBarry Smith               xrb = x_v(1+row + 1 - gxm)
528c4762a1bSJed Brown            endif
529c4762a1bSJed Brown
530c4762a1bSJed Brown            d1 = (xc-xl)*rhx
531c4762a1bSJed Brown            d2 = (xc-xr)*rhx
532c4762a1bSJed Brown            d3 = (xc-xt)*rhy
533c4762a1bSJed Brown            d4 = (xc-xb)*rhy
534c4762a1bSJed Brown            d5 = (xrb-xr)*rhy
535c4762a1bSJed Brown            d6 = (xrb-xb)*rhx
536c4762a1bSJed Brown            d7 = (xlt-xl)*rhy
537c4762a1bSJed Brown            d8 = (xlt-xt)*rhx
538c4762a1bSJed Brown
539c4762a1bSJed Brown            f1 = sqrt(1.0 + d1*d1 + d7*d7)
540c4762a1bSJed Brown            f2 = sqrt(1.0 + d1*d1 + d4*d4)
541c4762a1bSJed Brown            f3 = sqrt(1.0 + d3*d3 + d8*d8)
542c4762a1bSJed Brown            f4 = sqrt(1.0 + d3*d3 + d2*d2)
543c4762a1bSJed Brown            f5 = sqrt(1.0 + d2*d2 + d5*d5)
544c4762a1bSJed Brown            f6 = sqrt(1.0 + d4*d4 + d6*d6)
545c4762a1bSJed Brown
546d8606c27SBarry Smith            hl = (-hydhx*(1.0+d7*d7)+d1*d7)/(f1*f1*f1)+(-hydhx*(1.0+d4*d4)+d1*d4)/(f2*f2*f2)
547c4762a1bSJed Brown
548d8606c27SBarry Smith            hr = (-hydhx*(1.0+d5*d5)+d2*d5)/(f5*f5*f5)+(-hydhx*(1.0+d3*d3)+d2*d3)/(f4*f4*f4)
549c4762a1bSJed Brown
550d8606c27SBarry Smith            ht = (-hxdhy*(1.0+d8*d8)+d3*d8)/(f3*f3*f3)+(-hxdhy*(1.0+d2*d2)+d2*d3)/(f4*f4*f4)
551c4762a1bSJed Brown
552d8606c27SBarry Smith            hb = (-hxdhy*(1.0+d6*d6)+d4*d6)/(f6*f6*f6)+(-hxdhy*(1.0+d1*d1)+d1*d4)/(f2*f2*f2)
553c4762a1bSJed Brown
554c4762a1bSJed Brown            hbr = -d2*d5/(f5*f5*f5) - d4*d6/(f6*f6*f6)
555c4762a1bSJed Brown            htl = -d1*d7/(f1*f1*f1) - d3*d8/(f3*f3*f3)
556c4762a1bSJed Brown
557d8606c27SBarry Smith            hc = hydhx*(1.0+d7*d7)/(f1*f1*f1) + hxdhy*(1.0+d8*d8)/(f3*f3*f3) + hydhx*(1.0+d5*d5)/(f5*f5*f5) +                      &
558d8606c27SBarry Smith     &           hxdhy*(1.0+d6*d6)/(f6*f6*f6) + (hxdhy*(1.0+d1*d1)+hydhx*(1.0+d4*d4)- 2*d1*d4)/(f2*f2*f2) +  (hxdhy*(1.0+d2*d2)+   &
559c4762a1bSJed Brown     &           hydhx*(1.0+d3*d3)-2*d2*d3)/(f4*f4*f4)
560c4762a1bSJed Brown
561c4762a1bSJed Brown            hl = hl * 0.5
562c4762a1bSJed Brown            hr = hr * 0.5
563c4762a1bSJed Brown            ht = ht * 0.5
564c4762a1bSJed Brown            hb = hb * 0.5
565c4762a1bSJed Brown            hbr = hbr * 0.5
566c4762a1bSJed Brown            htl = htl * 0.5
567c4762a1bSJed Brown            hc = hc * 0.5
568c4762a1bSJed Brown
569c4762a1bSJed Brown            k = 0
570c4762a1bSJed Brown
571c4762a1bSJed Brown            if (j .gt. 0) then
572c4762a1bSJed Brown               v(k) = hb
573c4762a1bSJed Brown               col(k) = row - gxm
574c4762a1bSJed Brown               k=k+1
575c4762a1bSJed Brown            endif
576c4762a1bSJed Brown
577c4762a1bSJed Brown            if ((j .gt. 0) .and. (i .lt. mx-1)) then
578c4762a1bSJed Brown               v(k) = hbr
579c4762a1bSJed Brown               col(k) = row-gxm+1
580c4762a1bSJed Brown               k=k+1
581c4762a1bSJed Brown            endif
582c4762a1bSJed Brown
583c4762a1bSJed Brown            if (i .gt. 0) then
584c4762a1bSJed Brown               v(k) = hl
585c4762a1bSJed Brown               col(k) = row - 1
586c4762a1bSJed Brown               k = k+1
587c4762a1bSJed Brown            endif
588c4762a1bSJed Brown
589c4762a1bSJed Brown            v(k) = hc
590c4762a1bSJed Brown            col(k) = row
591c4762a1bSJed Brown            k=k+1
592c4762a1bSJed Brown
593c4762a1bSJed Brown            if (i .lt. mx-1) then
594c4762a1bSJed Brown               v(k) = hr
595c4762a1bSJed Brown               col(k) = row + 1
596c4762a1bSJed Brown               k=k+1
597c4762a1bSJed Brown            endif
598c4762a1bSJed Brown
599c4762a1bSJed Brown            if ((i .gt. 0) .and. (j .lt. my-1)) then
600c4762a1bSJed Brown               v(k) = htl
601c4762a1bSJed Brown               col(k) = row + gxm - 1
602c4762a1bSJed Brown               k=k+1
603c4762a1bSJed Brown            endif
604c4762a1bSJed Brown
605c4762a1bSJed Brown            if (j .lt. my-1) then
606c4762a1bSJed Brown               v(k) = ht
607c4762a1bSJed Brown               col(k) = row + gxm
608c4762a1bSJed Brown               k=k+1
609c4762a1bSJed Brown            endif
610c4762a1bSJed Brown
611c4762a1bSJed Brown! Set matrix values using local numbering, defined earlier in main routine
612*5d83a8b1SBarry Smith            PetscCall(MatSetValuesLocal(Hessian,i1,[row],k,col,v,INSERT_VALUES,ierr))
613c4762a1bSJed Brown
614c4762a1bSJed Brown         enddo
615c4762a1bSJed Brown      enddo
616c4762a1bSJed Brown
617c4762a1bSJed Brown! restore vectors
61842ce371bSBarry Smith      PetscCall(VecRestoreArrayF90(localX,x_v,ierr))
61942ce371bSBarry Smith      PetscCall(VecRestoreArrayF90(Left,left_v,ierr))
62042ce371bSBarry Smith      PetscCall(VecRestoreArrayF90(Right,right_v,ierr))
62142ce371bSBarry Smith      PetscCall(VecRestoreArrayF90(Top,top_v,ierr))
62242ce371bSBarry Smith      PetscCall(VecRestoreArrayF90(Bottom,bottom_v,ierr))
623c4762a1bSJed Brown
624c4762a1bSJed Brown! Assemble the matrix
625d8606c27SBarry Smith      PetscCall(MatAssemblyBegin(Hessian,MAT_FINAL_ASSEMBLY,ierr))
626d8606c27SBarry Smith      PetscCall(MatAssemblyEnd(Hessian,MAT_FINAL_ASSEMBLY,ierr))
627c4762a1bSJed Brown
628d8606c27SBarry Smith      PetscCall(PetscLogFlops(199.0d0*xm*ym,ierr))
629c4762a1bSJed Brown
630c4762a1bSJed Brown      end
631c4762a1bSJed Brown
632c4762a1bSJed Brown! Top,Left,Right,Bottom,bheight,mx,my,bmx,bmy,H, defined in plate2f.h
633c4762a1bSJed Brown
634c4762a1bSJed Brown! ----------------------------------------------------------------------------
635c4762a1bSJed Brown!
636c4762a1bSJed Brown!/*
637c4762a1bSJed Brown!     MSA_BoundaryConditions - calculates the boundary conditions for the region
638c4762a1bSJed Brown!
639c4762a1bSJed Brown!
640c4762a1bSJed Brown!*/
641c4762a1bSJed Brown
642c4762a1bSJed Brown      subroutine MSA_BoundaryConditions(ierr)
64377d968b7SBarry Smith      use plate2fmodule
644c4762a1bSJed Brown      implicit none
645c4762a1bSJed Brown
646c4762a1bSJed Brown      PetscErrorCode   ierr
647c4762a1bSJed Brown      PetscInt         i,j,k,limit,maxits
648c4762a1bSJed Brown      PetscInt         xs, xm, gxs, gxm
649c4762a1bSJed Brown      PetscInt         ys, ym, gys, gym
650c4762a1bSJed Brown      PetscInt         bsize, lsize
651c4762a1bSJed Brown      PetscInt         tsize, rsize
652c4762a1bSJed Brown      PetscReal      one,two,three,tol
653c4762a1bSJed Brown      PetscReal      scl,fnorm,det,xt
654c4762a1bSJed Brown      PetscReal      yt,hx,hy,u1,u2,nf1,nf2
655c4762a1bSJed Brown      PetscReal      njac11,njac12,njac21,njac22
656c4762a1bSJed Brown      PetscReal      b, t, l, r
65742ce371bSBarry Smith      PetscReal,pointer :: boundary_v(:)
65842ce371bSBarry Smith
659c4762a1bSJed Brown      logical exitloop
660c4762a1bSJed Brown      PetscBool flg
661c4762a1bSJed Brown
662c4762a1bSJed Brown      limit=0
663c4762a1bSJed Brown      maxits = 5
664c4762a1bSJed Brown      tol=1e-10
665c4762a1bSJed Brown      b=-0.5
666c4762a1bSJed Brown      t= 0.5
667c4762a1bSJed Brown      l=-0.5
668c4762a1bSJed Brown      r= 0.5
669c4762a1bSJed Brown      xt=0
670c4762a1bSJed Brown      yt=0
671c4762a1bSJed Brown      one=1.0
672c4762a1bSJed Brown      two=2.0
673c4762a1bSJed Brown      three=3.0
674c4762a1bSJed Brown
675d8606c27SBarry Smith      PetscCall(DMDAGetCorners(dm,xs,ys,PETSC_NULL_INTEGER,xm,ym,PETSC_NULL_INTEGER,ierr))
676d8606c27SBarry Smith      PetscCall(DMDAGetGhostCorners(dm,gxs,gys,PETSC_NULL_INTEGER,gxm,gym,PETSC_NULL_INTEGER,ierr))
677c4762a1bSJed Brown
678c4762a1bSJed Brown      bsize = xm + 2
679c4762a1bSJed Brown      lsize = ym + 2
680c4762a1bSJed Brown      rsize = ym + 2
681c4762a1bSJed Brown      tsize = xm + 2
682c4762a1bSJed Brown
683d8606c27SBarry Smith      PetscCall(VecCreateMPI(PETSC_COMM_WORLD,bsize,PETSC_DECIDE,Bottom,ierr))
684d8606c27SBarry Smith      PetscCall(VecCreateMPI(PETSC_COMM_WORLD,tsize,PETSC_DECIDE,Top,ierr))
685d8606c27SBarry Smith      PetscCall(VecCreateMPI(PETSC_COMM_WORLD,lsize,PETSC_DECIDE,Left,ierr))
686d8606c27SBarry Smith      PetscCall(VecCreateMPI(PETSC_COMM_WORLD,rsize,PETSC_DECIDE,Right,ierr))
687c4762a1bSJed Brown
688c4762a1bSJed Brown      hx= (r-l)/(mx+1)
689c4762a1bSJed Brown      hy= (t-b)/(my+1)
690c4762a1bSJed Brown
691c4762a1bSJed Brown      do j=0,3
692c4762a1bSJed Brown
693c4762a1bSJed Brown         if (j.eq.0) then
694c4762a1bSJed Brown            yt=b
695c4762a1bSJed Brown            xt=l+hx*xs
696c4762a1bSJed Brown            limit=bsize
69742ce371bSBarry Smith            PetscCall(VecGetArrayF90(Bottom,boundary_v,ierr))
698c4762a1bSJed Brown
699c4762a1bSJed Brown         elseif (j.eq.1) then
700c4762a1bSJed Brown            yt=t
701c4762a1bSJed Brown            xt=l+hx*xs
702c4762a1bSJed Brown            limit=tsize
70342ce371bSBarry Smith            PetscCall(VecGetArrayF90(Top,boundary_v,ierr))
704c4762a1bSJed Brown
705c4762a1bSJed Brown         elseif (j.eq.2) then
706c4762a1bSJed Brown            yt=b+hy*ys
707c4762a1bSJed Brown            xt=l
708c4762a1bSJed Brown            limit=lsize
70942ce371bSBarry Smith            PetscCall(VecGetArrayF90(Left,boundary_v,ierr))
710c4762a1bSJed Brown
711c4762a1bSJed Brown         elseif (j.eq.3) then
712c4762a1bSJed Brown            yt=b+hy*ys
713c4762a1bSJed Brown            xt=r
714c4762a1bSJed Brown            limit=rsize
71542ce371bSBarry Smith            PetscCall(VecGetArrayF90(Right,boundary_v,ierr))
716c4762a1bSJed Brown         endif
717c4762a1bSJed Brown
718c4762a1bSJed Brown         do i=0,limit-1
719c4762a1bSJed Brown
720c4762a1bSJed Brown            u1=xt
721c4762a1bSJed Brown            u2=-yt
722c4762a1bSJed Brown            k = 0
723c4762a1bSJed Brown            exitloop = .false.
724c4762a1bSJed Brown            do while (k .lt. maxits .and. (.not. exitloop))
725c4762a1bSJed Brown
726c4762a1bSJed Brown               nf1=u1 + u1*u2*u2 - u1*u1*u1/three-xt
727c4762a1bSJed Brown               nf2=-u2 - u1*u1*u2 + u2*u2*u2/three-yt
728c4762a1bSJed Brown               fnorm=sqrt(nf1*nf1+nf2*nf2)
729c4762a1bSJed Brown               if (fnorm .gt. tol) then
730c4762a1bSJed Brown                  njac11=one+u2*u2-u1*u1
731c4762a1bSJed Brown                  njac12=two*u1*u2
732c4762a1bSJed Brown                  njac21=-two*u1*u2
733c4762a1bSJed Brown                  njac22=-one - u1*u1 + u2*u2
734c4762a1bSJed Brown                  det = njac11*njac22-njac21*njac12
735c4762a1bSJed Brown                  u1 = u1-(njac22*nf1-njac12*nf2)/det
736c4762a1bSJed Brown                  u2 = u2-(njac11*nf2-njac21*nf1)/det
737c4762a1bSJed Brown               else
738c4762a1bSJed Brown                  exitloop = .true.
739c4762a1bSJed Brown               endif
740c4762a1bSJed Brown               k=k+1
741c4762a1bSJed Brown            enddo
742c4762a1bSJed Brown
74342ce371bSBarry Smith            boundary_v(1+i) = u1*u1-u2*u2
744c4762a1bSJed Brown            if ((j .eq. 0) .or. (j .eq. 1)) then
745c4762a1bSJed Brown               xt = xt + hx
746c4762a1bSJed Brown            else
747c4762a1bSJed Brown               yt = yt + hy
748c4762a1bSJed Brown            endif
749c4762a1bSJed Brown
750c4762a1bSJed Brown         enddo
751c4762a1bSJed Brown
752c4762a1bSJed Brown         if (j.eq.0) then
75342ce371bSBarry Smith            PetscCall(VecRestoreArrayF90(Bottom,boundary_v,ierr))
754c4762a1bSJed Brown         elseif (j.eq.1) then
75542ce371bSBarry Smith            PetscCall(VecRestoreArrayF90(Top,boundary_v,ierr))
756c4762a1bSJed Brown         elseif (j.eq.2) then
75742ce371bSBarry Smith            PetscCall(VecRestoreArrayF90(Left,boundary_v,ierr))
758c4762a1bSJed Brown         elseif (j.eq.3) then
75942ce371bSBarry Smith            PetscCall(VecRestoreArrayF90(Right,boundary_v,ierr))
760c4762a1bSJed Brown         endif
761c4762a1bSJed Brown
762c4762a1bSJed Brown      enddo
763c4762a1bSJed Brown
764c4762a1bSJed Brown! Scale the boundary if desired
765d8606c27SBarry Smith      PetscCall(PetscOptionsGetReal(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-bottom',scl,flg,ierr))
766c4762a1bSJed Brown      if (flg .eqv. PETSC_TRUE) then
767d8606c27SBarry Smith         PetscCall(VecScale(Bottom,scl,ierr))
768c4762a1bSJed Brown      endif
769c4762a1bSJed Brown
770d8606c27SBarry Smith      PetscCall(PetscOptionsGetReal(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-top',scl,flg,ierr))
771c4762a1bSJed Brown      if (flg .eqv. PETSC_TRUE) then
772d8606c27SBarry Smith         PetscCall(VecScale(Top,scl,ierr))
773c4762a1bSJed Brown      endif
774c4762a1bSJed Brown
775d8606c27SBarry Smith      PetscCall(PetscOptionsGetReal(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-right',scl,flg,ierr))
776c4762a1bSJed Brown      if (flg .eqv. PETSC_TRUE) then
777d8606c27SBarry Smith         PetscCall(VecScale(Right,scl,ierr))
778c4762a1bSJed Brown      endif
779c4762a1bSJed Brown
780d8606c27SBarry Smith      PetscCall(PetscOptionsGetReal(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-left',scl,flg,ierr))
781c4762a1bSJed Brown      if (flg .eqv. PETSC_TRUE) then
782d8606c27SBarry Smith         PetscCall(VecScale(Left,scl,ierr))
783c4762a1bSJed Brown      endif
784c4762a1bSJed Brown
785c4762a1bSJed Brown      end
786c4762a1bSJed Brown
787c4762a1bSJed Brown! ----------------------------------------------------------------------------
788c4762a1bSJed Brown!
789c4762a1bSJed Brown!/*
790c4762a1bSJed Brown!     MSA_Plate - Calculates an obstacle for surface to stretch over
791c4762a1bSJed Brown!
792c4762a1bSJed Brown!     Output Parameter:
793c4762a1bSJed Brown!.    xl - lower bound vector
794c4762a1bSJed Brown!.    xu - upper bound vector
795c4762a1bSJed Brown!
796c4762a1bSJed Brown!*/
797c4762a1bSJed Brown
798c4762a1bSJed Brown      subroutine MSA_Plate(tao,xl,xu,dummy,ierr)
79977d968b7SBarry Smith      use plate2fmodule
800c4762a1bSJed Brown      implicit none
801c4762a1bSJed Brown
802c4762a1bSJed Brown      Tao        tao
803c4762a1bSJed Brown      Vec              xl,xu
804c4762a1bSJed Brown      PetscErrorCode   ierr
805c4762a1bSJed Brown      PetscInt         i,j,row
806c4762a1bSJed Brown      PetscInt         xs, xm, ys, ym
807c4762a1bSJed Brown      PetscReal      lb,ub
808c4762a1bSJed Brown      PetscInt         dummy
80942ce371bSBarry Smith      PetscReal, pointer :: xl_v(:)
810c4762a1bSJed Brown
811c4762a1bSJed Brown      lb = PETSC_NINFINITY
812c4762a1bSJed Brown      ub = PETSC_INFINITY
813c4762a1bSJed Brown
814c4762a1bSJed Brown      if (bmy .lt. 0) bmy = 0
815c4762a1bSJed Brown      if (bmy .gt. my) bmy = my
816c4762a1bSJed Brown      if (bmx .lt. 0) bmx = 0
817c4762a1bSJed Brown      if (bmx .gt. mx) bmx = mx
818c4762a1bSJed Brown
819d8606c27SBarry Smith      PetscCall(DMDAGetCorners(dm,xs,ys,PETSC_NULL_INTEGER,xm,ym,PETSC_NULL_INTEGER,ierr))
820c4762a1bSJed Brown
821d8606c27SBarry Smith      PetscCall(VecSet(xl,lb,ierr))
822d8606c27SBarry Smith      PetscCall(VecSet(xu,ub,ierr))
823c4762a1bSJed Brown
82442ce371bSBarry Smith      PetscCall(VecGetArrayF90(xl,xl_v,ierr))
825c4762a1bSJed Brown
826c4762a1bSJed Brown      do i=xs,xs+xm-1
827c4762a1bSJed Brown
828c4762a1bSJed Brown         do j=ys,ys+ym-1
829c4762a1bSJed Brown
830c4762a1bSJed Brown            row=(j-ys)*xm + (i-xs)
831c4762a1bSJed Brown
832c4762a1bSJed Brown            if (i.ge.((mx-bmx)/2) .and. i.lt.(mx-(mx-bmx)/2) .and.           &
833c4762a1bSJed Brown     &          j.ge.((my-bmy)/2) .and. j.lt.(my-(my-bmy)/2)) then
83442ce371bSBarry Smith               xl_v(1+row) = bheight
835c4762a1bSJed Brown
836c4762a1bSJed Brown            endif
837c4762a1bSJed Brown
838c4762a1bSJed Brown         enddo
839c4762a1bSJed Brown      enddo
840c4762a1bSJed Brown
84142ce371bSBarry Smith      PetscCall(VecRestoreArrayF90(xl,xl_v,ierr))
842c4762a1bSJed Brown
843c4762a1bSJed Brown      end
844c4762a1bSJed Brown
845c4762a1bSJed Brown! ----------------------------------------------------------------------------
846c4762a1bSJed Brown!
847c4762a1bSJed Brown!/*
848c4762a1bSJed Brown!     MSA_InitialPoint - Calculates an obstacle for surface to stretch over
849c4762a1bSJed Brown!
850c4762a1bSJed Brown!     Output Parameter:
851c4762a1bSJed Brown!.    X - vector for initial guess
852c4762a1bSJed Brown!
853c4762a1bSJed Brown!*/
854c4762a1bSJed Brown
855c4762a1bSJed Brown      subroutine MSA_InitialPoint(X, ierr)
85677d968b7SBarry Smith      use plate2fmodule
857c4762a1bSJed Brown      implicit none
858c4762a1bSJed Brown
859c4762a1bSJed Brown      Vec               X
860c4762a1bSJed Brown      PetscErrorCode    ierr
861c4762a1bSJed Brown      PetscInt          start,i,j
862c4762a1bSJed Brown      PetscInt          row
863c4762a1bSJed Brown      PetscInt          xs,xm,gxs,gxm
864c4762a1bSJed Brown      PetscInt          ys,ym,gys,gym
865c4762a1bSJed Brown      PetscReal       zero, np5
866c4762a1bSJed Brown
86742ce371bSBarry Smith      PetscReal,pointer :: left_v(:),right_v(:)
86842ce371bSBarry Smith      PetscReal,pointer :: bottom_v(:),top_v(:)
86942ce371bSBarry Smith      PetscReal,pointer :: x_v(:)
870c4762a1bSJed Brown      PetscBool     flg
871c4762a1bSJed Brown      PetscRandom   rctx
872c4762a1bSJed Brown
873c4762a1bSJed Brown      zero = 0.0
874c4762a1bSJed Brown      np5 = -0.5
875c4762a1bSJed Brown
876d8606c27SBarry Smith      PetscCall(PetscOptionsGetInt(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-start', start,flg,ierr))
877c4762a1bSJed Brown
878c4762a1bSJed Brown      if ((flg .eqv. PETSC_TRUE) .and. (start .eq. 0)) then  ! the zero vector is reasonable
879d8606c27SBarry Smith         PetscCall(VecSet(X,zero,ierr))
880c4762a1bSJed Brown
881c4762a1bSJed Brown      elseif ((flg .eqv. PETSC_TRUE) .and. (start .gt. 0)) then  ! random start -0.5 < xi < 0.5
882d8606c27SBarry Smith         PetscCall(PetscRandomCreate(PETSC_COMM_WORLD,rctx,ierr))
883c4762a1bSJed Brown         do i=0,start-1
884d8606c27SBarry Smith            PetscCall(VecSetRandom(X,rctx,ierr))
885c4762a1bSJed Brown         enddo
886c4762a1bSJed Brown
887d8606c27SBarry Smith         PetscCall(PetscRandomDestroy(rctx,ierr))
888d8606c27SBarry Smith         PetscCall(VecShift(X,np5,ierr))
889c4762a1bSJed Brown
890c4762a1bSJed Brown      else   ! average of boundary conditions
891c4762a1bSJed Brown
892c4762a1bSJed Brown!        Get Local mesh boundaries
893d8606c27SBarry Smith         PetscCall(DMDAGetCorners(dm,xs,ys,PETSC_NULL_INTEGER,xm,ym,PETSC_NULL_INTEGER,ierr))
894d8606c27SBarry Smith         PetscCall(DMDAGetGhostCorners(dm,gxs,gys,PETSC_NULL_INTEGER,gxm,gym,PETSC_NULL_INTEGER,ierr))
895c4762a1bSJed Brown
896c4762a1bSJed Brown!        Get pointers to vector data
89742ce371bSBarry Smith         PetscCall(VecGetArrayF90(Top,top_v,ierr))
89842ce371bSBarry Smith         PetscCall(VecGetArrayF90(Bottom,bottom_v,ierr))
89942ce371bSBarry Smith         PetscCall(VecGetArrayF90(Left,left_v,ierr))
90042ce371bSBarry Smith         PetscCall(VecGetArrayF90(Right,right_v,ierr))
901c4762a1bSJed Brown
90242ce371bSBarry Smith         PetscCall(VecGetArrayF90(localX,x_v,ierr))
903c4762a1bSJed Brown
904c4762a1bSJed Brown!        Perform local computations
905c4762a1bSJed Brown         do  j=ys,ys+ym-1
906c4762a1bSJed Brown            do i=xs,xs+xm-1
907c4762a1bSJed Brown               row = (j-gys)*gxm  + (i-gxs)
90842ce371bSBarry Smith               x_v(1+row) = ((j+1)*bottom_v(1+i-xs+1)/my + (my-j+1)*top_v(1+i-xs+1)/(my+2) +                  &
90942ce371bSBarry Smith     &                          (i+1)*left_v(1+j-ys+1)/mx + (mx-i+1)*right_v(1+j-ys+1)/(mx+2))*0.5
910c4762a1bSJed Brown            enddo
911c4762a1bSJed Brown         enddo
912c4762a1bSJed Brown
913c4762a1bSJed Brown!        Restore vectors
91442ce371bSBarry Smith         PetscCall(VecRestoreArrayF90(localX,x_v,ierr))
915c4762a1bSJed Brown
91642ce371bSBarry Smith         PetscCall(VecRestoreArrayF90(Left,left_v,ierr))
91742ce371bSBarry Smith         PetscCall(VecRestoreArrayF90(Top,top_v,ierr))
91842ce371bSBarry Smith         PetscCall(VecRestoreArrayF90(Bottom,bottom_v,ierr))
91942ce371bSBarry Smith         PetscCall(VecRestoreArrayF90(Right,right_v,ierr))
920c4762a1bSJed Brown
921d8606c27SBarry Smith         PetscCall(DMLocalToGlobalBegin(dm,localX,INSERT_VALUES,X,ierr))
922d8606c27SBarry Smith         PetscCall(DMLocalToGlobalEnd(dm,localX,INSERT_VALUES,X,ierr))
923c4762a1bSJed Brown
924c4762a1bSJed Brown      endif
925c4762a1bSJed Brown
926c4762a1bSJed Brown      end
927c4762a1bSJed Brown
928c4762a1bSJed Brown!
929c4762a1bSJed Brown!/*TEST
930c4762a1bSJed Brown!
931c4762a1bSJed Brown!   build:
932c4762a1bSJed Brown!      requires: !complex
933c4762a1bSJed Brown!
934c4762a1bSJed Brown!   test:
93510978b7dSBarry Smith!      args: -tao_monitor_short -mx 8 -my 6 -bmx 3 -bmy 3 -bheight 0.2 -tao_type bqnls -tao_gatol 1.e-4
936c4762a1bSJed Brown!      filter: sort -b
937c4762a1bSJed Brown!      filter_output: sort -b
938c4762a1bSJed Brown!      requires: !single
939c4762a1bSJed Brown!
940c4762a1bSJed Brown!   test:
941c4762a1bSJed Brown!      suffix: 2
942c4762a1bSJed Brown!      nsize: 2
94310978b7dSBarry Smith!      args: -tao_monitor_short -mx 8 -my 6 -bmx 3 -bmy 3 -bheight 0.2 -tao_type bqnls -tao_gatol 1.e-4
944c4762a1bSJed Brown!      filter: sort -b
945c4762a1bSJed Brown!      filter_output: sort -b
946c4762a1bSJed Brown!      requires: !single
947c4762a1bSJed Brown!
948c4762a1bSJed Brown!TEST*/
949