2017-04-21 7 views
1

似たタイトルのスレッドがいくつかありますが、それらは同じではないと思います。 1つは非常によく似たfortran pass allocated array to main procedureでしたが、答えにはFortran 2008が必要でした。私はFortran 90/95ソリューションの後です。SUBTROUTINEから割り当てられた配列をFortranのメインプログラムに渡す

もう1つの非常によく、非常によく似たスレッドはDynamic array allocation in fortran90です。しかし、このメソッドでは、サブルーチンで割り振りをしている間に割り振りを解除するように見えることはありません。私のメソッドは、少なくとも同じになるように表面を見ていますが、メインプログラムで配列を印刷すると、空白だけが表示されます。サブルーチン自体で印刷すると、配列は正しい値と正しい数の値を画面に表示します。

以下では、MAINプログラムがサブルーチンを呼び出します。このサブルーチンは、データを割り当て可能な配列に読み込み、配列をメインプログラムに戻します。私は、入力ファイルの特定の用語を探すために設計された小さなサブルーチンを使用してこれを行います。これらのサブルーチンはすべて1つのモジュールファイルにあります。したがって、Main.f90、input_read.f90、およびfilename.inpという3つのファイルがあります。

プログラムMain.f90で割り当て可能な配列と、プログラムのMainに渡される前に実際に割り当てられ、サイズが割り当てられ、割り当てが解除された呼び出されたサブルーチンの配列を渡す方法がわかりません。これはおそらく混乱するように聞こえるので、ここでは3つのプログラムすべてのコードを示します。私はそれを貼り付けたときの貧弱な書式設定についてお詫び申し上げます。私はすべての行を分離しようとしました。

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 

そして再び、私は渡す方法を見つけ出すことはできません割り当てられました0配列をメインプログラムに追加します。割り当てられていない配列をmain.f90からサブルーチンに渡してみました。内側に配置し、戻し、main.f90で割り当てを解除しましたが、うまくいきませんでした。コードが現在動作しているので、試しましたが、コードは動作します(つまりバグがありません)が、正しく見つけて配列を作成するサブルーチンからepsilstarを渡しません。

+0

コードで使用している割り当て可能な引数は、Fortran 2003の標準機能です。 – IanH

+0

これは知っておきたいことです。ありがとう! Fortran 90/95で配列を渡す方法を簡単に説明していますか?私が本当に気に入らない方法の1つは、最初にサブルーチンを実行して、後にあるもののサイズを取得することです。割り当てが不要です。これはFortran 90/95方式ですか? –

答えて

0

私がした間違いは、メインプログラムに渡す前にサブルーチンで配列の割り当てを解除することでした。割り当てを解除しないと、配列は正常に戻されました。また、私はメインプログラムでも割り当てを解除しません。

+0

受け取ったフィードバックがどれほど少ないかに注目してください。コメントや回答はありません。あなたの質問をより合理化してみてください。すべてのコードが含まれていてもそれを変更しないでくださいが、まだ問題を示すより短いコードを作成しようとしてください([mcve])。必要な作業をやめるまで、コードの一部を削除します。そして、*最も重要な*もの:多くのテキストを含めないで、すぐにポイントに行く。 –

+0

私はそれを投稿した後に自分で解決してからでもそれを維持すべきかどうか不思議です。それは冗長なようだ。多分他人には有益でしょうが、あなたが言ったように、かさばるものです。 –

関連する問題