如何在Fortran代码中将2D数组转换为1D数组?

时间:2018-08-18 20:43:07

标签: arrays fortran gfortran

如何将r(i,j)转换为一维数组,以便可以轻松地对数字进行排序?

program sort
  implicit none
  character CN*8,O*7
  integer j,iconf,nconf
  integer i,nbins,t
  integer n,nmax,ind,num,b
  parameter (n=216)
  double precision xbox,rq
  parameter (nmax=3091,nconf=1)
  double precision atom(nmax),id(nmax),ox(nmax),oy(nmax),oz(nmax)
  double precision xij,yij,zij,rij
  double precision r(n,n),A(n)
  open(unit=10,status='unknown',file='1000.gro')
   do iconf= 1,nconf
    write(*,*)iconf
     read(10,*)
     read(10,*)
   do i=1,n
     read(10,'(A8,A7,1i5,3f8.3)')CN,O,num,ox(i),oy(i),oz(i)
   enddo
     read(10,*)xbox        ! read the xbox for PBC

  open(unit=3,file='dist.txt')

   do i=1,n
    do j=1,n
   if(i .ne. j) then
   xij=ox(i)-ox(j)
   yij=oy(i)-oy(j)
   zij=oz(i)-oz(j)
   r(i,j)=dsqrt(xij**2 + yij**2 + zij**2)
      write(3,'(i3,2x,i3,4x,f17.15)') i,j, r(i,j)
    endif 
    enddo
    enddo
    enddo
    END

我必须计算距离并将其保存在数组中为r (i,j)。我想将r(i,j)转换为一维数组,以便可以轻松地对r(i,j)进行排序。

3 个答案:

答案 0 :(得分:4)

先前的两个答案已着眼于字面上的问题,即如何将“等级2”数组“转换”为等级1数组。他们使用不同的方法:

  • 将值复制到新的rank-1数组中;
  • 在结束子例程中,具有与rank-2实际参数关联的rank-1虚拟参数。

我们可以扩展这两种方法。

reshape以其最简单的形式返回所需的rank-1数组。或者,我们可以说[x]形式的数组构造函数也可以做到:

real r1d(6), r2d(3,2)
r2d=5.
r1d = [r2d]

当实际参数为array element时,数组伪参数与数组中包含和跟随实际参数的元素按顺序关联。

通过序列关联,伪数组将采用假定大小或显式形状。因为在这种情况下,我们对整个数组感兴趣,所以我们可以传递整个数组:

real r2d(3,2)
call sub(r2d)

其中

subroutine sub(r1d)
  real r1d(*) ! or r1d(6), etc.
end subroutine

这里重要的是,对于显式形状和假定大小的伪参数,其等级不必与实际参数的等级匹配。

如前所述,第一组方法涉及创建一个新数组。不使用序列关联。还可以使用第三种方法:让1级指针指向2级目标。当然,创建副本确实也意味着任何更改都不会反映在原始的rank-2数组中。序列关联和指针将看到更改。

有关这些问题中任何一项的更多详细信息,请参见其他问题和答案。

对于排序而言,将等级2数组作为等级1数组是另一种考虑因素,这很有意义。

答案 1 :(得分:3)

这似乎是为重整形函数量身定制的:https://gcc.gnu.org/onlinedocs/gfortran/RESHAPE.html在这个小例子中,首先使用重整形来形成二维数组A,然后再次调用reshape来形成一维数组C。 / p>

Program reshape_demo
    use, intrinsic :: iso_c_binding

    implicit none
    real(kind=c_float),allocatable :: A(:,:),C(:)
    integer(kind=c_int) :: krow
    allocate(A(3,3))
    A=reshape((/1,2,3,4,5,6,7,8,9/),(/3,3/))
    do krow=1,3
       write(*,fmt="(1p3e10.3)")A(krow,:)
    end do
    C=reshape(A,(/9/))
    write(*,fmt="(9(1x,f4.1))")C
End Program reshape_demo

答案 2 :(得分:2)

您可以将r(1,1)传递给一个子例程,该子例程将参数声明为一维数组。这在Fortran中是合法的(有一些不适用于您的代码的限制),并且使用一种称为“序列关联”的功能。