xref: /petsc/src/tao/unconstrained/tutorials/rosenbrock1f.F90 (revision d8606c274c09e255c003062beb17b1be973467bc)
1c4762a1bSJed Brown!  Program usage: mpiexec -n 1 rosenbrock1f [-help] [all TAO options]
2c4762a1bSJed Brown!
3c4762a1bSJed Brown!  Description:  This example demonstrates use of the TAO package to solve an
4c4762a1bSJed Brown!  unconstrained minimization problem on a single processor.  We minimize the
5c4762a1bSJed Brown!  extended Rosenbrock function:
6c4762a1bSJed Brown!       sum_{i=0}^{n/2-1} (alpha*(x_{2i+1}-x_{2i}^2)^2 + (1-x_{2i})^2)
7c4762a1bSJed Brown!
8c4762a1bSJed Brown!  The C version of this code is rosenbrock1.c
9c4762a1bSJed Brown!
10c4762a1bSJed Brown
11c4762a1bSJed Brown!
12c4762a1bSJed Brown
13c4762a1bSJed Brown! ----------------------------------------------------------------------
14c4762a1bSJed Brown!
15c4762a1bSJed Brown#include "rosenbrock1f.h"
16c4762a1bSJed Brown
17c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
18c4762a1bSJed Brown!                   Variable declarations
19c4762a1bSJed Brown! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
20c4762a1bSJed Brown!
21c4762a1bSJed Brown!  See additional variable declarations in the file rosenbrock1f.h
22c4762a1bSJed Brown
23c4762a1bSJed Brown      PetscErrorCode   ierr    ! used to check for functions returning nonzeros
24c4762a1bSJed Brown      Vec              x       ! solution vector
25c4762a1bSJed Brown      Mat              H       ! hessian matrix
26c4762a1bSJed Brown      Tao        tao     ! TAO_SOVER context
27c4762a1bSJed Brown      PetscBool       flg
28c4762a1bSJed Brown      PetscInt         i2,i1
29c4762a1bSJed Brown      PetscMPIInt     size
30c4762a1bSJed Brown      PetscReal      zero
31c4762a1bSJed Brown
32c4762a1bSJed Brown!  Note: Any user-defined Fortran routines (such as FormGradient)
33c4762a1bSJed Brown!  MUST be declared as external.
34c4762a1bSJed Brown
35c4762a1bSJed Brown      external FormFunctionGradient,FormHessian
36c4762a1bSJed Brown
37c4762a1bSJed Brown      zero = 0.0d0
38c4762a1bSJed Brown      i2 = 2
39c4762a1bSJed Brown      i1 = 1
40c4762a1bSJed Brown
41c4762a1bSJed Brown!  Initialize TAO and PETSc
42*d8606c27SBarry Smith      PetscCallA(PetscInitialize(ierr))
43c4762a1bSJed Brown
44*d8606c27SBarry Smith      PetscCallMPIA(MPI_Comm_size(PETSC_COMM_WORLD,size,ierr))
45c4762a1bSJed Brown      if (size .ne. 1) then; SETERRA(PETSC_COMM_SELF,PETSC_ERR_WRONG_MPI_SIZE,'This is a uniprocessor example only'); endif
46c4762a1bSJed Brown
47c4762a1bSJed Brown!  Initialize problem parameters
48c4762a1bSJed Brown      n     = 2
49c4762a1bSJed Brown      alpha = 99.0d0
50c4762a1bSJed Brown
51c4762a1bSJed Brown! Check for command line arguments to override defaults
52*d8606c27SBarry Smith      PetscCallA(PetscOptionsGetInt(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-n',n,flg,ierr))
53*d8606c27SBarry Smith      PetscCallA(PetscOptionsGetReal(PETSC_NULL_OPTIONS,PETSC_NULL_CHARACTER,'-alpha',alpha,flg,ierr))
54c4762a1bSJed Brown
55c4762a1bSJed Brown!  Allocate vectors for the solution and gradient
56*d8606c27SBarry Smith      PetscCallA(VecCreateSeq(PETSC_COMM_SELF,n,x,ierr))
57c4762a1bSJed Brown
58c4762a1bSJed Brown!  Allocate storage space for Hessian;
59*d8606c27SBarry Smith      PetscCallA(MatCreateSeqBAIJ(PETSC_COMM_SELF,i2,n,n,i1,PETSC_NULL_INTEGER, H,ierr))
60c4762a1bSJed Brown
61*d8606c27SBarry Smith      PetscCallA(MatSetOption(H,MAT_SYMMETRIC,PETSC_TRUE,ierr))
62c4762a1bSJed Brown
63c4762a1bSJed Brown!  The TAO code begins here
64c4762a1bSJed Brown
65c4762a1bSJed Brown!  Create TAO solver
66*d8606c27SBarry Smith      PetscCallA(TaoCreate(PETSC_COMM_SELF,tao,ierr))
67*d8606c27SBarry Smith      PetscCallA(TaoSetType(tao,TAOLMVM,ierr))
68c4762a1bSJed Brown
69c4762a1bSJed Brown!  Set routines for function, gradient, and hessian evaluation
70*d8606c27SBarry Smith      PetscCallA(TaoSetObjectiveAndGradient(tao,PETSC_NULL_VEC,FormFunctionGradient,0,ierr))
71*d8606c27SBarry Smith      PetscCallA(TaoSetHessian(tao,H,H,FormHessian,0,ierr))
72c4762a1bSJed Brown
73c4762a1bSJed Brown!  Optional: Set initial guess
74*d8606c27SBarry Smith      PetscCallA(VecSet(x, zero, ierr))
75*d8606c27SBarry Smith      PetscCallA(TaoSetSolution(tao, x, ierr))
76c4762a1bSJed Brown
77c4762a1bSJed Brown!  Check for TAO command line options
78*d8606c27SBarry Smith      PetscCallA(TaoSetFromOptions(tao,ierr))
79c4762a1bSJed Brown
80c4762a1bSJed Brown!  SOLVE THE APPLICATION
81*d8606c27SBarry Smith      PetscCallA(TaoSolve(tao,ierr))
82c4762a1bSJed Brown
83c4762a1bSJed Brown!  TaoView() prints ierr about the TAO solver; the option
84c4762a1bSJed Brown!      -tao_view
85c4762a1bSJed Brown!  can alternatively be used to activate this at runtime.
86*d8606c27SBarry Smith!      PetscCallA(TaoView(tao,PETSC_VIEWER_STDOUT_SELF,ierr))
87c4762a1bSJed Brown
88c4762a1bSJed Brown!  Free TAO data structures
89*d8606c27SBarry Smith      PetscCallA(TaoDestroy(tao,ierr))
90c4762a1bSJed Brown
91c4762a1bSJed Brown!  Free PETSc data structures
92*d8606c27SBarry Smith      PetscCallA(VecDestroy(x,ierr))
93*d8606c27SBarry Smith      PetscCallA(MatDestroy(H,ierr))
94c4762a1bSJed Brown
95*d8606c27SBarry Smith      PetscCallA(PetscFinalize(ierr))
96c4762a1bSJed Brown      end
97c4762a1bSJed Brown
98c4762a1bSJed Brown! --------------------------------------------------------------------
99c4762a1bSJed Brown!  FormFunctionGradient - Evaluates the function f(X) and gradient G(X)
100c4762a1bSJed Brown!
101c4762a1bSJed Brown!  Input Parameters:
102c4762a1bSJed Brown!  tao - the Tao context
103c4762a1bSJed Brown!  X   - input vector
104c4762a1bSJed Brown!  dummy - not used
105c4762a1bSJed Brown!
106c4762a1bSJed Brown!  Output Parameters:
107c4762a1bSJed Brown!  G - vector containing the newly evaluated gradient
108c4762a1bSJed Brown!  f - function value
109c4762a1bSJed Brown
110c4762a1bSJed Brown      subroutine FormFunctionGradient(tao, X, f, G, dummy, ierr)
111c4762a1bSJed Brown#include "rosenbrock1f.h"
112c4762a1bSJed Brown
113c4762a1bSJed Brown      Tao        tao
114c4762a1bSJed Brown      Vec              X,G
115c4762a1bSJed Brown      PetscReal        f
116c4762a1bSJed Brown      PetscErrorCode   ierr
117c4762a1bSJed Brown      PetscInt         dummy
118c4762a1bSJed Brown
119c4762a1bSJed Brown      PetscReal        ff,t1,t2
120c4762a1bSJed Brown      PetscInt         i,nn
121c4762a1bSJed Brown
122c4762a1bSJed Brown! PETSc's VecGetArray acts differently in Fortran than it does in C.
123c4762a1bSJed Brown! Calling VecGetArray((Vec) X, (PetscReal) x_array(0:1), (PetscOffset) x_index, ierr)
124c4762a1bSJed Brown! will return an array of doubles referenced by x_array offset by x_index.
125c4762a1bSJed Brown!  i.e.,  to reference the kth element of X, use x_array(k + x_index).
126c4762a1bSJed Brown! Notice that by declaring the arrays with range (0:1), we are using the C 0-indexing practice.
127c4762a1bSJed Brown      PetscReal        g_v(0:1),x_v(0:1)
128c4762a1bSJed Brown      PetscOffset      g_i,x_i
129c4762a1bSJed Brown
130c4762a1bSJed Brown      ierr = 0
131c4762a1bSJed Brown      nn = n/2
132c4762a1bSJed Brown      ff = 0
133c4762a1bSJed Brown
134c4762a1bSJed Brown!     Get pointers to vector data
135*d8606c27SBarry Smith      PetscCall(VecGetArrayRead(X,x_v,x_i,ierr))
136*d8606c27SBarry Smith      PetscCall(VecGetArray(G,g_v,g_i,ierr))
137c4762a1bSJed Brown
138c4762a1bSJed Brown!     Compute G(X)
139c4762a1bSJed Brown      do i=0,nn-1
140c4762a1bSJed Brown         t1 = x_v(x_i+2*i+1) - x_v(x_i+2*i)*x_v(x_i+2*i)
141c4762a1bSJed Brown         t2 = 1.0 - x_v(x_i + 2*i)
142c4762a1bSJed Brown         ff = ff + alpha*t1*t1 + t2*t2
143c4762a1bSJed Brown         g_v(g_i + 2*i) = -4*alpha*t1*x_v(x_i + 2*i) - 2.0*t2
144c4762a1bSJed Brown         g_v(g_i + 2*i + 1) = 2.0*alpha*t1
145c4762a1bSJed Brown      enddo
146c4762a1bSJed Brown
147c4762a1bSJed Brown!     Restore vectors
148*d8606c27SBarry Smith      PetscCall(VecRestoreArrayRead(X,x_v,x_i,ierr))
149*d8606c27SBarry Smith      PetscCall(VecRestoreArray(G,g_v,g_i,ierr))
150c4762a1bSJed Brown
151c4762a1bSJed Brown      f = ff
152*d8606c27SBarry Smith      PetscCall(PetscLogFlops(15.0d0*nn,ierr))
153c4762a1bSJed Brown
154c4762a1bSJed Brown      return
155c4762a1bSJed Brown      end
156c4762a1bSJed Brown
157c4762a1bSJed Brown!
158c4762a1bSJed Brown! ---------------------------------------------------------------------
159c4762a1bSJed Brown!
160c4762a1bSJed Brown!  FormHessian - Evaluates Hessian matrix.
161c4762a1bSJed Brown!
162c4762a1bSJed Brown!  Input Parameters:
163c4762a1bSJed Brown!  tao     - the Tao context
164c4762a1bSJed Brown!  X       - input vector
165c4762a1bSJed Brown!  dummy   - optional user-defined context, as set by SNESSetHessian()
166c4762a1bSJed Brown!            (not used here)
167c4762a1bSJed Brown!
168c4762a1bSJed Brown!  Output Parameters:
169c4762a1bSJed Brown!  H      - Hessian matrix
170c4762a1bSJed Brown!  PrecH  - optionally different preconditioning matrix (not used here)
171c4762a1bSJed Brown!  flag   - flag indicating matrix structure
172c4762a1bSJed Brown!  ierr   - error code
173c4762a1bSJed Brown!
174c4762a1bSJed Brown!  Note: Providing the Hessian may not be necessary.  Only some solvers
175c4762a1bSJed Brown!  require this matrix.
176c4762a1bSJed Brown
177c4762a1bSJed Brown      subroutine FormHessian(tao,X,H,PrecH,dummy,ierr)
178c4762a1bSJed Brown#include "rosenbrock1f.h"
179c4762a1bSJed Brown
180c4762a1bSJed Brown!  Input/output variables:
181c4762a1bSJed Brown      Tao        tao
182c4762a1bSJed Brown      Vec              X
183c4762a1bSJed Brown      Mat              H, PrecH
184c4762a1bSJed Brown      PetscErrorCode   ierr
185c4762a1bSJed Brown      PetscInt         dummy
186c4762a1bSJed Brown
187c4762a1bSJed Brown      PetscReal        v(0:1,0:1)
188c4762a1bSJed Brown      PetscBool assembled
189c4762a1bSJed Brown
190c4762a1bSJed Brown! PETSc's VecGetArray acts differently in Fortran than it does in C.
191c4762a1bSJed Brown! Calling VecGetArray((Vec) X, (PetscReal) x_array(0:1), (PetscOffset) x_index, ierr)
192c4762a1bSJed Brown! will return an array of doubles referenced by x_array offset by x_index.
193c4762a1bSJed Brown!  i.e.,  to reference the kth element of X, use x_array(k + x_index).
194c4762a1bSJed Brown! Notice that by declaring the arrays with range (0:1), we are using the C 0-indexing practice.
195c4762a1bSJed Brown      PetscReal        x_v(0:1)
196c4762a1bSJed Brown      PetscOffset      x_i
197c4762a1bSJed Brown      PetscInt         i,nn,ind(0:1),i2
198c4762a1bSJed Brown
199c4762a1bSJed Brown      ierr = 0
200c4762a1bSJed Brown      nn= n/2
201c4762a1bSJed Brown      i2 = 2
202c4762a1bSJed Brown
203c4762a1bSJed Brown!  Zero existing matrix entries
204*d8606c27SBarry Smith      PetscCall(MatAssembled(H,assembled,ierr))
205*d8606c27SBarry Smith      if (assembled .eqv. PETSC_TRUE) PetscCall(MatZeroEntries(H,ierr))
206c4762a1bSJed Brown
207c4762a1bSJed Brown!  Get a pointer to vector data
208c4762a1bSJed Brown
209*d8606c27SBarry Smith      PetscCall(VecGetArrayRead(X,x_v,x_i,ierr))
210c4762a1bSJed Brown
211c4762a1bSJed Brown!  Compute Hessian entries
212c4762a1bSJed Brown
213c4762a1bSJed Brown      do i=0,nn-1
214c4762a1bSJed Brown         v(1,1) = 2.0*alpha
215*d8606c27SBarry Smith         v(0,0) = -4.0*alpha*(x_v(x_i+2*i+1) - 3*x_v(x_i+2*i)*x_v(x_i+2*i))+2
216c4762a1bSJed Brown         v(1,0) = -4.0*alpha*x_v(x_i+2*i)
217c4762a1bSJed Brown         v(0,1) = v(1,0)
218c4762a1bSJed Brown         ind(0) = 2*i
219c4762a1bSJed Brown         ind(1) = 2*i + 1
220*d8606c27SBarry Smith         PetscCall(MatSetValues(H,i2,ind,i2,ind,v,INSERT_VALUES,ierr))
221c4762a1bSJed Brown      enddo
222c4762a1bSJed Brown
223c4762a1bSJed Brown!  Restore vector
224c4762a1bSJed Brown
225*d8606c27SBarry Smith      PetscCall(VecRestoreArrayRead(X,x_v,x_i,ierr))
226c4762a1bSJed Brown
227c4762a1bSJed Brown!  Assemble matrix
228c4762a1bSJed Brown
229*d8606c27SBarry Smith      PetscCall(MatAssemblyBegin(H,MAT_FINAL_ASSEMBLY,ierr))
230*d8606c27SBarry Smith      PetscCall(MatAssemblyEnd(H,MAT_FINAL_ASSEMBLY,ierr))
231c4762a1bSJed Brown
232*d8606c27SBarry Smith      PetscCall(PetscLogFlops(9.0d0*nn,ierr))
233c4762a1bSJed Brown
234c4762a1bSJed Brown      return
235c4762a1bSJed Brown      end
236c4762a1bSJed Brown
237c4762a1bSJed Brown!
238c4762a1bSJed Brown!/*TEST
239c4762a1bSJed Brown!
240c4762a1bSJed Brown!   build:
241c4762a1bSJed Brown!      requires: !complex
242c4762a1bSJed Brown!
243c4762a1bSJed Brown!   test:
244c4762a1bSJed Brown!      args: -tao_smonitor -tao_type ntr -tao_gatol 1.e-5
245c4762a1bSJed Brown!      requires: !single
246c4762a1bSJed Brown!
247c4762a1bSJed Brown!TEST*/
248