2016-07-15 3 views
1

У меня есть несколько переменных массива в модуле, которые являются динамическими, а затем распределены в одной из двух подпрограмм вне модуля. Однако в одной подпрограмме я хочу, чтобы массив был 1D, в другой подпрограмме я хочу, чтобы он был 2D.Ранг динамической матрицы

В принципе я хотел бы что-то подобное в модуле, но я не считаю, что это возможно в области декларации ?:

if (option1) then 
    real (kind=8), allocatable :: arr1(:) 
else 
    real (kind=8), allocatable :: arr1(:,:) 
endif 

Есть ли способ в размещаемых декларациях имеют размерность быть динамичным?

Редактировать 1: Причина, по которой я делаю это, я добавляю новую подпрограмму к существующей кодовой базе, но я хочу быть обратно совместимой. arr1 используется только двумя отдельными подпрограммами, основная программа не использует его вообще. Вот некоторые более полный код, показывающий идею:

program myprog 
use inputs 

call read_inputs 

if (option1) then 
    call do1 
else 
    call do2 
endif 

contains 
    subroutine read_inputs 
     use inputs 
     use mymod 
     !!!read from file .logical. option1, integers N1, N2 

     !allocate arrays 
     if (option1) then 

     else 

     endif 
    end subroutine read_inputs 

    subroutine do1 
     use inputs 
     use mymod 

     allocate(arr1(N1)) 

     !do stuff with arr1 
    end subroutine do1 

    subroutine do2 
     use inputs 
     use mymod 

     allocate(arr1(N1,N2)) 

     !do stuff with arr1 
    end subroutine do2 

end program 

module inputs 
    logical :: option1 
    integer :: N1, N2 

end module inputs 

module mymod 
    use inputs 
    !!!!can I do something here to make the rank of arr1 dynamic? I don't think the following will work 
    if (option1) 
     real (kind=8), allocatable :: arr1(:) 
    else 
     real (kind=8), allocatable :: arr1(:,:) 
    endif 
end module mymod 

Я могу только иметь две отдельные переменные в MyMod, arr1 и arr1_new. Я просто надеялся избежать этого.

+2

Вы можете перегрузить оператор 'allocate' с помощью подпрограммы, выполняющей задание. Fortran 90 почти 26 лет. Какой компилятор вы используете? Если вы используете современный компилятор Fortran (2003+), я бы предложил определить производный тип данных с 2 и 3-мерными распределяемыми типами-типами с соответствующими процедурами, связанными с типом. Fortran 90 не позволяет этого, вместо этого вам придется использовать указатели, которые подвержены утечке памяти. – jlokimlin

+2

Я не понимаю ваш вопрос. Как выглядит массив в основной программе или модуле? Является ли это 1D или 2D? Описывает ли основная программа или модуль вопрос о том, как обрабатывается подпрограмма (1D или 2D)? Возможно, вы можете использовать простую ассоциацию хранения, но вам действительно нужно показать больше кода. Ceterum censeo 'kind = 8' является уродливым, вонючим и злым http://stackoverflow.com/a/856243/721644 –

+0

Компиляторы @jlokimlin не являются проблемой, но, к сожалению, это большая база кода с несколькими пользователями, поэтому для в обозримом будущем это будет Fortran90. – Michael

ответ

1

Я думаю, что «старина» способы, чтобы сделать что-то вроде этого, чтобы пройти первый элемент вместо всего массива и размер массива отдельно:

program dyn_array 
    implicit none 
    integer :: a(2, 3) 
    integer :: i 
    call set1d(a(1,1), size(a)) 
    do i = 1, 3 
     write(*, '(2I4)') a(:,i) 
    end do 
    contains 
     subroutine set1d(array, s) 
      implicit none 
      integer, intent(in) :: s 
      integer, intent(out) :: array(s) 
      integer :: i 
      do i = 1, s 
       array(i) = 3 * i 
      end do 
     end subroutine set1d 
end program dyn_array 
+0

Не сегодня сатана! Сила принимаемых форм массивов заставляет вас! Почему бы не передать 'array (:)' и использовать функцию запроса 's = size (array)' – jlokimlin

+0

Я не пробовал. Можете ли вы передать 2D-массив в подпрограмму, которая ожидает 1D-массив и получит нужный размер? – chw21

+0

Синтаксис идентичен синтаксису массивов отложенной формы при определении массивов с атрибутом 'pointer' или' allocatable'. Смотрите: http://stackoverflow.com/questions/38140951/fortran-subroutine-returning-wrong-values/38154225#38154225 – jlokimlin

0

«Вы можете передать 2D-массив в подпрограмма, которая ожидает 1D-массив и получит нужный размер? "

Вы можете использовать reshape, но если ваш код опирается на компилятор, чтобы помочь, то 2D в 1D является рискованным. Вы можете использовать RESHAPE до и после ... Или вы можете иметь 2 процедуры, которые мы можем назвать set1d и set2d. Затем в модуле вы можете выбрать, что вы хотите использовать. У вас могут быть целые числа, float (s), complex (s), byte.

Вы назовете массив $ Set (Array, s)

MODULE Stuff 
    PUBLIC :: Array$Set 

    PRIVATE 
    INTERFACE Array$Set 
    MODULE PROCEDURE Set1d_Float, Set1D_Double, set2D_Float, Set2D_Double 
END INTERFACE Array$Set 

CONTAINS 

SUBROUTINE Set1D_Float(Array,S)... 
!$DIR ATRIBUTES ASUUME_ALIGND:64    :: Array 
REAL, DIMENSION(:,:), CONTIGUOUS, INTENT(INOUT) :: Array 
REAL, DIMENSION(:,:),    INTENT(IN ) :: S 
REAL, DIMENSION(2)        :: Shapez 
... 
Shapez = Shape(Array) 
DO I = 1, Shapez(1) 
    DO J = 1, Shapez(2) 
... 
END SUBROUTINE Set1D_Float 

END MODULE Stuff 

Для примера: если (option1), то реальный (вид = 8), размещаемый :: arr1 (:) еще реальный (вид = 8), размещаемый :: arr1 (:, :) ENDIF

Я хотел бы предложить следующее:

!DIR ATTRIBUTES ALIGN:64  :: Arr1 
REAL, DIMENSION(:), ALLOCATABLE :: Arr1 
... 


if (option1) then 
    ALLOCATE(Arr1(<#>)) 
else 
    ALLOCATE(Arr1(<#>*<#2>)) 
    RESHAPE(Arr1, SHAPE=/(#1,#2)) !Check the syntax 
endif 

CALL Array$Set(Arr1,s) !It'll find the right one... 

!... at the bottom ... 
IF(ALLOCATED(Arr1)) DEALLOCATE(Arr1) 
END PROGRAM 
+1

'kind = 4' и' kind = 8' действительно уродливые. Не используйте его в качестве примера хорошего кода. –

+0

Вы уверены, что можете комбинировать ПОЛНОСТЬЮ и КОНТИГУРУ? Один подразумевает другой. ALIGN будет выполняться только одним конкретным компилятором –

+1

'ASUUME_ALIGND' выглядит неправильно, а' '' не разрешено в именах имен Fortran. –

Смежные вопросы