2014 dxdy logo

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

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




Начать новую тему Ответить на тему
 
 fortan90 subroutine
Сообщение17.03.2011, 20:08 


08/03/11
186
Привет,
пишу подпрограмму на fortran 90. Основная программа работает с массивами, размер которых может изменяться во времени. Написал простой тест, в котором использую одномерные массивы из одного эллемента testput и testoutput. При компиляции ошибка в модуле - не верно allocate используется. Подпрограмма должна создавать input и output размера как и testput, как это можно сделать?

Код:

module coordinates
   real, dimension(:), allocatable :: input
   real, dimension(:), allocatable :: output
end module coordinates

module hlens
   use coordinates
   contains
   subroutine test1(input, output, n)
      allocate( input(n) )
      allocate( output(n) )
      write(*,*) f(1.0)
      output = input
      write(*,*) output
      deallocate(input)
      deallocate(output)
   end subroutine test1
   function f1(x)
      real :: x, f1
      f1  = x + 1.0
   end function f1
end module hlens

program test
   use hlens
   implicit none
   integer :: n=1
   real,  dimension(1) :: testput, testoutput   
   testput(1)=3.4324   
   call test1(testput, testoutput, n)
   write(*,*) input, output
end program test




И еще один вопрос, я с фортраном знаком пару недель всего, поэтому интересно вот что. Что быстрее будет работать:
Код:
module ...
   ...
  contains
  subroutine ..
  ...
  end subroutine
end module

program ...
  use ...
  call ...


либо
Код:
program ...
  interface
    subroutine ...
    end ...
  end ...
end ...

subroutine ...
end subroutine ...


Буду признателен за комментарии!

-- Чт мар 17, 2011 20:27:03 --

Если же убрать allocation в основную прогу, то модуль ошибок не выдает, но интересно можно ли в модуле это?

 Профиль  
                  
 
 
Сообщение17.03.2011, 20:48 
Заслуженный участник


19/07/08
1266
Вы всё же определитесь, вы массивы из модуля используете или в функцию subroutine передаёте. Потому что это взаимоисключающие действия.

И поставьте везде где можно IMPLICIT NONE. Тогда фортран станет вести себя несколько предсказуемее и станет выдавать более иноформативные ошибки.

 Профиль  
                  
 
 
Сообщение17.03.2011, 21:23 


08/03/11
186
implicit none я добавил, только его не везде нужно.
Я хочу, что бы основная программа знала минимум о subroutine, что бы кроме call там ничего не нужно было писать. Поэтому и стоит задача стэйтманты типа allocate использовать в subroutine, а данные сколько именно нужно выделять subroutine должна брать из основной программы.

 Профиль  
                  
 
 
Сообщение18.03.2011, 00:59 
Заслуженный участник


19/07/08
1266
Вы с тем как массив передавать-то определились или нет, я не понял.

 Профиль  
                  
 
 
Сообщение18.03.2011, 07:28 


08/03/11
186
Массив входных данных формируется основной программой, назавем его input, передавать его нужно в subroutine(input, output). Подпрограмма выдает данные и делаем input=output, дальше основная программа что то делает с input и размер input может измениться. В этом и трудность, как согласовать размеры.

-- Пт мар 18, 2011 07:45:55 --

Вот еще тест этой же проблемы,
Код:
program test
implicit none
real, dimension(:), allocatable :: a
integer :: k=10, j

do j=1,4,1
   allocate(a(k))
   a=0.0
   write(*,*) a
   deallocate(a)
   k=k-1
end do
end program test


Здесь все работает, размер a меняется, проблем нет. Если добавить subroutine как ниже. То ошибка будет:
D is a dummy argument and so cannot be ALLOCATABLE
А обидно, что не может. Вот я и пытаюсь узнать как можно это сделать.

Код:
program test
implicit none
real, dimension(:), allocatable :: a, b, c, d
integer :: k=10, j

do j=1,4,1
   allocate(a(k))
   allocate (b(k))
   call check(a,b)
   write(*,*) a
   deallocate(a)
   deallocate(b)
   k=k-1
end do
contains
subroutine check(c , d)
  implicit none
  real, dimension(:), allocatable :: c , d
  d=c
end subroutine
end program test

 Профиль  
                  
 
 
Сообщение18.03.2011, 10:15 
Заслуженный участник


19/07/08
1266
Так, уже лучше.
sithif в сообщении #424148 писал(а):
Вот я и пытаюсь узнать как можно это сделать.
Для этого надо или сделать ей явный интерфейс или объявлять в модуле (при этом интерфейс делается автоматом). Хитрость в том что у разных процедур в модуле есть некоторые сложности с тем чтобы видеть друг друга.
Грамотно сформулированный запрос в гугл даёт писал(а):
Interface for passing arrays
# Warning!! When passing assumed shape arrays as arguments you must provide an interface
...
код: [ скачать ] [ спрятать ]
Используется синтаксис Fortran
module numz
    integer, parameter:: b8 = selected_real_kind(14)
    integer,allocatable :: a_gene(:),many_genes(:,:)
end module

module face
    interface fitness
        function fitness(vector)
        use numz
        implicit none
        real(b8) fitness
        integer, dimension(:) ::  vector
        end function fitness
    end interface
end module

program darwin
    use numz
    use face
    implicit none
    integer i
    integer vect(10) ! just a regular array
    allocate(a_gene(10));allocate(many_genes(3,10))
    a_gene=1  !sets every element of a_gene to 1
    write(*,*)fitness(a_gene)
    vect=8
    write(*,*)fitness(vect) ! also works with regular arrays
    many_genes=3  !sets every element to 3
    many_genes(1,:)=a_gene  !sets column 1 to a_gene
    many_genes(2,:)=2*many_genes(1,:)
    do i=1,3
        write(*,*)fitness(many_genes(i,:))
    enddo
    write(*,*)fitness(many_genes(:,1))  !go along other dimension
!!!!write(*,*)fitness(many_genes)!!!!does not work
end program

function fitness(vector)
    use numz
    implicit none
    real(b8) fitness
    integer, dimension(:)::  vector ! must match interface
    fitness=sum(vector)
end function


И всё же, очень напрягает что Вы используете одно и то же имя для глобальной переменной и для переменной передаваемой в подпрограмму. Очень легко запутаться.

 Профиль  
                  
 
 
Сообщение18.03.2011, 15:47 


08/03/11
186
Спасибо!
Аналогичный способ нашел здесь
http://www.rhinocerus.net/forum/lang-fortran/561747-how-allocate-array-subroutine.html
кому интересно, пичитайте, там подробнее.

 Профиль  
                  
 
 
Сообщение18.03.2011, 17:58 


08/03/11
186
Спасибо, nestoklon! Теперь все работает так как и хотелось.

Код:
module dynamic
   real, dimension(:), allocatable :: array1, array2
end module dynamic

module hlensmode
   interface hlensinterface
      subroutine hlens(input, output)
         use dynamic
         implicit none
         real, dimension(:) :: input, output
      end subroutine hlens
   end interface hlensinterface
end module hlensmode

program test
   use dynamic
   use hlensmode
   implicit none
   integer :: n=10
   allocate(array1(n))
   allocate(array2(n))
   array1=4.0
   array2=0.0
   call hlens(array1, array2)
   write(*,*) array2
end program test

subroutine hlens(input, output)
   use dynamic
   implicit none
   real, dimension(:) :: input, output
   output=input
end subroutine hlens


 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 8 ] 

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



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

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


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

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