How to convert 2D array to 1D array in Fortran code?

北城以北 提交于 2019-12-10 19:07:51

问题


How do I convert r(i,j) to a 1D array so that I can sort the number easily?

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

I have to calculate the distance and save this in array as r (i,j). I want to convert r(i,j) to a 1 dimensional array, so that I can sort the r(i,j)easily.


回答1:


This seems tailor made for the reshape function: https://gcc.gnu.org/onlinedocs/gfortran/RESHAPE.html In this tiny example, reshape is used first to make a two-dimensional array A, then reshape is called again to make the one-dimension array C.

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:


Two previous answers have looked at the literal question of how to "convert" a rank-2 array in to a rank-1 array. They use different approaches:

  • copy the values in to a new rank-1 array;
  • in the end subroutine, have a rank-1 dummy argument associated with a rank-2 actual argument.

We can expand on both of these approaches.

reshape in its simplest form returns the desired rank-1 array. As an alternative, we can say that an array constructor, of the form [x] does that also:

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

When the actual argument is an array element the array dummy argument and those elements of the array including and following the actual argument are in sequence association.

With sequence association, the dummy array would be assumed-size or explicit shape. As in this case we're interested in the whole array, we could just pass the whole array:

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

where

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

The important thing here is that for explicit-shape and assumed-size dummy arguments the rank need not match that of the actual argument.

As noted before, this first group of approaches involves creating a new array. The use of sequence association doesn't. A third approach is also available: having a rank-1 pointer pointing to a rank-2 target. Creating a copy does also mean, of course, that any changes aren't reflected in the original rank-2 array. Sequence association and pointers will see changes passed on.

More detail on any one of these things can be found in other questions and answers.

Whether, for sorting, it makes much sense to treat a rank-2 array as a rank-1 array is a different consideration.




回答3:


You can pass r(1,1) to a subroutine that declares the argument to be a one-dimension array. This is legal in Fortran (with some restrictions that don't apply to your code) and uses a feature called "sequence association".



来源:https://stackoverflow.com/questions/51912396/how-to-convert-2d-array-to-1d-array-in-fortran-code

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!