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

    MODULE e04uqfe_mod

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

!      .. Use Statements ..
       USE nag_library, ONLY : nag_wp
!      .. Implicit None Statement ..
       IMPLICIT NONE
!      .. Parameters ..
       INTEGER, PARAMETER                  :: iset = 1, nin = 5, ninopt = 7,   &
                                              nout = 6
    CONTAINS
!dec$ attributes offload : mic :: objfun
       SUBROUTINE objfun(mode,m,n,ldfj,needfi,x,f,fjac,nstate,iuser,ruser)
!         Routine to evaluate the subfunctions and their 1st derivatives.

!         .. Implicit None Statement ..
          IMPLICIT NONE
!         .. Parameters ..
          REAL (KIND=nag_wp), PARAMETER       :: a(44) = (/ 8.0E0_nag_wp,      &
                                                 8.0E0_nag_wp, 10.0E0_nag_wp,  &
                                                 10.0E0_nag_wp, 10.0E0_nag_wp, &
                                                 10.0E0_nag_wp, 12.0E0_nag_wp, &
                                                 12.0E0_nag_wp, 12.0E0_nag_wp, &
                                                 12.0E0_nag_wp, 14.0E0_nag_wp, &
                                                 14.0E0_nag_wp, 14.0E0_nag_wp, &
                                                 16.0E0_nag_wp, 16.0E0_nag_wp, &
                                                 16.0E0_nag_wp, 18.0E0_nag_wp, &
                                                 18.0E0_nag_wp, 20.0E0_nag_wp, &
                                                 20.0E0_nag_wp, 20.0E0_nag_wp, &
                                                 22.0E0_nag_wp, 22.0E0_nag_wp, &
                                                 22.0E0_nag_wp, 24.0E0_nag_wp, &
                                                 24.0E0_nag_wp, 24.0E0_nag_wp, &
                                                 26.0E0_nag_wp, 26.0E0_nag_wp, &
                                                 26.0E0_nag_wp, 28.0E0_nag_wp, &
                                                 28.0E0_nag_wp, 30.0E0_nag_wp, &
                                                 30.0E0_nag_wp, 30.0E0_nag_wp, &
                                                 32.0E0_nag_wp, 32.0E0_nag_wp, &
                                                 34.0E0_nag_wp, 36.0E0_nag_wp, &
                                                 36.0E0_nag_wp, 38.0E0_nag_wp, &
                                                 38.0E0_nag_wp, 40.0E0_nag_wp, &
                                                 42.0E0_nag_wp/)
!         .. Scalar Arguments ..
          INTEGER, INTENT (IN)                :: ldfj, m, n, needfi, nstate
          INTEGER, INTENT (INOUT)             :: mode
!         .. Array Arguments ..
          REAL (KIND=nag_wp), INTENT (OUT)    :: f(m)
          REAL (KIND=nag_wp), INTENT (INOUT)  :: fjac(ldfj,n), ruser(*)
          REAL (KIND=nag_wp), INTENT (IN)     :: x(n)
          INTEGER, INTENT (INOUT)             :: iuser(*)
!         .. Local Scalars ..
          REAL (KIND=nag_wp)                  :: ai, temp, x1, x2
          INTEGER                             :: i
          LOGICAL                             :: mode02, mode12
!         .. Intrinsic Functions ..
          INTRINSIC                              exp
!         .. Executable Statements ..
          x1 = x(1)
          x2 = x(2)

          mode02 = (mode==0 .OR. mode==2)
          mode12 = (mode==1 .OR. mode==2)

LOOP:     DO i = 1, m

             IF (needfi==i) THEN
                f(i) = x1 + (0.49E0_nag_wp-x1)*exp(-x2*(a(i)-8.0E0_nag_wp))
                EXIT LOOP
             END IF

             ai = a(i)
             temp = exp(-x2*(ai-8.0E0_nag_wp))

             IF (mode02) THEN
                f(i) = x1 + (0.49E0_nag_wp-x1)*temp
             END IF

             IF (mode12) THEN
                fjac(i,1) = 1.0E0_nag_wp - temp
                fjac(i,2) = -(0.49E0_nag_wp-x1)*(ai-8.0E0_nag_wp)*temp
             END IF

          END DO LOOP

          RETURN

!dec$ attributes offload : mic :: objfun
       END SUBROUTINE objfun
!dec$ attributes offload : mic :: confun
       SUBROUTINE confun(mode,ncnln,n,ldcj,needc,x,c,cjac,nstate,iuser,ruser)
!         Routine to evaluate the nonlinear constraint and its 1st
!         derivatives.

!         .. Implicit None Statement ..
          IMPLICIT NONE
!         .. Scalar Arguments ..
          INTEGER, INTENT (IN)                :: ldcj, n, ncnln, nstate
          INTEGER, INTENT (INOUT)             :: mode
!         .. Array Arguments ..
          REAL (KIND=nag_wp), INTENT (OUT)    :: c(ncnln)
          REAL (KIND=nag_wp), INTENT (INOUT)  :: cjac(ldcj,n), ruser(*)
          REAL (KIND=nag_wp), INTENT (IN)     :: x(n)
          INTEGER, INTENT (INOUT)             :: iuser(*)
          INTEGER, INTENT (IN)                :: needc(ncnln)
!         .. Executable Statements ..
          IF (nstate==1) THEN

!            First call to CONFUN.  Set all Jacobian elements to zero.
!            Note that this will only work when 'Derivative Level = 3'
!            (the default; see Section 11.2).

             cjac(1:ncnln,1:n) = 0.0E0_nag_wp
          END IF

          IF (needc(1)>0) THEN

             IF (mode==0 .OR. mode==2) THEN
                c(1) = -0.09E0_nag_wp - x(1)*x(2) + 0.49E0_nag_wp*x(2)
             END IF

             IF (mode==1 .OR. mode==2) THEN
                cjac(1,1) = -x(2)
                cjac(1,2) = -x(1) + 0.49E0_nag_wp
             END IF

          END IF

          RETURN

!dec$ attributes offload : mic :: confun
       END SUBROUTINE confun
    END MODULE e04uqfe_mod
    PROGRAM e04uqfe

!      E04UQF Example Main Program

!      .. Use Statements ..
       USE nag_library, ONLY : e04uqf, e04urf, e04usf, nag_wp, x04abf, x04acf, &
                               x04baf
       USE e04uqfe_mod, ONLY : confun, iset, nin, ninopt, nout, objfun
!      .. Implicit None Statement ..
       IMPLICIT NONE
!      .. Parameters ..
       CHARACTER (*), PARAMETER            :: fname = 'e04uqfe.opt'
!      .. Local Scalars ..
       REAL (KIND=nag_wp)                  :: objf
       INTEGER                             :: i, ifail, inform, iter, lda,     &
                                              ldcj, ldfj, ldr, liwork, lwork,  &
                                              m, mode, n, nclin, ncnln,        &
                                              outchn, sda, sdcjac
       CHARACTER (80)                      :: rec
!      .. Local Arrays ..
       REAL (KIND=nag_wp), ALLOCATABLE     :: a(:,:), bl(:), bu(:), c(:),      &
                                              cjac(:,:), clamda(:), f(:),      &
                                              fjac(:,:), r(:,:), work(:),      &
                                              x(:), y(:)
       REAL (KIND=nag_wp)                  :: user(1)
       INTEGER, ALLOCATABLE                :: istate(:), iwork(:)
       INTEGER                             :: iuser(1)
!      .. Intrinsic Functions ..
       INTRINSIC                              max
!      .. Executable Statements ..
       WRITE (rec,99998) 'E04UQF Example Program Results'
       CALL x04baf(nout,rec)

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

       READ (nin,*) m, n
       READ (nin,*) nclin, ncnln
       liwork = 3*n + nclin + 2*ncnln
       lda = max(1,nclin)

       IF (nclin>0) THEN
          sda = n
       ELSE
          sda = 1
       END IF

       ldcj = max(1,ncnln)

       IF (ncnln>0) THEN
          sdcjac = n
       ELSE
          sdcjac = 1
       END IF

       ldfj = m
       ldr = n

       IF (ncnln==0 .AND. nclin>0) THEN
          lwork = 2*n**2 + 20*n + 11*nclin + m*(n+3)
       ELSE IF (ncnln>0 .AND. nclin>=0) THEN
          lwork = 2*n**2 + n*nclin + 2*n*ncnln + 20*n + 11*nclin + 21*ncnln + &
             m*(n+3)
       ELSE
          lwork = 20*n + m*(n+3)
       END IF

       ALLOCATE (istate(n+nclin+ncnln),iwork(liwork),a(lda,sda), &
          bl(n+nclin+ncnln),bu(n+nclin+ncnln),y(m),c(max(1, &
          ncnln)),cjac(ldcj,sdcjac),f(m),fjac(ldfj,n),clamda(n+nclin+ncnln), &
          r(ldr,n),x(n),work(lwork))

       IF (nclin>0) THEN
          READ (nin,*) (a(i,1:sda),i=1,nclin)
       END IF

       READ (nin,*) y(1:m)
       READ (nin,*) bl(1:(n+nclin+ncnln))
       READ (nin,*) bu(1:(n+nclin+ncnln))
       READ (nin,*) x(1:n)

!      Set the unit number for advisory messages to OUTCHN

       outchn = nout
       CALL x04abf(iset,outchn)

!      Set three options using E04URF

       CALL e04urf(' Infinite Bound Size = 1.0D+25 ')

       CALL e04urf(' Print Level = 1 ')

       CALL e04urf(' Verify Level = -1 ')

!      Open the options file for reading

       mode = 0

       ifail = 0
       CALL x04acf(ninopt,fname,mode,ifail)

!      Read the options file for the remaining options

       CALL e04uqf(ninopt,inform)

       IF (inform/=0) THEN
          WRITE (rec,99999) 'E04UQF terminated with INFORM = ', inform
          CALL x04baf(nout,rec)
          GO TO 20
       END IF

!      Solve the problem

       ifail = 0
       CALL e04usf(m,n,nclin,ncnln,lda,ldcj,ldfj,ldr,a,bl,bu,y,confun,objfun, &
          iter,istate,c,cjac,f,fjac,clamda,objf,r,x,iwork,liwork,work,lwork, &
          iuser,user,ifail)

20     CONTINUE

99999  FORMAT (1X,A,I5)
99998  FORMAT (1X,A)
    END PROGRAM e04uqfe
