Я хочу использовать GSL с интерфейсом Fortran FGSL , чтобы использовать предоставленный multiroots solver . Чтобы запустить симуляцию, мне нужно определить остаток от root проблемы с поиском. В тестах FSGL есть этот пример Розенброка :
function rosenbrock_f(x, params, f) bind(c)
type(c_ptr), value :: x, params, f
integer(c_int) :: rosenbrock_f
!
type(fgsl_vector) :: fx, ff
real(fgsl_double), pointer :: par(:), xv(:), yv(:)
integer(fgsl_int) :: status
!
call fgsl_obj_c_ptr(fx, x)
call fgsl_obj_c_ptr(ff, f)
call c_f_pointer(params, par, (/ 2 /))
status = fgsl_vector_align(xv, fx)
status = fgsl_vector_align(yv, ff)
yv(1) = par(1) * (1.0_fgsl_double - xv(1))
yv(2) = par(2) * (xv(2) - xv(1)*xv(1))
rosenbrock_f = fgsl_success
end function rosenbrock_f
Здесь x - входящая переменная, params - дополнительные переменные, а f - исходящий остаток. В моем коде у меня уже есть функция для остатка, поэтому я хотел бы передать ее как внешнюю функцию через params. К сожалению, мне также нужно передать другой самоопределенный тип данных, также через params. Мне это нужно, потому что решателю из GSL нужна функция с правильными фиктивными переменными, и я не знаю, как этого добиться.
Итак, мой вопрос :
Как я могу передать через функцию внешнюю функцию и самоопределяемый тип данных, чтобы использовать ее в этой функции?
Изменение приведенного выше примера привело меня к
function rosenbrock_f(x, params, f) bind(c)
type(c_ptr), value :: x, params, f
integer(c_int) :: rosenbrock_f
!
type(fgsl_vector) :: fx, ff
real(fgsl_double), pointer :: xv(:), yv(:) ! par removed
integer(fgsl_int) :: status
! NEW DECLARATIONS
type(owntype) :: this
external :: GetRes
!
call fgsl_obj_c_ptr(fx, x)
call fgsl_obj_c_ptr(ff, f)
! In this region I need to get GetRes (external function)
! and this (self-defined data type) from the params variable
! instead of par
call c_f_pointer(params, GetRes))
!call c_f_pointer(params, this)) ! not possible
status = fgsl_vector_align(xv, fx)
status = fgsl_vector_align(yv, ff)
call GetRes(this,xv,yv) ! call the external function
rosenbrock_f = fgsl_success
end function rosenbrock_f
Однако, это только позволило бы мне получить доступ к GetRes. Я имею в виду что-то вроде указателя параметров с формой 2. Аналогично вышеописанному, но с учетом разных типов данных.
Редактировать 1 (еще немного кода): Вот еще немного кода для Это. Внешняя функция будет выглядеть для примера выше, как это.
subroutine GetRes(this,y,res)
implicit none
type(owntype) :: this
double precision, dimension(this%neq) :: y
double precision, dimension(this%neq) :: res
intent (in) :: y
intent (out) :: res
res(1) = (1.0 - y(1))
res(2) = (y(2) - y(1)*y(1))
end subroutine GetRes
Чтобы увидеть, как используется функция rosenbrock_f, я думаю, лучше всего сослаться на многокорневые тесты .
Решатель инициализируется в строка 80 :
mroot_f = fgsl_multiroot_function_init(rosenbrock_f,nrt,ptr)
устанавливается в строку 84
status = fgsl_multiroot_fsolver_set(mroot_fslv, mroot_f, xvec)
и затем итеративно вызывается в строка 97 :
status = fgsl_multiroot_fsolver_iterate(mroot_fslv);