У меня нет большого опыта работы с Fortran или f2py
, но я использую пример, написанный коллегой, чтобы попытаться написать свой собственный.
У меня есть часть функции Python, которую я хочу написать на Фортране, чтобы попытаться получить хорошее ускорение. Подпрограмма на Фортране, которую я написал и буду вызывать с помощью f2py
,
subroutine cone_model_func(box_cart, &
box_em, box_ne, box_Te, &
iz_sigma_box, box_bool, pixels, &
vecs, gas_valve_cart, ll, n_vec, &
box_base, cone_c, cone_m, dV, N_box, &
M, iz, pixel_count)
! Inputs
real(8), intent(in) :: box_cart(:,:,:,:) ! (151,151,151,3)
real(8), intent(in) :: box_em(:,:,:), box_ne(:,:,:), box_Te(:,:,:), iz_sigma_box(:,:,:) ! (151,151,151)
logical, intent(in) :: box_bool(:,:,:) ! (151,151,151)
real(8), intent(in) :: pixels(:,:,:), vecs(:,:,:) ! (151,151,3)
real(8), intent(in) :: gas_valve_cart(3), ll(3), n_vec(3) ! (3)
real(8), intent(in) :: box_base, cone_c, cone_m, dV
integer, intent(in) :: N_box
real(8) :: M(:), iz(:) ! (151)
! Local variables
real(8) :: box_n0(size(box_ne,1),size(box_ne,2),size(box_ne,3)) ! (151,151,151)
real(8) :: distances(size(pixels,1),size(pixels,2)), plane_perp_dist(size(pixels,1),size(pixels,2)) ! (151,151)
integer :: inds(2) ! (2)
real(8) :: mu, sigma_n0
integer :: i, j, k
! Output
real(8), intent(out) :: pixel_count(size(vecs,1),size(vecs,2)) ! (151,151)
! The function
do i=1, N_box
if (M(i) > 0.d0) then
mu = abs(sum((ll + box_base * i * n_vec - gas_valve_cart) * n_vec))
sigma_n0 = (cone_m * mu + cone_c) * denom
plane_perp_dist = 0.d0
box_n0 = 0.d0
do j=1, N_box
do k=1, N_box
plane_perp_dist(j,k) = magnitude1(gas_valve_cart + (mu * n_vec) - box_cart(i,j,k,:))
box_n0(i,j,k) = neutral_gauss(plane_perp_dist(j,k), M(i), sigma_n0)
if (box_bool(i,j,k)) then
distances = distance_to_vector(box_cart(i,j,k,:), vecs, pixels)
inds = minloc(distances)
pixel_count(inds(1),inds(2)) = pixel_count(inds(1),inds(2)) + (box_n0(i,j,k)*box_em(i,j,k)*box_ne(i,j,k)*dV)
end if
end do
end do
else
M(i) = 0.d0
end if
if (i < N_box) then
iz(i) = sum(box_n0(i,:,:)*vel_Te(box_Te(i,:,:))*iz_sigma_box(i,:,:)*box_ne(i,:,:)*dV*dV)
M(i+1) = M(i) - iz(i)
end if
end do
end subroutine cone_model_func
Я могу вызвать функцию и запустить ее из моей функции Python, вплоть до строки
distances = distance_to_vector(box_cart(i,j,k,:), vecs, pixels)
Затем я получаю следующую ошибку
free(): invalid next size (normal)
Aborted (core dumped)
Я знаю, что он доходит до этой строки, потому что я могу поставить перед ним оператор печати, и он распечатает его нормально. Я также могу поместить оператор печати в самую последнюю строку функции Distance_to_vector, и она тоже будет распечатана. Итак, есть некоторая проблема с тем, как эта функция выводит массив, я думаю?
Функция Distance_to_vector:
function distance_to_vector(P, v, v0)
! Inputs
real(8), intent(in) :: P(3)
real(8), intent(in) :: v(:,:,:), v0(:,:,:)
! Local variables
real(8) :: mag(size(v,1),size(v,2))
real(8) :: mu
integer :: i, j
! Outputs
real(8) :: distance_to_vector(size(v0,1),size(v0,2))
! The function
mag = 1.d0/(magnitude3(v)**2)
do i=1, size(v,1)
do j=1, size(v,2)
mu = sum((P - v0(i,j,:)) * v(i,j,:)) * mag(i,j)
distance_to_vector(i,j) = magnitude1((mu * v(i,j,:))+v0(i,j,:)-P)
end do
end do
print*, 'This print statement returns fine'
! end and return
end function distance_to_vector
и две функции magnitude1
и magnitude3
, которые он вызывает, работают нормально.