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, Супермодераторы



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

Сейчас этот форум просматривают: Dmitriy40


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

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