Existe uma maneira de definir implicitamente uma função midprogram em fortran '[duplicar]
Estou tentando resolver alguns problemas de autovalor. Estou usando o gfortran. Escrevi um módulo que contém a bisection_methodsub - rotina. Em meu programa, eu defini a secular(m,x)função que pega um array 2D me um float xe produz o polinômio característico de mat x; ou seja, det (m - x Id). Um dos argumentos da bisection_methodsub-rotina é uma função f, que foi concebida como uma função de uma entrada real e uma saída real. Gostaria de inserir, no entanto, a função 'parcialmente aplicada' secular(m,_)a esta sub-rotina. Existe uma maneira de fazer isso, sem definir explicitamente essa função em um módulo?
Não posso definir essas funções explicitamente, pois devo fazer esse procedimento para várias matrizes m. Além disso, não posso modificar o corpo do bisection_methodporque também o uso para a função de um argumento real. Existe uma maneira de contornar isso em Fortran?
Respostas
Como @francescalus apontou, você quer ter um encerramento para o seu problema.
Os fechamentos são parcialmente suportados no Fortran usando procedimentos internos, porque o procedimento interno tem acesso a todas as variáveis no escopo circundante.¹
Supondo que você queira encontrar os valores próprios de Mcom seu código, ele pode ser estruturado assim.²
module bisection_and_linalg
use iso_fortran_env, only: real64
integer, parameter :: wp = real64
implicit none(type, external)
abstract interface
real(wp) pure function real_function(x)
real(wp), intent(in) :: x
end function
end interface
contains
!> Find the root of f in the interval I
real(wp) pure function bisect(f, I)
procedure(real_function) :: f
real(wp) :: I(2)
...
end function
!> Evaluate the characteristic polynomial of m at x
real(wp) pure function secular(M, x)
real(wp), intent(in) :: M(:, :), x
...
end function
!> Get eigenvalues
real(wp) pure function eigenvalues(M)
real(wp), intent(in) :: M(:, :)
...
! n.b. here you can use the bisection method to
! find your eigenvalues.
bisect(f, ...)
contains
real(wp) pure function f(x)
! n.b. here you have your closure.
! M is captured from surrounding scope.
f = secular(M, x)
end function
end function
end module
¹ A única ressalva é que os procedimentos internos só existem enquanto o escopo circundante existir. Portanto, infelizmente não é possível escrever uma função genérica que recebe uma função e retorna um ponteiro de função para uma versão parcialmente aplicada dela usando procedimentos internos. Mas isso não é uma preocupação para o seu problema.
² Talvez seja melhor retornar um polinômio característico real. Então você poderia derivá-lo, para usar, por exemplo, Newton-Raphson em vez de bissecção.