Intel® oneAPI Math Kernel Library
Ask questions and share information with other developers who use Intel® Math Kernel Library.

djacobix with user defined function imported from a module

andrea_r_
Beginner
730 Views

Hi there, I'm new to this forum, so I hope I'm posting this into the correct section.

 

 

I'm trying to use the mkl trust region algorithm to solve a non linear system of equations in a fortran program. I started from the example provided online (ex_nlsqp_f90_x.f90 https://software.intel.com/en-us/node/501498) and everything works correctly. Now, because I have to use this in a much bigger program, I need the user defined objective function to be loaded from a separate module. Hence, I splitted the example into 2 separate files, but I'm not able to make it compile correctly. 

So here is the code for module which contains user defined data structure and the objective function

module modFun
implicit none
private
public my_data, extended_powell

type :: my_data
      integer a
      integer sum
end type my_data


contains

subroutine extended_powell (m, n, x, f, user_data)
    implicit none
    integer, intent(in) :: m, n
    real*8 , intent(in) :: x(n)
    real*8, intent(out) :: f(m)
    type(my_data) :: user_data
    integer i

    user_data%sum = user_data%sum + user_data%a
    do i = 1, n/4
        f(4*(i-1)+1) = x(4*(i-1)+1) + 10.0 * x(4*(i-1)+2)
        f(4*(i-1)+2) = 2.2360679774998 * (x(4*(i-1)+3) - x(4*(i-1)+4))
        f(4*(i-1)+3) = ( x(4*(i-1)+2) - 2.0 * x(4*(i-1)+3) )**2
        f(4*(i-1)+4) = 3.1622776601684 * (x(4*(i-1)+1) - x(4*(i-1)+4))**2
    end do
end subroutine extended_powell

end module modFun
!    nonlinear least square problem without boundary constraints
    include 'mkl_rci.f90'
program EXAMPLE_EX_NLSQP_F90_X
    use MKL_RCI
    use MKL_RCI_type
    use modFun

!   user's objective function
!   n - number of function variables
!   m - dimension of function value
    integer n, m
    parameter (n = 4)
    parameter (m = 4)
!   precisions for stop-criteria (see manual for more details)
    real*8 eps(6)
!   solution vector. contains values x for f(x)
    real*8 x(n)
!   jacobi matrix
    real*8 fjac(m*n)
...
!   Additional users data
    type(my_data), target :: m_data
...
djacobix (extended_powell,n,m,fjac,x,eps(1),%val(loc(m_data))) /= &
                TR_SUCCESS)
...
end program

The problem appear to be some characteristic of argument 5, which is the are defined data, hence it has its on type. I tried changing intent, but it doesn't work

ex_nlsqp_f90_x_M.f90(170): error #7065: The characteristics of dummy argument 5 of the associated actual procedure differ from the characteristics of dummy argument 5 of the dummy procedure.   [EXTENDED_POWELL]

            if (djacobix (extended_powell,n,m,fjac,x,eps(1),%val(loc(m_data))) /= &

--------------------------^

 

On the other hand http://technion.ac.il/doc/intel/mkl/mkl_manual/osr/functn_djacobix.htm it's stated that the first argument of djacobix (i.e. the objective function subroutine) need to be declared as external, which can't done  because the obj function need to reside in a module.

Can anyone help me with this problem providing a working example? Thanks a lot. Andrea

 

 

0 Kudos
1 Reply
mecej4
Honored Contributor III
730 Views

Andrea, the difficulties that you have run into are a consequence of (inadvertently) enabling argument checking because of the way that you structured your module code and some obscure features of the interface that its designers gave to DJACOBIX.

The MKL example code ex_nlsqp_f90_x.f90, which you used as the basis of your own code, contains extended_powell as an external subroutine. In fact, the main program declares it to be EXTERNAL and, with some help from %VAL and LOC, things work as long as you do not request that the interfaces be checked.

In the long run and in production code, you probably should do things properly using ISO_C_BINDING and type conversions using TRANSFER, but that is a lot of work for code used only for testing and intended to be discarded soon after. Here is what I suggest as a "quick fix":

  1. Make extended_powell() an external procedure, by moving the body of the subroutine outside the module (or putting it into a separate file) and remove the CONTAINS.
  2. Declare extended_powell as EXTERNAL in your main program, as in the MKL example.

That should take care of things for now, but be alert for problems if you use this code in a larger program.

 

0 Kudos
Reply