Arrays Multidimensionais#

Matrizes multidimensionais são armazenadas em ordem de maior coluna. Isso significa que o índice mais à esquerda (mais interno) endereça elementos continuamente. De um ponto de vista prático, isso significa que a parte da matriz V(:,1) é continua, enquanto que o passo entre os elementos da parte V(1,:) é a dimensão das colunas. Isso é importante ao passar pedaços da matriz para procedimentos que esperam trabalhar em dados contínuos.

É importante considerar a localização da memória na sua aplicação, normalmente quando realizando operações multidimensionais o acesso sequencial deve sempre avançar em passos unitários.

No exemplo à seguir a distância inversa entre dois conjuntos de ponto é calculada. Note que os pontos são guardados continuamente nas matrizes xyz1/xyz2, enquanto que o laço mais interno está avançando o índice mais externo da matriz a.

subroutine coulomb_matrix(xyz1, xyz2, a)
  real(dp), intent(in) :: xyz1(:, :)
  real(dp), intent(in) :: xyz2(:, :)
  real(dp), intent(out) :: a(:, :)
  integer :: i, j
  do i = 1, size(a, 2)
    do j = 1, size(a, 1)
      a(j, i) = 1.0_dp/norm2(xyz1(:, j) - xyz2(:, i))
    end do
  end do
end subroutine coulomb_matrix

Outro exemplo seria a contradição da terceira dimensão em uma matriz tridimensional:

do i = 1, size(amat, 3)
  do j = 1, size(amat, 2)
    do k = 1, size(amat, 1)
      cmat(k, j) = cmat(k, j) + amat(k, j, i) * bvec(i)
    end do
  end do
end do

Pedaços de matrizes contínuas podem ser usadas em remapeamento vinculados à matriz para permitir uso de matriz de ordem maior como matriz de ordem menor sem necessidade de remodelar e potencialmente criar uma cópia temporária da matriz.

Por exemplo, isso pode ser usado para suprimir a terceira dimensão de uma matriz tridimensional usando uma operação matriz-vetor:

subroutine matmul312(amat, bvec, cmat)
  real(dp), contiguous, intent(in), target :: amat(:, :, :)
  real(dp), intent(in) :: bvec(:)
  real(dp), contiguous, intent(out), target :: cmat(:, :)
  real(dp), pointer :: aptr(:, :)
  real(dp), pointer :: cptr(:)

  aptr(1:size(amat, 1)*size(amat, 2), 1:size(amat, 3)) => amat
  cptr(1:size(cmat)) => cmat

  cptr = matmul(aptr, bvec)
end subroutine matmul312