如何在每次迭代中将1D数组转换为FORTRAN中的2D数组列?

时间:2015-06-30 02:01:05

标签: matrix vector fortran

我已经花了整整一周。但我无法解决它。

我想在循环中将一维数组转换为二维数组的列。在第一次迭代时,该2D阵列的大小与1D阵列相同。所以。施放它应该没有问题。在第二次迭代中,1D阵列将具有不同的元素。我想将它转换为2D数组的第二列。这种情况仍在继续,算法是这样的,你无法猜测在开始计算之前分配2D数组的列数。

在Matlab中,可以使用这样的do循环:

do iter=1:m
p(:,iter) = r
end

但FORTRAN怎么样? 以下测试代码旨在表明我的意思:

代码1 :(使用指针)

program ptrtest

 real, pointer, CONTIGUOUS :: Mr(:)
 real, pointer, CONTIGUOUS :: Mp(:,:)
 real, DIMENSION(9) ::abc


 integer :: n = 2
 iter=3

 Do i=1,iter

 alpha2 = 2
 allocate(Mr(n**2))
 abc= 42

 Mr(1:n**2) = 0.5 * abc(1:n**2)
 write(*,*) 'Mr='
 write(*,555) Mr

 Mr(1:n**2) => Mp(1:n**2,1:1) 

 WRITE(*,*) 'Mp='
 WRITE(*,555) Mp

 end do

 555  FORMAT(F12.4,1X) 


 end program ptrtest

错误:

gfortran -Wall -o "1234" "1234.f95" (in directory: /home/vahid/Desktop)
1234.f95:26.15:
 Mr(1:n**2) => Mp(1:n**2,1:1)
               1
Error: Rank remapping target must be rank 1 or simply contiguous at (1)
Compilation failed.

代码2 :(使用简单的循环)

program ptrtest

 real, pointer, CONTIGUOUS :: Mr(:)
 real, pointer, CONTIGUOUS :: Mp(:,:)
 real, DIMENSION(9) ::abc


 integer :: n = 2
 iter=3

 Do i=1,iter

 alpha2 = 2
 allocate(Mr(n**2))
 abc= 42

 Mr(1:n**2) = 0.5 * abc(1:n**2)
 write(*,*) 'Mr='
 write(*,555) Mr

 do j = 1, iter
    Mp(:, j) = Mr
 end do

 WRITE(*,*) 'Mp='
 WRITE(*,555) Mp

 end do

 555  FORMAT(F12.4,1X) 


 end program ptrtest

ERROR:

 Mr=
     21.0000
     21.0000
     21.0000
     21.0000

Program received signal SIGSEGV: Segmentation fault - invalid memory reference.

Backtrace for this error:
#0  0x7F1F888E4777
#1  0x7F1F888E4D7E
#2  0x7F1F8853CD3F
#3  0x400D67 in MAIN__ at 1234.f95:?
Segmentation fault (core dumped)

1 个答案:

答案 0 :(得分:2)

不确定你的意思。我按照你设想的方式尝试了它:

program vec2mat
    implicit none
    integer :: r(3), m(3, 3), i

    r = (/ 1, 2, 3/)
    do i = 1, 3
        m(:, i) = r
    end do

    write(*, '(3I4)') m

end program vec2mat

它完美无缺:

$ ./vec2mat
   1   2   3
   1   2   3
   1   2   3

(当然,多维数组中的第一个索引变化最快。)

好的,自从我发布以来,您添加了更多信息:

DATA已弃用。它仍然有效,但没有括号:

DATA r/1.1, 2, 3, 4/

但是如果你想立即初始化r,通常最好将它写在变量声明中:

REAL*8, DIMENSION(4) :: r = (/1.1, 2, 3, 4/)

在实际的代码块中,根本不需要使用DATA(我甚至不确定它是否允许)。请继续并指定值:

ALLOCATE r(4)
r = (/1.1, 2, 3, 4/)

(你必须先分配一个可分配的数组,然后才能写东西。)

最后,ALLOCATE错误似乎很奇怪:

ALLOCATE(p)

无法工作,因为程序不知道为p分配多少空间。但

ALLOCATE(p(1:4, 1:4))

应该工作得很好。

通常,编译器会输出导致错误的整行,而不是将其缩写为其他内容。因此,假设ALLOCATE行没有改变,我唯一能想到的是迟到的DATA(据我所知,DATA应该是声明块的一部分,ALLOCATE是指令块的一部分,因此ALLOCATE永远不会在DATA之前弄乱。

替换

DATA r(/1.1, 2, 3, 4/)

ALLOCATE(r(4))
r = (/1.1, 2, 3, 4/)

你应该好好去。