Fortran 90 не сохраняет нижние/верхние границы массива после копирования в другой выделяемый массив

это не работает

program main
   implicit none
   integer :: nx = 3
   integer :: ny = 5
   integer :: nz = 8

   real, allocatable, dimension(:,:,:) :: A
   real, allocatable, dimension(:,:) :: B

   allocate(A(nx,0:ny,nz) )
   ! ...do something with array A and at some point cope a slice of A to B:
   B = A(:,:,1)
   ! in this case B is (1:nx, 1: ny+1) 
end program main

Приведенный выше код автоматически выделяет B и копирует A(:,:,1) в B. Однако он не сохраняет нижнюю/верхнюю границу 0/ny, вместо этого B имеет нижнюю границу 1 и верхнюю границу ny+1. .

Единственный способ, которым я нашел, чтобы сохранить нижнюю/верхнюю границу A 2dn-dim, - это явно выделить B как:

   allocate(B(nx, 0:ny))
   B = A(:,:,1)
   ! in this case B is (1:nx, 0:ny)

Учитывая, что у меня намного больше переменных, чем в этом простом примере, есть ли способ назначить как B = A (:,:, 1), а также сохранить границы A без явного выделения B?


person pablosaa    schedule 01.02.2020    source источник
comment
Я видел такое же поведение. Это не совсем баг, а случайная фича. По сути, вы копируете один массив в другой с разными границами с помощью оператора =.   -  person John Alexiou    schedule 11.04.2020
comment
Отвечает ли это на ваш вопрос? Сохранение границ распределения во внутреннем назначении   -  person francescalus    schedule 11.04.2020
comment
Спасибо, francescalus, да частично отвечает.   -  person pablosaa    schedule 11.04.2020


Ответы (2)


A(:,:,1) — это выражение. Он имеет границы (1:nx, 1:ny), ОБА ранга начинаются с 1. Это не исходный массив, это новое выражение.

Однако, даже если это был массив с другими нижними границами, автоматическое выделение всегда выделяет индексы, начиная с 1. По сути, правая часть снова представляет собой выражение.

В вашем случае вам нужно выделить явно.

person Vladimir F    schedule 01.02.2020
comment
Спасибо @vladimir-f за ответ. A(:,:,1) на самом деле является исходным массивом, и при назначении B он копирует все элементы из границ (1:nx, 0:ny) в (1:nx, 1:ny+1). Поскольку у меня есть много массивов, таких как A, с разными нижними/верхними границами, мне было интересно, есть ли способ скопировать напрямую, сохраняя границы без явного выделения. - person pablosaa; 03.02.2020
comment
@pablosaa НЕТ, пожалуйста, прочитайте мой ответ еще раз. A - исходный массив. A(:,:,1) — это подмассив, это НЕ исходный массив, это выражение. Я понимаю, что вы хотели сделать, и мой ответ как раз об этом. - person Vladimir F; 03.02.2020

Вы можете использовать:

allocate(B(lbound(A,1):ubound(A,1), lbound(A,2):ubound(A,2)))
person mohammad bagher Malekhosseini    schedule 10.04.2020
comment
Да, похоже, единственный обходной путь — это явно выделить переменную с нижней и верхней границей использования source=A при распределении. - person pablosaa; 11.04.2020