Исправлена ​​форма массива Fortran Allocate с размером для чтения из файла - PullRequest
0 голосов
/ 06 июля 2018

Я читаю из файла, который содержит значение T, которое будет использоваться для инициализации нескольких массивов, которые примут T в качестве первого измерения с помощью allocate позже. т.е.

subroutine read_file(T,F,array,A,B,C,...)
    ...
    real, intent(out) :: T,F
    real, intent(in) :: A,B,C
    real, intent(out) :: array
    ...
    read(1,*) T
    ...
    read(1,*) F
    ...
    read(1,*) array(1), array(5), array(6)
    read(1,*) array(2), array(4)
    read(1,*) array(3)
    ...
    if (F.eq.1) then
        array(1) = A(1)
        array(2) = B(2)
        array(3) = C(3)
    endif
    ...
program main
    ...
    do I=1,nproc
        ...
        do J=1,nsteps
            ...
            call read_file(T,F,array,A,B,C,...)
            ...
        enddo
        ...
        if (F.eq.1.and.etc.) then
            ...
            allocate(A(T,3))
            allocate(B(T,6))
            allocate(C(T))
            ...
        endif
        ...
    enddo

Оператор read содержится в подпрограмме read_file модуля в modules.for. Операторы allocate находятся в main.for, где также вызывается read_file.

Подпрограмма read_file также читает много других вещей, и она вызывается много раз в течение 1 выполнения кода, где некоторые файлы могут иметь T равным нулю.

Мне нужно передать A, B и C в read_file. В зависимости от состояния флага F, также считываемого в файле read_file, значения в A, B и C должны быть присвоены массиву (1,6), который в противном случае считывался бы непосредственно из файла.

Итак, я предполагаю, что мой вопрос: как передать массивы, которые, возможно, не были распределены по размеру? Я написал в коде проверки, чтобы убедиться, что A, B и C не будут фактически использоваться, если они не прошли выделение с известным размером, заданным как пользовательский ввод T, но компилятор давал мне проблемы.

Я попытался скомпилировать код, и компилятор Intel сначала возвратил ошибку, заявив, что типы для A, B, C не объявлены в read_file, поэтому я объявил их, используя T и real :: A(T,3) в read_file. Затем он сказал, что так как T является intent(out), его нельзя использовать для определения размерности A, B и C, поскольку они intent(in). Таким образом, я удалил intent(out) из T (так как сейчас это просто real :: T).

А теперь ошибка говорит:

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

Я отредактировал свой вопрос, чтобы предоставить больше кода и уточнить мой вопрос.

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

Спасибо!

Джесси

1 Ответ

0 голосов
/ 06 июля 2018

Кажется, что самый безопасный способ справиться с описанной вами проблемой - позволить read_file обработать выделение, то есть передать A,B,C в read_file как

real, intent(inout), allocatable :: A(:,:), B(:,:), C(:,:) 

С intent(inout), позволяющим вам вызывать read_file несколько раз с одним и тем же A,B,C, не теряя информацию из предыдущих вызовов. Если это не требуется, не стесняйтесь использовать только intent(out). Передача нераспределенных массивов в качестве аргументов - это нормально, просто убедитесь, что выделение произошло перед попыткой любого доступа.

Затем вы можете выделить A,B,C внутри read_file, после прочтения T.

Если темперирование с read_file невозможно или вы хотите, чтобы распределение происходило в main, вы также можете использовать описанный вами подход. Сначала выделите A, B, C как фиктивные массивы

allocate(A(0,0), B(0,0), C(0,0)) 

, который вы можете передать первому вызову read_file (разрешены массивы 0, просто убедитесь, что вы не пытаетесь получить доступ к их записям). Если я правильно понял, первый вызов не будет выполнять никаких операций над A,B,C, и они должны быть распределены только при последующих вызовах read_file. В этом случае распределение в main.for также работает.

Как только вы получили T, вы можете перераспределить A, B, C с помощью

if(allocated(A)) deallocate(A)
allocate(A(T,3))

Затем вы можете передать перераспределенные массивы следующему вызову read_file.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...