!   E04VHF Example Program Text
!   Mark 23 Release. NAG Copyright 2011.

    MODULE e04vhfe_mod

!      E04VHF Example Program Module:
!             Parameters and User-defined Routines

!      .. Use Statements ..
       USE nag_library, ONLY : nag_wp
!      .. Implicit None Statement ..
       IMPLICIT NONE
!      .. Parameters ..
       INTEGER, PARAMETER                  :: lencw = 600, leniw = 600,        &
                                              lenrw = 600, nin = 5, nout = 6
    CONTAINS
!dec$ attributes offload : mic :: usrfun
       SUBROUTINE usrfun(status,n,x,needf,nf,f,needg,leng,g,cuser,iuser,ruser)

!         .. Implicit None Statement ..
          IMPLICIT NONE
!         .. Scalar Arguments ..
          INTEGER, INTENT (IN)                :: leng, n, needf, needg, nf
          INTEGER, INTENT (INOUT)             :: status
!         .. Array Arguments ..
          REAL (KIND=nag_wp), INTENT (INOUT)  :: f(nf), g(leng), ruser(*)
          REAL (KIND=nag_wp), INTENT (IN)     :: x(n)
          INTEGER, INTENT (INOUT)             :: iuser(*)
          CHARACTER (8), INTENT (INOUT)       :: cuser(*)
!         .. Intrinsic Functions ..
          INTRINSIC                              cos, sin
!         .. Executable Statements ..
          IF (needf>0) THEN

!            The nonlinear components of f_i(x) need to be assigned,
!            for i = 1 to NF

             f(1) = 1000.0E+0_nag_wp*sin(-x(1)-0.25E+0_nag_wp) + &
                1000.0E+0_nag_wp*sin(-x(2)-0.25E+0_nag_wp)
             f(2) = 1000.0E+0_nag_wp*sin(x(1)-0.25E+0_nag_wp) + &
                1000.0E+0_nag_wp*sin(x(1)-x(2)-0.25E+0_nag_wp)
             f(3) = 1000.0E+0_nag_wp*sin(x(2)-x(1)-0.25E+0_nag_wp) + &
                1000.0E+0_nag_wp*sin(x(2)-0.25E+0_nag_wp)

!            N.B. in this example there is no need to assign for the wholly
!            linear components f_4(x) and f_5(x).

             f(6) = 1.0E-6_nag_wp*x(3)**3 + 2.0E-6_nag_wp*x(4)**3/ &
                3.0E+0_nag_wp
          END IF

          IF (needg>0) THEN

!            The derivatives of the function f_i(x) need to be assigned.
!            G(k) should be set to partial derivative df_i(x)/dx_j where
!            i = IGFUN(k) and j = IGVAR(k), for k = 1 to LENG.

             g(1) = -1000.0E+0_nag_wp*cos(-x(1)-0.25E+0_nag_wp)
             g(2) = -1000.0E+0_nag_wp*cos(-x(2)-0.25E+0_nag_wp)
             g(3) = 1000.0E+0_nag_wp*cos(x(1)-0.25E+0_nag_wp) + &
                1000.0E+0_nag_wp*cos(x(1)-x(2)-0.25E+0_nag_wp)
             g(4) = -1000.0E+0_nag_wp*cos(x(1)-x(2)-0.25E+0_nag_wp)
             g(5) = -1000.0E+0_nag_wp*cos(x(2)-x(1)-0.25E+0_nag_wp)
             g(6) = 1000.0E+0_nag_wp*cos(x(2)-x(1)-0.25E+0_nag_wp) + &
                1000.0E+0_nag_wp*cos(x(2)-0.25E+0_nag_wp)
             g(7) = 3.0E-6_nag_wp*x(3)**2
             g(8) = 2.0E-6_nag_wp*x(4)**2
          END IF

          RETURN

!dec$ attributes offload : mic :: usrfun
       END SUBROUTINE usrfun
    END MODULE e04vhfe_mod
    PROGRAM e04vhfe

!      E04VHF Example Main Program

!      .. Use Statements ..
       USE nag_library, ONLY : e04vgf, e04vhf, e04vmf, nag_wp
       USE e04vhfe_mod, ONLY : lencw, leniw, lenrw, nin, nout, usrfun
!      .. Implicit None Statement ..
       IMPLICIT NONE
!      .. Local Scalars ..
       REAL (KIND=nag_wp)                  :: objadd, sinf
       INTEGER                             :: i, ifail, lena, leng, n, nea,    &
                                              neg, nf, nfname, ninf, ns,       &
                                              nxname, objrow, start
       CHARACTER (8)                       :: prob
!      .. Local Arrays ..
       REAL (KIND=nag_wp), ALLOCATABLE     :: a(:), f(:), flow(:), fmul(:),    &
                                              fupp(:), x(:), xlow(:), xmul(:), &
                                              xupp(:)
       REAL (KIND=nag_wp)                  :: ruser(1), rw(lenrw)
       INTEGER, ALLOCATABLE                :: fstate(:), iafun(:), igfun(:),   &
                                              javar(:), jgvar(:), xstate(:)
       INTEGER                             :: iuser(1), iw(leniw)
       CHARACTER (8)                       :: cuser(1), cw(lencw)
       CHARACTER (8), ALLOCATABLE          :: fnames(:), xnames(:)
!      .. Intrinsic Functions ..
       INTRINSIC                              max
!      .. Executable Statements ..
       WRITE (nout,*) 'E04VHF Example Program Results'
       FLUSH (nout)

!      Skip heading in data file
       READ (nin,*)

       READ (nin,*) n, nf
       READ (nin,*) nea, neg, objrow, start
       lena = max(1,nea)
       leng = max(1,neg)
       nxname = n
       nfname = nf
       ALLOCATE (iafun(lena),javar(lena),igfun(leng),jgvar(leng),xstate(n), &
          fstate(nf),a(lena),xlow(n),xupp(n),flow(nf),fupp(nf),x(n),xmul(n), &
          f(nf),fmul(nf),xnames(nxname),fnames(nfname))

!      Read the variable names

       READ (nin,*) xnames(1:nxname)

!      Read the function names

       READ (nin,*) fnames(1:nfname)

!      Read the sparse matrix A, the linear part of F

       DO i = 1, nea

!         For each element read row, column, A(row,column)

          READ (nin,*) iafun(i), javar(i), a(i)
       END DO

!      Read the structure of sparse matrix G, the nonlinear part of F

       DO i = 1, neg

!         For each element read row, column

          READ (nin,*) igfun(i), jgvar(i)
       END DO

!      Read the lower and upper bounds on the variables

       DO i = 1, n
          READ (nin,*) xlow(i), xupp(i)
       END DO

!      Read the lower and upper bounds on the functions

       DO i = 1, nf
          READ (nin,*) flow(i), fupp(i)
       END DO

!      Initialise X, XSTATE, XMUL, F, FSTATE, FMUL

       READ (nin,*) x(1:n)
       READ (nin,*) xstate(1:n)
       READ (nin,*) xmul(1:n)
       READ (nin,*) f(1:nf)
       READ (nin,*) fstate(1:nf)
       READ (nin,*) fmul(1:nf)

       objadd = 0.0E0_nag_wp
       prob = ' '

!      Call E04VGF to initialise E04VHF.

       ifail = 0
       CALL e04vgf(cw,lencw,iw,leniw,rw,lenrw,ifail)

!      By default E04VHF does not print monitoring
!      information. Set the print file unit or the summary
!      file unit to get information.

       ifail = 0
       CALL e04vmf('Print file',nout,cw,iw,rw,ifail)

!      Solve the problem.

       ifail = 0
       CALL e04vhf(start,nf,n,nxname,nfname,objadd,objrow,prob,usrfun,iafun, &
          javar,a,lena,nea,igfun,jgvar,leng,neg,xlow,xupp,xnames,flow,fupp, &
          fnames,x,xstate,xmul,f,fstate,fmul,ns,ninf,sinf,cw,lencw,iw,leniw, &
          rw,lenrw,cuser,iuser,ruser,ifail)

       WRITE (nout,*)
       WRITE (nout,99999) f(objrow)
       WRITE (nout,99998) x(1:n)

99999  FORMAT (1X,'Final objective value = ',F11.1)
99998  FORMAT (1X,'Optimal X = ',7F9.2)
    END PROGRAM e04vhfe
