将分配的数组从 SUBTROUTINE 传递到 Fortran 中的主程序
Passing an allocated array from a SUBTROUTINE to the main program in Fortran
我的帖子有几个标题相似,但我不认为它们是相同的。一个非常相似 fortran pass allocated array to main procedure,但答案需要 Fortran 2008。我正在寻求 Fortran 90/95 解决方案。
另一个非常好且非常相似的线程是 Dynamic array allocation in fortran90。然而,在这种方法中,当它们在子例程中进行分配时,它们似乎从未解除分配,这看起来很奇怪。我的方法至少在表面上看起来是一样的,但是当我在主程序中打印数组时,只打印空白 spaces 。当我在子例程本身中打印时,数组会打印以筛选正确的值和正确的值数。
下面一个主程序调用一个子程序。该子例程将数据读入可分配数组,并将该数组传回主程序。我通过使用小的子程序来做到这一点,每个子程序都设计用于在输入文件中查找特定的术语。所有这些子程序都在一个模块文件中。所以有三个文件:Main.f90、input_read.f90 和 filename.inp.
看来我不知道如何传递一个在程序 Main.f90 中可分配的数组以及在被调用的子例程中实际分配、调整大小然后在传递给程序 Main 之前释放的数组.这听起来可能令人困惑,所以这里是所有三个程序的代码。对于粘贴时格式不正确,我深表歉意。我试着把所有的行分开。
main.f90:
Program main
use input_read ! the module with the subroutines used for reading filename.inp
implicit none
REAL, Allocatable :: epsilstar(:)
INTEGER :: natoms
call Obtain_LJ_Epsilon(epsilstar, natoms)
print*, 'LJ Epsilon : ', epsilstar
END Program main
接下来是带有子例程的模块(我删除了 space 所需的所有子程序),input_read.f90:
module input_read
contains
!===============================================================
!===============================================================
Subroutine Obtain_LJ_Epsilon(epsilstar,natoms)
! Reads epsilon and sigma parameters for Lennard-Jones Force-Field and also
! counts the number of types of atoms in the system
!===============================================================
!===============================================================
INTEGER :: error,line_number,natoms_eps,i
CHARACTER(120) :: string, next_line, next_next_line,dummy_char
CHARACTER(8) :: dummy_na,dummy_eps
INTEGER,intent(out) :: natoms
LOGICAL :: Proceed
real, intent(out), allocatable :: epsilstar(:)
error = 0
line_number = 0
Proceed = .true.
open(10,file='filename.inp',status='old')
!=============================================
! Find key word LJ_Epsilon
!=============================================
DO
line_number = line_number + 1
Read(10,'(A120)',iostat=error) string
IF (error .NE. 0) THEN
print*, "Error, stopping read input due to an error reading line"
exit
END IF
IF (string(1:12) == '$ LJ_epsilon') THEN
line_number = line_number + 1
exit
ELSE IF (string(1:3) == 'END' .or. line_number > 2000) THEN
print*, "Hit end of file before reading '$ LJ_epsilon' "
Proceed = .false.
exit
ENDIF
ENDDO
!========================================================
! Key word found, now determine number of parameters
! needing to be read
!========================================================
natoms_eps = -1
dummy_eps = 'iii'
do while ((dummy_eps(1:1) .ne. '$') .and. (dummy_eps(1:1) .ne. ' '))
natoms_eps = natoms_eps + 1
read(10,*) dummy_eps
enddo !we now know the number of atoms in the system (# of parameters)
close(10)
Allocate(epsilstar(natoms_eps))
epsilstar = 0.0
!============================================================
! Number of parameters found, now read their values
!============================================================
if(Proceed) then
open(11,file='filename.inp',status='old')
do i = 1,line_number-1
read(11,*) ! note it is not recording anything for this do loop
enddo
do i = 1,natoms_eps
read(11,*) dummy_char
read(dummy_char,*) epsilstar(i) ! convert string read in to real, and store in epsilstar
enddo
close(11)
PRINT*, 'LJ_epsilon: ', epsilstar ! printing to make sure it worked
endif
deallocate(epsilstar)
END Subroutine Obtain_LJ_Epsilon
end module input_read
最后是输入文件:filename.inp
# Run_Type
NVT
# Run_Name
Test_Name
# Pressure
1.0
# Temperature
298.15
# Number_Species
# LJ_epsilon
117.1
117.1
117.1
# LJ_sigma
3.251
3.251
3.251
END
同样,我不知道如何将分配的 epsilstar
数组传递给主程序。我试过将一个未分配的数组从 main.f90 传递给子例程,在内部分配它,将它传递回去,然后在 main.f90 中释放它,但这没有用。我已经尝试过它,因为当前代码是......代码有效(即没有错误)但它没有从正确找到它并创建数组的子例程中传递 epsilstar
。
原来我犯的错误是在将数组传递给主程序之前在子程序中释放了数组。通过不解除分配,数组被正常发回。另外,我也不在主程序中释放。
我的帖子有几个标题相似,但我不认为它们是相同的。一个非常相似 fortran pass allocated array to main procedure,但答案需要 Fortran 2008。我正在寻求 Fortran 90/95 解决方案。
另一个非常好且非常相似的线程是 Dynamic array allocation in fortran90。然而,在这种方法中,当它们在子例程中进行分配时,它们似乎从未解除分配,这看起来很奇怪。我的方法至少在表面上看起来是一样的,但是当我在主程序中打印数组时,只打印空白 spaces 。当我在子例程本身中打印时,数组会打印以筛选正确的值和正确的值数。
下面一个主程序调用一个子程序。该子例程将数据读入可分配数组,并将该数组传回主程序。我通过使用小的子程序来做到这一点,每个子程序都设计用于在输入文件中查找特定的术语。所有这些子程序都在一个模块文件中。所以有三个文件:Main.f90、input_read.f90 和 filename.inp.
看来我不知道如何传递一个在程序 Main.f90 中可分配的数组以及在被调用的子例程中实际分配、调整大小然后在传递给程序 Main 之前释放的数组.这听起来可能令人困惑,所以这里是所有三个程序的代码。对于粘贴时格式不正确,我深表歉意。我试着把所有的行分开。
main.f90:
Program main
use input_read ! the module with the subroutines used for reading filename.inp
implicit none
REAL, Allocatable :: epsilstar(:)
INTEGER :: natoms
call Obtain_LJ_Epsilon(epsilstar, natoms)
print*, 'LJ Epsilon : ', epsilstar
END Program main
接下来是带有子例程的模块(我删除了 space 所需的所有子程序),input_read.f90:
module input_read
contains
!===============================================================
!===============================================================
Subroutine Obtain_LJ_Epsilon(epsilstar,natoms)
! Reads epsilon and sigma parameters for Lennard-Jones Force-Field and also
! counts the number of types of atoms in the system
!===============================================================
!===============================================================
INTEGER :: error,line_number,natoms_eps,i
CHARACTER(120) :: string, next_line, next_next_line,dummy_char
CHARACTER(8) :: dummy_na,dummy_eps
INTEGER,intent(out) :: natoms
LOGICAL :: Proceed
real, intent(out), allocatable :: epsilstar(:)
error = 0
line_number = 0
Proceed = .true.
open(10,file='filename.inp',status='old')
!=============================================
! Find key word LJ_Epsilon
!=============================================
DO
line_number = line_number + 1
Read(10,'(A120)',iostat=error) string
IF (error .NE. 0) THEN
print*, "Error, stopping read input due to an error reading line"
exit
END IF
IF (string(1:12) == '$ LJ_epsilon') THEN
line_number = line_number + 1
exit
ELSE IF (string(1:3) == 'END' .or. line_number > 2000) THEN
print*, "Hit end of file before reading '$ LJ_epsilon' "
Proceed = .false.
exit
ENDIF
ENDDO
!========================================================
! Key word found, now determine number of parameters
! needing to be read
!========================================================
natoms_eps = -1
dummy_eps = 'iii'
do while ((dummy_eps(1:1) .ne. '$') .and. (dummy_eps(1:1) .ne. ' '))
natoms_eps = natoms_eps + 1
read(10,*) dummy_eps
enddo !we now know the number of atoms in the system (# of parameters)
close(10)
Allocate(epsilstar(natoms_eps))
epsilstar = 0.0
!============================================================
! Number of parameters found, now read their values
!============================================================
if(Proceed) then
open(11,file='filename.inp',status='old')
do i = 1,line_number-1
read(11,*) ! note it is not recording anything for this do loop
enddo
do i = 1,natoms_eps
read(11,*) dummy_char
read(dummy_char,*) epsilstar(i) ! convert string read in to real, and store in epsilstar
enddo
close(11)
PRINT*, 'LJ_epsilon: ', epsilstar ! printing to make sure it worked
endif
deallocate(epsilstar)
END Subroutine Obtain_LJ_Epsilon
end module input_read
最后是输入文件:filename.inp
# Run_Type
NVT
# Run_Name
Test_Name
# Pressure
1.0
# Temperature
298.15
# Number_Species
# LJ_epsilon
117.1
117.1
117.1
# LJ_sigma
3.251
3.251
3.251
END
同样,我不知道如何将分配的 epsilstar
数组传递给主程序。我试过将一个未分配的数组从 main.f90 传递给子例程,在内部分配它,将它传递回去,然后在 main.f90 中释放它,但这没有用。我已经尝试过它,因为当前代码是......代码有效(即没有错误)但它没有从正确找到它并创建数组的子例程中传递 epsilstar
。
原来我犯的错误是在将数组传递给主程序之前在子程序中释放了数组。通过不解除分配,数组被正常发回。另外,我也不在主程序中释放。