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

    MODULE e04wdfe_mod

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

!      .. Use Statements ..
       USE nag_library, ONLY : nag_wp
!      .. Implicit None Statement ..
       IMPLICIT NONE
!      .. Parameters ..
       INTEGER, PARAMETER                  :: leniw = 600, lenrw = 600,        &
                                              nin = 5, nout = 6
    CONTAINS
!dec$ attributes offload : mic :: objfun
       SUBROUTINE objfun(mode,n,x,objf,grad,nstate,iuser,ruser)
!         Routine to evaluate objective function and its 1st derivatives.

!         .. Implicit None Statement ..
          IMPLICIT NONE
!         .. Scalar Arguments ..
          REAL (KIND=nag_wp), INTENT (OUT)    :: objf
          INTEGER, INTENT (INOUT)             :: mode
          INTEGER, INTENT (IN)                :: n, nstate
!         .. Array Arguments ..
          REAL (KIND=nag_wp), INTENT (INOUT)  :: grad(n), ruser(*)
          REAL (KIND=nag_wp), INTENT (IN)     :: x(n)
          INTEGER, INTENT (INOUT)             :: iuser(*)
!         .. Executable Statements ..
          IF (mode==0 .OR. mode==2) THEN
             objf = x(1)*x(4)*(x(1)+x(2)+x(3)) + x(3)
          END IF

          IF (mode==1 .OR. mode==2) THEN
             grad(1) = x(4)*(2.0E0_nag_wp*x(1)+x(2)+x(3))
             grad(2) = x(1)*x(4)
             grad(3) = x(1)*x(4) + 1.0E0_nag_wp
             grad(4) = x(1)*(x(1)+x(2)+x(3))
          END IF

          RETURN

!dec$ attributes offload : mic :: objfun
       END SUBROUTINE objfun
!dec$ attributes offload : mic :: confun
       SUBROUTINE confun(mode,ncnln,n,ldcj,needc,x,ccon,cjac,nstate,iuser, &
             ruser)
!         Routine to evaluate the nonlinear constraints and their 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)    :: ccon(max(1,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)
!         .. Intrinsic Functions ..
          INTRINSIC                              max
!         .. 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
                ccon(1) = x(1)**2 + x(2)**2 + x(3)**2 + x(4)**2
             END IF

             IF (mode==1 .OR. mode==2) THEN
                cjac(1,1) = 2.0E0_nag_wp*x(1)
                cjac(1,2) = 2.0E0_nag_wp*x(2)
                cjac(1,3) = 2.0E0_nag_wp*x(3)
                cjac(1,4) = 2.0E0_nag_wp*x(4)
             END IF

          END IF

          IF (needc(2)>0) THEN

             IF (mode==0 .OR. mode==2) THEN
                ccon(2) = x(1)*x(2)*x(3)*x(4)
             END IF

             IF (mode==1 .OR. mode==2) THEN
                cjac(2,1) = x(2)*x(3)*x(4)
                cjac(2,2) = x(1)*x(3)*x(4)
                cjac(2,3) = x(1)*x(2)*x(4)
                cjac(2,4) = x(1)*x(2)*x(3)
             END IF

          END IF

          RETURN

!dec$ attributes offload : mic :: confun
       END SUBROUTINE confun
    END MODULE e04wdfe_mod
    PROGRAM e04wdfe

!      E04WDF Example Main Program

!      .. Use Statements ..
       USE nag_library, ONLY : e04wcf, e04wdf, e04wgf, nag_wp
       USE e04wdfe_mod, ONLY : confun, leniw, lenrw, nin, nout, objfun
!      .. Implicit None Statement ..
       IMPLICIT NONE
!      .. Local Scalars ..
       REAL (KIND=nag_wp)                  :: objf
       INTEGER                             :: i, ifail, lda, ldcj, ldh,        &
                                              majits, n, nclin, ncnln, sda,    &
                                              sdcjac
!      .. Local Arrays ..
       REAL (KIND=nag_wp), ALLOCATABLE     :: a(:,:), bl(:), bu(:), ccon(:),   &
                                              cjac(:,:), clamda(:), grad(:),   &
                                              h(:,:), x(:)
       REAL (KIND=nag_wp)                  :: ruser(1), rw(lenrw)
       INTEGER, ALLOCATABLE                :: istate(:)
       INTEGER                             :: iuser(1), iw(leniw)
!      .. Intrinsic Functions ..
       INTRINSIC                              max
!      .. Executable Statements ..
       WRITE (nout,*) 'E04WDF Example Program Results'
       FLUSH (nout)

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

       READ (nin,*) n, nclin, 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

       ldh = n
       ALLOCATE (istate(n+nclin+ncnln),a(lda,sda),bl(n+nclin+ncnln), &
          bu(n+nclin+ncnln),ccon(max(1,ncnln)),cjac(ldcj,sdcjac),clamda(n+ &
          nclin+ncnln),grad(n),h(ldh,n),x(n))

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

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

!      Call E04WCF to initialise E04WDF.

       ifail = 0
       CALL e04wcf(iw,leniw,rw,lenrw,ifail)

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

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

!      Solve the problem.

       ifail = 0
       CALL e04wdf(n,nclin,ncnln,lda,ldcj,ldh,a,bl,bu,confun,objfun,majits, &
          istate,ccon,cjac,clamda,objf,grad,h,x,iw,leniw,rw,lenrw,iuser,ruser, &
          ifail)

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

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