【问题标题】:Passing an allocated array from a SUBTROUTINE to the main program in Fortran将分配的数组从 SUBTROUTINE 传递到 Fortran 中的主程序
【发布时间】:2017-09-17 21:40:42
【问题描述】:

有几个主题与我的标题相似,但我不相信它们是相同的。一个与fortran pass allocated array to main procedure 非常相似,但答案需要 Fortran 2008。我追求的是 Fortran 90/95 解决方案。

另一个非常好的和非常相似的线程是Dynamic array allocation in fortran90。然而,在这种方法中,当它们在子例程中分配时,它们似乎从未释放,这似乎很奇怪。我的方法至少表面上看起来是一样的,但是当我在主程序中打印数组时,只打印了空格。当我在子例程本身中打印时,数组会打印以筛选正确的值和正确的值数量。

下面的主程序调用一个子程序。该子例程将数据读入一个可分配数组,并将该数组传回主程序。我通过使用每个设计用于在输入文件中查找特定术语的小型子程序来做到这一点。所有这些子程序都在一个模块文件中。所以有三个文件: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

接下来是带有子例程的模块(我删除了所有必要的空格),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 2003 标准功能。
  • 很高兴知道这一点。谢谢!是否有关于如何在 Fortran 90/95 中传递数组的简单描述?我不太喜欢的一种方法是首先有一个子程序通过并获取我所追求的东西的大小,然后就不需要分配了。那会是 Fortran 90/95 方法吗?

标签: fortran gfortran fortran90 dynamic-arrays fortran95


【解决方案1】:

事实证明,我犯的错误是在将数组传递给主程序之前在子例程中取消分配数组。通过不解除分配,数组被很好地送回。另外,我也不在主程序中解除分配。

【讨论】:

  • 请注意您收到的反馈很少。没有 cmets 或答案。尽量让你的问题更简洁。包含所有代码很好,不要更改它,但尝试制作一个仍然存在问题的较短代码(minimal reproducible example)。删除部分代码,直到它停止执行您需要的操作。还有最重要的一点:不要包含那么多文字,直奔主题。
  • 我很好奇我是否应该保持它,因为我在发布它一段时间后自己解决了它。似乎是多余的。也许它对其他人有用,但就像你说的,它有点笨重。
猜你喜欢
  • 2020-12-05
  • 2018-01-21
  • 2012-10-15
  • 2016-12-15
  • 1970-01-01
  • 2019-11-06
  • 2017-07-19
  • 1970-01-01
  • 2013-04-26
相关资源
最近更新 更多