2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




 
 Фортран: как передать подпрограмме динамический массив
Сообщение22.02.2012, 12:41 
Есть основная программа, в которой существует
real, allocatable, dimension(:) :: X
в какой-то момент делается allocate(X(1:N))
Дальше этот массив X задается как фактический аргумент внешней подпрограммы:
call SubRout(X)
в подпрограмме описываю так:
subroutine SubRout(X)
real, dimension(:):: X
Проблема в том, что когда я в основной программе делаю deallocate(X), она падает с диагнозом access violation. С массивом к этому моменту все в порядке и подпрограмма работает с ним верно. Что я неправильно делаю с памятью?

 
 
 
 Re: Фортран: как передать подпрограмме динамический массив
Сообщение23.02.2012, 14:34 
Покажите код

 
 
 
 Re: Фортран: как передать подпрограмме динамический массив
Сообщение23.02.2012, 14:44 
Внутри подпрограммы его тоже надо объявить allocatable. Тогда туда будет нельзя передавать нединамические массивы, зато динамические можно будет там высвобождать.

 
 
 
 Re: Фортран: как передать подпрограмме динамический массив
Сообщение24.02.2012, 16:18 
Разобрался. Сделать внутри программы allocatable у меня к победе не ведет, т.к. компилятор выдает ошибку "A dummy argument name is invalid in this context". Но:
1) если массив одномерный, то можно просто сделать его в подпрограмме dimension(*)
2) если чуть сложнее (сделав модуль и interface в нем), то проходит и для двумерных массивов. Привожу примитивный пример с подсчетом суммы элементов квадратной матрицы.
Код:
       module Summing
      interface SumCalc
         subroutine SumCalc(X, N, S)
         implicit none
         integer i, j, N, S
         integer, dimension(:, :) :: X
         end subroutine SumCalc
      end interface
   end module Summing

       subroutine SumCalc(X, N, S)

      implicit none
      integer i, j, N, S
      integer, dimension(:, :) :: X

      S=0
      do i=1, N
         do j=1, N
            S=S+X(i, j)
         end do
      end do
   end subroutine SumCalc       


        program mymain

   use Summing
   implicit none
   integer i, j, N, S
   integer, allocatable:: X(:, :)
   
   N=100
   allocate(X(1:N, 1:N))
   
   do i=1, N
      do j=1, N
         X(i, j)=i+j
      end do
   end do

   call SumCalc(X, N, S)

   deallocate(X)
   end program mymain

Наверное, в фортране-95 можно еще как-то, но у меня -90.

 
 
 
 Re: Фортран: как передать подпрограмме динамический массив
Сообщение24.02.2012, 18:24 
fizik в сообщении #542248 писал(а):
2) если чуть сложнее (сделав модуль и interface в нем), то проходит и для двумерных массивов
вообще, это не очень чётко во всяких документациях написано, но есть такой момент который стоит учитывать. В принципе фортран умеет проверять типы и всё такое, но он умеет это делать только с подпрограммами и функциями для которых определён интерфейс. Также если читать документацию внимательно, можно узнать что для подпрограмм и функций определённых в модуле интерфейсы генерируются автоматом.

Отсюда простое правило: никогда не объявлять их кроме как в модуле, иначе понять откуда берутся те или иные ошибки не будет никакой возможности.

 
 
 
 Re: Фортран: как передать подпрограмме динамический массив
Сообщение25.02.2012, 20:03 
2 fizik:
Между одномерными и многомерными массивами никакой разницы нет. Не надо использовать dimension(*). В фортране естественный способ передачи массива в подпрограмму - использование массива, перенимающего форму. Не важно, allocatable исходный или нет.
Как вам уже справедливо написали выше, функцию SumCalc нужно было определять в модуле. Тогда явный интерфейс не нужен. Ну или же описывать интерфейс внутри вызывающей процедуры/программы
Просто интересно: что означает "у меня -90"? Сейчас вроде бы уже все компиляторы в той или иной степени 2003 поддерживают.

2 nestoklon:
Иногда требуется все же задавать явный интерфейс, например, при
передаче процедуры, как параметра. В этом случае то, что процедура определена в модуле, не поможет

 
 
 
 Re: Фортран: как передать подпрограмме динамический массив
Сообщение27.02.2012, 16:03 
Да, если подпрограмму определять как
Код:
module Summing
      contains
         subroutine SumCalc(X, N, S)

            implicit none
            integer i, j, N, S
            integer, dimension(:, :) :: X

            S=0
            do i=1, N
               do j=1, N
                  S=S+X(i, j)
               end do
            end do
         end subroutine SumCalc
   end module Summing

то модуль с интерфейсом не нужен.
А что плохого в передаче одномерного динамического массива по dimension(*)? Я просто пользуюсь одной подпрограммой, написанной еще в конце 80-х, в которой сделано именно так.
2 Evgeny_2012: У меня компилятор Compaq 6.5.0 (ну да, очень старый), так что что-то новое он может и не поддерживать.

 
 
 
 Re: Фортран: как передать подпрограмме динамический массив
Сообщение27.02.2012, 18:14 
Вот пример:

Код:
module m
contains
subroutine f(b)
integer b(*)
print *,b
print *,size(b)
end subroutine f
end module m

use m
integer :: b(5) = [1,2,3,4,5]
call f(b)
end


На строки 5 и 6 компилятор ругается. Если заменить звезду в описании b на двоеточие - то есть передавать, как массив, перенимающий форму, то все работает. Можно явно задать сечение: print *,b(1:5) и size(b(1:5)), но надо точно знать границы массива.

 
 
 [ Сообщений: 8 ] 


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group