有幾個線程的標題類似,但我不相信它們是相同的。其中一個非常類似於fortran pass allocated array to main procedure,但答案需要Fortran 2008.我是在Fortran 90/95解決方案之後。將從SUBTROUTINE分配的數組傳遞給Fortran中的主程序
另一個非常好的,非常相似的線程是Dynamic array allocation in fortran90。然而,在這種方法中,當它們在子程序中分配時,它們似乎不會解除分配,這看起來很奇怪。我的方法在表面看起來至少是相同的,但是當我在主程序中打印數組時,僅打印空格。當我在子程序本身中打印時,數組將打印以篩選正確的值和正確數量的值。
在下面的MAIN程序調用一個子程序。該子程序將數據讀入可分配數組,並將該數組傳回主程序。我通過使用每個設計用於在輸入文件中查找特定術語的小型子例程來執行此操作。所有這些子程序都在一個模塊文件中。所以有三個文件: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中,但這並不起作用。我已經嘗試過了,因爲代碼目前是...代碼工作(即沒有bug),但它不會通過epsilstar
從它正確找到它的子例程創建一個數組。
請注意,您在代碼中使用的可分配參數是Fortran 2003標準功能。 – IanH
這是很好的知道。謝謝!有沒有關於如何在Fortran 90/95中傳遞數組的簡單描述?我不太喜歡的一種方式是先創建一個子程序,然後獲取我所處理的事物的大小,然後就不需要分配了。那是Fortran 90/95方法嗎? –