Сокращение 4-х мерного массива до 2-х Фортранов - PullRequest
0 голосов
/ 24 сентября 2018

Я пытаюсь изменить 4-мерный массив в Фортране на 2-мерный:

do k=1,nA
   do m=1,nA
      do l=1,nB
         do n=1,nB

           p = k * nA + m
           q = l * nB + n

           Lpq(p,q) = Aij(k,m,l,n) 

         end do
      end do
   end do
end do

Как правильно определить индексы p и q?

Ответы [ 2 ]

0 голосов
/ 26 сентября 2018

Это зависит от того, что вы хотите сделать с Aij и Lpq.Если вы просто хотите изменить индексирование, чтобы иметь более легкий доступ к элементам массива, и хотите использовать Lpq в качестве массива только для чтения, вы вполне можете использовать оператор EQUIVALENCE.Кроме того, это сэкономит место в памяти, потому что это только повторно интерпретирует массив.Если вы хотите рассматривать их как независимые массивы, вы можете сделать копию Lpq следующей и использовать эту копию.

  integer Aij(nA,nA,nB,nB)
  integer Lpq(nA*nA,nB*nB), Lpq_copy(nA*nA,nB*nB)
  equivalence (Aij, Lpq)

! fill Aij with test data
  do k=1,nA
  do m=1,nA
  do l=1,nB
  do n=1,nB
    Aij(k,m,l,n) = k*10000+m*1000+l*100+n
  end do
  end do
  end do
  end do

  print *, Lpq

! make a copy if needed
  Lpq_copy = Lpq
  Lpq(1,1) = 1 ! this will affect Aij, but not Lpq_copy
0 голосов
/ 25 сентября 2018

Следующий ответ делает следующее предположение:

  • Оба Aij и Lpq имеют начальный и конечный индексы по умолчанию (т. Е. Начальные индексы равны ОДНО, а конечные индексы являются соответствующими измерениями).Т.е.

    TYPE, DIMENSION(nA,nA,nB,nB) :: Aij
    TYPE, DIMENSION(nA*nA,nB*nB) :: Lpq
    

Есть много способов отобразить Aij на Lpq, но вы определили, где второй и четвертый индексы в Aij (обозначаемые m и n) - самые быстрые индексы в Lpq. Это означает:

Aij(1,1  ,1,1) => Lpq(1,1)
...
Aij(1,nA ,1,1) => Lpq(nA,1)
Aij(2,1  ,1,1) => Lpq(nA+1,1)
...
Aij(2,nA ,1,1) => Lpq(2*nA,1)
...
Aij(nA,nA,1,1) => Lpq(nA*nA,1)

Аналогичное сопоставление существует для других измерений.

текущее преобразование, которое вы реализовали (т.е. p = k * nA + m) устанавливает p=nA+1, когда k=m=1, и возвращает p=(nA+1)*nA для k=m=nA. Таким образом, вы пропускаете нижний диапазон и выходите за верхний диапазон.

вам нужноопределите сопоставление следующим образом:

p = (k-1) * nA + m
q = (l-1) * nB + n

Обратите внимание, однако, как уже упоминалось в комментариях, в Fortran есть встроенная процедура reshape, которая может выполнять такие сопоставления для вас. К сожалению, в вашем конкретном случае этоне так удобно из-за выбора постовt index.

  • Если вы выберете самые быстрые индексы k и l, то вы можете использовать один reshape, поскольку система уже находится в основной колонкепорядок:

    Lpq = reshape(Aij,[nA*nA,nB*nB])
    
  • Если вы выбираете самые быстрые индексы m и n, то вам нужно два вызова на reshape.Первый - поменять местами два индекса и привести систему в порядок столбцов, а второй - изменить форму.

    Bij = reshape(Aij,[nA,nA,nB,nB],order=[2,1,4,3])
    Lpq = reshape(Bij,[nA*nA,nB*nB])
    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...