NAG Library Manual, Mark 30.1
Interfaces:  FL   CL   CPP   AD 

NAG AD Library Introduction
Example description
!   C05AY_A1T1W_F Example Program Text
!   Mark 30.1 Release. NAG Copyright 2024.
    Module c05ay_a1t1w_fe_mod

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

!     .. Use Statements ..
      Use iso_c_binding, Only: c_ptr
      Use nagad_library, Only: exp, nagad_a1t1w_w_rtype, Assignment (=),       &
                               Operator (-), Operator (*)
!     .. Implicit None Statement ..
      Implicit None
!     .. Accessibility Statements ..
      Private
      Public                           :: f_a1t1w
!     .. Parameters ..
      Integer, Parameter, Public       :: nin = 5, nout = 6
    Contains
      Subroutine f_a1t1w(ad_handle,x,z,iuser,ruser)

!       .. Scalar Arguments ..
        Type (c_ptr), Intent (Inout)   :: ad_handle
        Type (nagad_a1t1w_w_rtype), Intent (In) :: x
        Type (nagad_a1t1w_w_rtype), Intent (Out) :: z
!       .. Array Arguments ..
        Type (nagad_a1t1w_w_rtype), Intent (Inout) :: ruser(*)
        Integer, Intent (Inout)        :: iuser(*)
!       .. Local Scalars ..
        Integer                        :: ifail
!       .. Executable Statements ..
        ifail = 0

!       Use module extensions to operators and intrinsics.
        z = exp(-x) - x*ruser(1)
        Return

      End Subroutine f_a1t1w

    End Module c05ay_a1t1w_fe_mod

    Program c05ay_a1t1w_fe
!     C05AY_A1T1W_F Example Main Program

!     .. Use Statements ..
      Use c05ay_a1t1w_fe_mod, Only: f_a1t1w, nin, nout
      Use iso_c_binding, Only: c_ptr
      Use nagad_library, Only: c05ay_a1t1w_f, nagad_a1t1w_get_derivative,      &
                               nagad_a1t1w_inc_derivative,                     &
                               nagad_a1t1w_ir_create => x10za_a1t1w_f,         &
                               nagad_a1t1w_ir_interpret_adjoint,               &
                               nagad_a1t1w_ir_register_variable,               &
                               nagad_a1t1w_ir_remove, nagad_a1t1w_w_rtype,     &
                               nagad_t1w_w_rtype, x10aa_a1t1w_f,               &
                               x10ab_a1t1w_f, x10ac_a1t1w_f, x10ae_a1t1w_f,    &
                               x10af_a1t1w_f, Assignment (=)
      Use nag_library, Only: nag_wp
!     .. Implicit None Statement ..
      Implicit None
!     .. Local Scalars ..
      Type (nagad_a1t1w_w_rtype)       :: a, b, eps, eta, x
      Type (c_ptr)                     :: ad_handle
      Type (nagad_t1w_w_rtype)         :: t_t
      Real (Kind=nag_wp)               :: ar, br, epsr, etar, rr
      Integer                          :: ifail, mode
!     .. Local Arrays ..
      Type (nagad_a1t1w_w_rtype)       :: ruser(1)
      Integer                          :: iuser(1)
!     .. Executable Statements ..

      Write (nout,*) 'C05AY_A1T1W_F Example Program Results'

!     Skip first line of data file
      Read (nin,*)
!     Read problem parameters
      Read (nin,*) ar
      Read (nin,*) br
      Read (nin,*) epsr
      Read (nin,*) etar
      Read (nin,*) rr

      ruser(1) = 0.0_nag_wp
      a = ar
      b = br
      eps = epsr
      eta = etar

      t_t%value = rr
      t_t%tangent = 1.0_nag_wp
      ruser(1)%value = t_t

!     Create AD tape
      Call nagad_a1t1w_ir_create

!     Create AD configuration data object
      ifail = 0
      Call x10aa_a1t1w_f(ad_handle,ifail)

!     Read AD computational mode
      Read (nin,*) mode
!     Set this mode.
      Call x10ac_a1t1w_f(ad_handle,mode,ifail)

!     Register variables to differentiate w.r.t.
      Call nagad_a1t1w_ir_register_variable(ruser)

!     Call AD routine
      ifail = 0
      Call x10ae_a1t1w_f(ad_handle,1,ifail)
      ifail = 0
      Call x10af_a1t1w_f(ad_handle,-1,ifail)
      Call c05ay_a1t1w_f(ad_handle,a,b,eps,eta,f_a1t1w,x,iuser,ruser,ifail)

!     Setup evaluation of derivatives via adjoints
      t_t = 1.0_nag_wp
      Call nagad_a1t1w_inc_derivative(x,t_t)
      ifail = 0
      Call nagad_a1t1w_ir_interpret_adjoint(ifail)

      Write (nout,*)
      Write (nout,*)                                                           &
        ' Derivatives calculated: Second order (adjoint of tangent)'
      Write (nout,*) ' Computational mode    : algorithmic'

!     Get derivatives
      t_t = nagad_a1t1w_get_derivative(ruser(1))

      Write (nout,*)
      Write (nout,99999) ' Solution, x =', x%value%value
      Write (nout,*) ' Derivatives:'
      Write (nout,99999) ' d^2x/druser(x)^2 =', t_t%tangent
99999 Format (1X,A,1X,E12.5)

!     Remove computational data object and tape
      Call x10ab_a1t1w_f(ad_handle,ifail)
      Call nagad_a1t1w_ir_remove

    End Program c05ay_a1t1w_fe