Actual source code: rosenbrock1f.F90

  1: !  Program usage: mpiexec -n 1 rosenbrock1f [-help] [all TAO options]
  2: !
  3: !  Description:  This example demonstrates use of the TAO package to solve an
  4: !  unconstrained minimization problem on a single processor.  We minimize the
  5: !  extended Rosenbrock function:
  6: !       sum_{i=0}^{n/2-1} (alpha*(x_{2i+1}-x_{2i}^2)^2 + (1-x_{2i})^2)
  7: !
  8: !  The C version of this code is rosenbrock1.c
  9: !

 11: !

 13: ! ----------------------------------------------------------------------
 14: !
 15: #include "petsc/finclude/petsctao.h"
 16: module rosenbrock1fmodule
 17:   use petsctao

 19:   implicit none
 20:   PetscReal alpha
 21:   PetscInt n

 23: contains
 24: ! --------------------------------------------------------------------
 25: !  FormFunctionGradient - Evaluates the function f(X) and gradient G(X)
 26: !
 27: !  Input Parameters:
 28: !  tao - the Tao context
 29: !  X   - input vector
 30: !  dummy - not used
 31: !
 32: !  Output Parameters:
 33: !  G - vector containing the newly evaluated gradient
 34: !  f - function value

 36:   subroutine FormFunctionGradient(ta, X, f, G, dummy, ierr)
 37:     type(tTao) ta
 38:     type(tVec) X, G
 39:     PetscReal, intent(out) :: f
 40:     PetscErrorCode, intent(out) :: ierr
 41:     PetscInt dummy

 43:     PetscReal t1, t2
 44:     PetscInt i, nn
 45:     PetscReal, pointer :: g_v(:), x_v(:)

 47: !   Get pointers to vector data
 48:     PetscCall(VecGetArrayRead(X, x_v, ierr))
 49:     PetscCall(VecGetArray(G, g_v, ierr))

 51:     nn = n/2
 52:     f = 0.0_PETSC_REAL_KIND
 53: !   Compute G(X)
 54:     do i = 0, nn - 1
 55:       t1 = x_v(1 + 2*i + 1) - x_v(1 + 2*i)*x_v(1 + 2*i)
 56:       t2 = 1.0 - x_v(1 + 2*i)
 57:       f = f + alpha*t1**2 + t2**2
 58:       g_v(1 + 2*i) = -4*alpha*t1*x_v(1 + 2*i) - 2.0*t2
 59:       g_v(1 + 2*i + 1) = 2.0*alpha*t1
 60:     end do

 62: !   Restore vectors
 63:     PetscCall(VecRestoreArrayRead(X, x_v, ierr))
 64:     PetscCall(VecRestoreArray(G, g_v, ierr))

 66:     PetscCall(PetscLogFlops(15.0d0*nn, ierr))

 68:   end

 70: !
 71: ! ---------------------------------------------------------------------
 72: !
 73: !  FormHessian - Evaluates Hessian matrix.
 74: !
 75: !  Input Parameters:
 76: !  tao     - the Tao context
 77: !  X       - input vector
 78: !  dummy   - optional user-defined context, as set by SNESSetHessian()
 79: !            (not used here)
 80: !
 81: !  Output Parameters:
 82: !  H      - Hessian matrix
 83: !  PrecH  - optionally different matrix used to compute the preconditioner (not used here)
 84: !  ierr   - error code
 85: !
 86: !  Note: Providing the Hessian may not be necessary.  Only some solvers
 87: !  require this matrix.

 89:   subroutine FormHessian(ta, X, H, PrecH, dummy, ierr)
 90: !  Input/output variables:
 91:     type(tTao) ta
 92:     type(tVec) X
 93:     type(tMat) H, PrecH
 94:     PetscErrorCode, intent(out) :: ierr
 95:     PetscInt dummy

 97:     PetscReal v(0:1, 0:1)
 98:     PetscBool assembled

100: ! PETSc's VecGetArray acts differently in Fortran than it does in C.
101: ! Calling VecGetArray((Vec) X, (PetscReal) x_array(0:1), (PetscOffset) x_index, ierr)
102: ! will return an array of doubles referenced by x_array offset by x_index.
103: !  i.e.,  to reference the kth element of X, use x_array(k + x_index).
104: ! Notice that by declaring the arrays with range (0:1), we are using the C 0-indexing practice.
105:     PetscReal, pointer :: x_v(:)
106:     PetscInt i, nn, ind(0:1)

108: !   Zero existing matrix entries
109:     PetscCall(MatAssembled(H, assembled, ierr))
110:     if (assembled) PetscCall(MatZeroEntries(H, ierr))

112: !   Get a pointer to vector data
113:     PetscCall(VecGetArrayRead(X, x_v, ierr))

115: !   Compute Hessian entries
116:     nn = n/2
117:     do i = 0, nn - 1
118:       v(1, 1) = 2.0*alpha
119:       v(0, 0) = -4.0*alpha*(x_v(1 + 2*i + 1) - 3*x_v(1 + 2*i)*x_v(1 + 2*i)) + 2
120:       v(1, 0) = -4.0*alpha*x_v(1 + 2*i)
121:       v(0, 1) = v(1, 0)
122:       ind(0) = 2*i
123:       ind(1) = 2*i + 1
124:       PetscCall(MatSetValues(H, 2_PETSC_INT_KIND, ind, 2_PETSC_INT_KIND, ind, reshape(v, [2_PETSC_INT_KIND**2]), INSERT_VALUES, ierr))
125:     end do

127: !  Restore vector

129:     PetscCall(VecRestoreArrayRead(X, x_v, ierr))

131: !  Assemble matrix

133:     PetscCall(MatAssemblyBegin(H, MAT_FINAL_ASSEMBLY, ierr))
134:     PetscCall(MatAssemblyEnd(H, MAT_FINAL_ASSEMBLY, ierr))

136:     PetscCall(PetscLogFlops(9.0d0*nn, ierr))

138:   end
139: end module rosenbrock1fmodule

141: program rosenbrock1f
142:   use petsctao
143:   use rosenbrock1fmodule
144:   implicit none

146: ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
147: !                   Variable declarations
148: ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
149: !
150: !  See additional variable declarations in the file rosenbrock1f.h

152:   PetscErrorCode ierr    ! used to check for functions returning nonzeros
153:   type(tVec) x       ! solution vector
154:   type(tMat) H       ! hessian matrix
155:   type(tTao) ta     ! TAO_SOVER context
156:   PetscBool flg
157:   PetscMPIInt size

159: !  Initialize TAO and PETSc
160:   PetscCallA(PetscInitialize(ierr))

162:   PetscCallMPIA(MPI_Comm_size(PETSC_COMM_WORLD, size, ierr))
163:   PetscCheckA(size == 1, PETSC_COMM_SELF, PETSC_ERR_WRONG_MPI_SIZE, 'This is a uniprocessor example only')

165: ! Initialize problem parameters and
166: ! check for command line arguments to override defaults
167:   n = 2
168:   PetscCallA(PetscOptionsGetInt(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-n', n, flg, ierr))
169:   alpha = 99.0d0
170:   PetscCallA(PetscOptionsGetReal(PETSC_NULL_OPTIONS, PETSC_NULL_CHARACTER, '-alpha', alpha, flg, ierr))

172: ! Allocate vectors for the solution and gradient
173:   PetscCallA(VecCreateSeq(PETSC_COMM_SELF, n, x, ierr))

175: ! Allocate storage space for Hessian
176:   PetscCallA(MatCreateSeqBAIJ(PETSC_COMM_SELF, 2_PETSC_INT_KIND, n, n, 1_PETSC_INT_KIND, PETSC_NULL_INTEGER_ARRAY, H, ierr))

178:   PetscCallA(MatSetOption(H, MAT_SYMMETRIC, PETSC_TRUE, ierr))

180: !  The TAO code begins here

182: ! Create TAO solver
183:   PetscCallA(TaoCreate(PETSC_COMM_SELF, ta, ierr))
184:   PetscCallA(TaoSetType(ta, TAOLMVM, ierr))

186: ! Set routines for function, gradient, and hessian evaluation
187:   PetscCallA(TaoSetObjectiveAndGradient(ta, PETSC_NULL_VEC, FormFunctionGradient, 0, ierr))
188:   PetscCallA(TaoSetHessian(ta, H, H, FormHessian, 0, ierr))

190: ! Optional: Set initial guess
191:   PetscCallA(VecSet(x, 0.0_PETSC_REAL_KIND, ierr))
192:   PetscCallA(TaoSetSolution(ta, x, ierr))

194: ! Check for TAO command line options
195:   PetscCallA(TaoSetFromOptions(ta, ierr))

197: ! SOLVE THE APPLICATION
198:   PetscCallA(TaoSolve(ta, ierr))

200: !  TaoView() prints ierr about the TAO solver; the option
201: !      -tao_view
202: !  can alternatively be used to activate this at runtime.
203: !      PetscCallA(TaoView(ta,PETSC_VIEWER_STDOUT_SELF,ierr))

205: ! Free TAO data structures
206:   PetscCallA(TaoDestroy(ta, ierr))

208: ! Free PETSc data structures
209:   PetscCallA(VecDestroy(x, ierr))
210:   PetscCallA(MatDestroy(H, ierr))

212:   PetscCallA(PetscFinalize(ierr))
213: end program rosenbrock1f
214: !
215: !/*TEST
216: !
217: !   build:
218: !      requires: !complex
219: !
220: !   test:
221: !      args: -tao_monitor_short -tao_type ntr -tao_gatol 1.e-5
222: !      requires: !single
223: !
224: !TEST*/