2014 dxdy logo

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

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




Начать новую тему Ответить на тему
 
 Фортран: как передать подпрограмме динамический массив
Сообщение22.02.2012, 12:41 


29/12/08
20
Есть основная программа, в которой существует
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 


01/02/12
13
Покажите код

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


19/07/08
1266
Внутри подпрограммы его тоже надо объявить allocatable. Тогда туда будет нельзя передавать нединамические массивы, зато динамические можно будет там высвобождать.

 Профиль  
                  
 
 Re: Фортран: как передать подпрограмме динамический массив
Сообщение24.02.2012, 16:18 


29/12/08
20
Разобрался. Сделать внутри программы 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 
Заслуженный участник


19/07/08
1266
fizik в сообщении #542248 писал(а):
2) если чуть сложнее (сделав модуль и interface в нем), то проходит и для двумерных массивов
вообще, это не очень чётко во всяких документациях написано, но есть такой момент который стоит учитывать. В принципе фортран умеет проверять типы и всё такое, но он умеет это делать только с подпрограммами и функциями для которых определён интерфейс. Также если читать документацию внимательно, можно узнать что для подпрограмм и функций определённых в модуле интерфейсы генерируются автоматом.

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

 Профиль  
                  
 
 Re: Фортран: как передать подпрограмме динамический массив
Сообщение25.02.2012, 20:03 


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

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

 Профиль  
                  
 
 Re: Фортран: как передать подпрограмме динамический массив
Сообщение27.02.2012, 16:03 


29/12/08
20
Да, если подпрограмму определять как
Код:
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 


01/02/12
13
Вот пример:

Код:
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 ] 

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group