f2py не возвращает функцию, выдавая ошибку free(): неверный следующий размер (нормальный)

У меня нет большого опыта работы с 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, которые он вызывает, работают нормально.


person Steven Thomas    schedule 03.11.2020    source источник


Ответы (1)


Я на самом деле очень глуп, и мне удалось это исправить. Ошибка была в строке

real(8) :: distances(size(pixels,1),size(pixels,2)), plane_perp_dist(size(pixels,1),size(pixels,2))

и я дал plane_perp_distance неправильные размеры для использования. Это добавляет к тому, что я в основном читал в Интернете раньше, об ошибке, которую я часто получал, ссылаясь на индекс вне указанного размера массива, но это бросало меня, поскольку я смог получить примерно 3 или 4 строки после точки, которая ломался.

person Steven Thomas    schedule 03.11.2020
comment
Превосходно! Хорошо разобрались! Но обратите внимание, что real( 8 ) не очень хорошая практика, см. /questions/838310/fortran-90-kind-parameter почему; методы selected_real_kind или iso_fortran_env намного лучше - person Ian Bush; 03.11.2020
comment
Меня немного смущает ссылка, которую вы мне прислали, но, как я уже сказал, я новичок в фортране, и мой текущий код сделан из примера коллег. Я уверен, что привыкну к этому, но спасибо за дополнительное чтение :) - person Steven Thomas; 04.11.2020
comment
Суть в том, что Real( 8 ) не переносим, ​​он будет работать с некоторыми компиляторами, но не с другими. Таким образом, это считается плохой практикой. Ссылка описывает способы, которые будут работать со всеми компиляторами. - person Ian Bush; 04.11.2020