Алгоритм вывода 3D массива

Я изо всех сил пытаюсь придумать алгоритм для вывода 3D-массива. В основном у меня есть массив из 9 2D-массивов, которые мне нужно объединить в сетку 3X3 и вывести в текстовый файл в виде матрицы. Так что я:

real:: array3D(9,16,16)

И мне нужно последовательно (слева направо, сверху вниз) объединить эти 9 массивов 16x16 в сетку 3x3:

real:: array2D(48,48)

Любая помощь будет здорово.

[Изменить: информация для комментариев]: это часть программы MPI, в которой матрица 48x48 разбивается на 9 матриц 16x16, где каждый из 9 процессов назначается одной «подсетке» большего массива. Подобно сетке судоку, как упоминалось в комментариях, где каждый процесс применяет формулу к каждому элементу в своей собственной подсетке. Окончательные значения, рассчитанные каждым процессом, затем необходимо поместить обратно в матрицу 48x48, чтобы отобразить их в текстовом файле. В настоящее время это выглядит так:

if(procID.ne.0)then!Send all arrays to root
    call MPI_SEND (array, row*col, MPI_REAL, 0, procID+1000, MPI_COMM_WORLD, ierr)
else
    complete(1,:,:)=array(:,:)
    do i=2, 9
        call MPI_RECV (recvArray, row*col, MPI_REAL, i-1, (i-1)+1000, MPI_COMM_WORLD, status, ierr)
        complete(i,:,:)=recvArray   
    end do

То, что я пытаюсь получить, - это алгоритм, который я могу использовать для отображения complete в текстовом файле в виде матрицы таким образом, чтобы мне было удобно читать. (Я знаю, что имена переменных отличаются от приведенных выше, но я попытался максимально упростить/обобщить свою первоначальную проблему. Здесь array снова имеет размеры 48x48, но меня интересует только блок 16x16 внутри каждого (9 головоломок судоку, только хочу одна подсетка от каждого), какой блок 16x16, который я хочу, определяется первыми индексами complete/array3D:1-9, я хочу взять эти подблоки и расположить их в другом массиве 48x48, скажем, arrayOut/array2D). Я постараюсь представить графическое объяснение проблемы, когда у меня будет возможность, если то, что я написал, не имеет особого смысла.

Спасибо @george, чей ответ приведен ниже, чтобы поместить это в массив, который вам нужен:

do majorRow=1,3
    do majorCol=1,3
        subBlock=(majorRow-1)*3+majorCol
        do minorRow=majorRow*16-(16-1),majorRow*16
            do minorCol=majorCol*16-(16-1),majorCol*16 
                outArray(minorRow,minorCol)=complete(subBlock,minorRow,minorCol)
            end do
        end do
    end do
    end do

person WireInTheGhost    schedule 09.01.2014    source источник
comment
Посмотрите на цикл do fortran.   -  person mbeckish    schedule 09.01.2014
comment
Я знаю, что ему нужен цикл, скорее всего, тройной вложенный. Это граничные условия цикла, с которыми я борюсь.   -  person WireInTheGhost    schedule 09.01.2014
comment
Граничные условия зависят от того, как организован ваш 3x3 и организованы ли 48 в вашем целевом массиве по строкам (3x16) или по столбцам (16x3). Затем вы можете либо перебрать три измерения исходного массива и поместить элементы на место в целевой матрице, либо перебрать два измерения целевой матрицы и получить элементы из источника. Способ расчета индексов зависит от желаемого макета.   -  person M Oehm    schedule 09.01.2014
comment
array2d(1:16,1:16)=array3d(1,1:16,1:16), затем array2d(1:16,17:32)=array3d(2,1:16,1:16) и так далее.   -  person Kyle Kanos    schedule 09.01.2014
comment
Спасибо @KyleKanos, это то, что у меня сейчас есть, но можно ли их обобщить?   -  person WireInTheGhost    schedule 09.01.2014
comment
Вы можете использовать целочисленное деление и функцию остатка mod, чтобы разделить ваше 9-мерное измерение на фрагменты 3x3. Или вы можете использовать массив поиска для новых координат строки и столбца.   -  person M Oehm    schedule 09.01.2014
comment
1+(n-1)*16:16+(n-1)*16, где n — первый индекс в array3d, будет работать для первых трех, вам, вероятно, придется использовать mod, чтобы получить следующие три.   -  person Kyle Kanos    schedule 09.01.2014
comment
@MOehm: 3x3, о котором он упоминал, кажется отдельной переменной из массивов 9x16x16 и 48x48.   -  person Kyle Kanos    schedule 09.01.2014
comment
@KyleKanos: я представляю себе трехмерный массив как большую сетку судоку, адресуемую ячейкой, локальными строками и столбцами, и двумерный массив как те же данные, адресуемые как глобальные строки и столбцы. Таким образом, 9-е измерение — это линейное представление 3x3, которое отображается в двумерном массиве (3*16 x 3*16).   -  person M Oehm    schedule 09.01.2014
comment
@MOehm: Ага, это имеет смысл.   -  person Kyle Kanos    schedule 10.01.2014
comment
@user2538235 user2538235 - Пожалуйста, покажите код, который у вас есть, чтобы мы могли знать, что вы знаете и что еще вам нужно.   -  person mbeckish    schedule 10.01.2014
comment
Поскольку массивы допускают произвольный доступ, вы можете заполнять элементы в любом порядке. Например, у вас может быть только два вложенных цикла от 0 до 47, и внутри самого внутреннего цикла выясните, как сопоставить координаты массива 2D с координатами массива 3D. Или вы можете сделать 3 вложенных цикла для перебора координат array3D и сопоставить их с координатами array2D. Или вы можете разбить его на еще большее количество вложенных циклов — решать вам. У вас есть предпочтения?   -  person mbeckish    schedule 10.01.2014
comment
Я добавил некоторую информацию выше. Комментарий о сетке судоку в значительной степени точен. У меня есть массив из 9, 16x16 массивов, которые я хотел бы расположить в порядке от 1 до 9, как они будут отображаться в головоломке судоку, а затем вывести двумерный массив в текстовый файл. Я думаю, чем меньше циклов, тем лучше, но пока результат правильный на этом этапе, я не возражаю :)   -  person WireInTheGhost    schedule 10.01.2014
comment
В вашем первоначальном вопросе не было ключевой информации о том, что вы работаете над программой MPI. Я думаю, что вам нужно исследовать mpi_scatterv и mpi_gatherv Здесь слишком поздно для меня, чтобы предоставить какую-либо дополнительную помощь, но посмотрите на ответ Джонатана Дурси здесь: stackoverflow.com/questions/9269399/   -  person High Performance Mark    schedule 10.01.2014
comment
Разве тот факт, что это программа MPI, более или менее не имеет отношения к моему вопросу? Вся информация отправлена ​​и собрана, проблема в отображении данных, или что-то более фундаментальное не так с тем, что я написал? Я смотрел на это в течение дня и готов попробовать что-нибудь :)   -  person WireInTheGhost    schedule 10.01.2014


Ответы (2)


не нужно копировать в новый массив только для вывода.

псевдокод: (возможно, я переставил строки/столбцы, но это легко исправить)

do majorrow=1,3
 do minorrow=1,16
   do majorcol=1,3
    subblock=(majorrow-1)*3+majorcol
    do minorcol=1,16 
           write(advance=no)array3D(subblock,minorrow,minorcol)
    enddo
   enddo !end of row
   write() ! to advance line at end of row.
enddo
enddo

обратите внимание, что самый внутренний цикл можно заменить на

 write(advance=no)array3D(subblock,minorrow,:)

вам по-прежнему не нужно заранее, так как у вас есть три записи в строке.

person agentp    schedule 11.01.2014
comment
Я вижу и понимаю, как это работает, и спасибо, это то, о чем я просил. Но если бы я хотел поместить его в массив, чтобы выполнить другие манипуляции, как бы я заставил его работать. Простое изменение строки 6 на outArray(minorRow,minorCol)=complete(subBlock,minorRow,minorCol) просто помещает все в 1-й подблок. - person WireInTheGhost; 13.01.2014
comment
Я сделал это сейчас, я добавлю код в сообщение. Спасибо еще раз - person WireInTheGhost; 14.01.2014

Если вы прибегаете к простым конструкциям do-loop, вам просто нужно перебрать большой 2d-массив поблочно, а затем сохранить соответствующие элементы из 3d-массива в правильном блоке 2d-массива.

BLKSZ=16
NBLOCK=3
DO IB=1,NBLOCK
  ISTA=BLKSZ*(IB-1)+1
  IEND=ISTA+BLKSZ-1
  DO JB=1,NBLOCK
    JSTA=BLKSZ*(JB-1)+1
    JEND=JSTA+BLKSZ-1
    array2D(ISTA:IEND,JSTA:JEND)=array3D(JB+NBLOCK*(IB-1),:,:)
  END DO
END DO

Обратите внимание, что трехмерный массив не очень эффективно упорядочен, поскольку блочный индекс является самым быстрым индексом. Предпочтительно, чтобы это был последний индекс (чтобы избежать промахов кеша).

person steabert    schedule 10.01.2014