Cómo inicializar matrices bidimensionales en Fortran

En C, puede inicializar fácilmente una matriz usando la syntax de llaves, si no recuerdo mal:

int* a = new int[] { 1, 2, 3, 4 }; 

¿Cómo se puede hacer lo mismo en Fortran para arreglos bidimensionales cuando se desea inicializar una matriz con valores de prueba específicos para fines matemáticos? (Sin tener que indexar doblemente cada elemento en declaraciones separadas)

La matriz está definida por

 real, dimension(3, 3) :: a 

o

 real, dimension(:), allocatable :: a 

Puedes hacerlo usando remodelar y formar elementos intrínsecos. Algo como:

 INTEGER, DIMENSION(3, 3) :: array array = reshape((/ 1, 2, 3, 4, 5, 6, 7, 8, 9 /), shape(array)) 

Pero recuerda el orden de la columna principal. La matriz será

 1 4 7 2 5 8 3 6 9 

después de remodelar

Entonces para obtener:

 1 2 3 4 5 6 7 8 9 

también necesitas transponer intrínsecamente:

 array = transpose(reshape((/ 1, 2, 3, 4, 5, 6, 7, 8, 9 /), shape(array))) 

Para un ejemplo más general (matriz 2D asignable con diferentes dimensiones), se necesita un tamaño intrínseco:

 PROGRAM main IMPLICIT NONE INTEGER, DIMENSION(:, :), ALLOCATABLE :: array ALLOCATE (array(2, 3)) array = transpose(reshape((/ 1, 2, 3, 4, 5, 6 /), & (/ size(array, 2), size(array, 1) /))) DEALLOCATE (array) END PROGRAM main 

Para matrices multidimensionales (rango> 1), la forma de Fortran para inicialización difiere de la solución C porque en C las matrices multidimensionales son solo matrices de matrices de etc.

En Fortran, cada rango corresponde a un atributo diferente del tipo de datos modificado. Pero solo hay un constructor de matriz, para matrices de rango 1. A partir de estas dos razones, la inicialización a través del constructor de conjuntos requiere la función intrínseca RESHAPE .

Además de lo que ya se ha respondido, hay una forma más directa de ingresar el valor de una matriz por fila en lugar de hacerlo por columna: restructurar tiene un argumento opcional ORDER que se puede usar para modificar el orden de llenar el elemento del multidimensional array con las entradas del constructor de la matriz.

Por ejemplo, en el caso del ejemplo en la primera respuesta, uno podría escribir:

 INTEGER, DIMENSION(3, 3) :: array=reshape( (/ 1, 2, 3, & 4, 5, 6, & 7, 8, 9 /), & shape(array), order=(/2,1/) ) 

obteniendo el relleno de la matriz matriz exactamente en el orden mostrado por las líneas de código.

La matriz (/2, 1/) fuerza al índice de columna (2) a tener precedencia en el índice de fila (1) , dando el efecto deseado.

La inicialización de la matriz se puede hacer en la statement de statement de la matriz, como se muestra a continuación:

 program test real:: x(3) = (/1,2,3/) real:: y(3,3) = reshape((/1,2,3,4,5,6,7,8,9/), (/3,3/)) integer:: i(3,2,2) = reshape((/1,2,3,4,5,6,7,8,9,10,11,12/), (/3,2,2/)) end program test 

Me sorprende que

  real:: y(3,3) = (/(/1,2,3/),(/4,5,6/),(/7,8,9/)/) 

no es aceptado por el comstackdor (intentado g95, gfortran). Resulta que la shape de (/(/1,2,3/),(/4,5,6/),(/7,8,9/)/) es 9 y no 3 3 !