2017-07-14 17 views
0

OpenMPを初めて使用しました。並列doループを使用して、ある範囲のパラメータ値に対して厳しいODEシステムを解決したい。私は以下のコードをFortranで使用します。しかし、並列doループ内で(サブルーチンとして)剛性ソルバを呼び出すことが許可されているかどうかはわかりません。また、メインプログラムに戻る前に、サブルーチンの "r_value_s__value.txt"などのファイル名を持つファイルに時系列データを書きたいと思います。誰も助けることができます。以下はコードとエラーです。私はgfortranとフラグ-fopenmpを使ってコンパイルしました。 r>=10のためにオーバーフローするf6.4rのために:OpenMPパラメータスイープパラレル

PROGRAM OPENMP_PARALLEL_STIFF 

      USE omp_lib 
      IMPLICIT NONE 

      INTEGER :: I, J 
      INTEGER, PARAMETER :: RTOT=10, STOT=15 
      INTEGER :: TID 
      INTEGER, PARAMETER :: NUM_THREADS=8 
      DOUBLE PRECISION :: T_INITIAL, T_FINAL 
      CALL OMP_SET_NUM_THREADS(NUM_THREADS) 
      CALL CPU_TIME(T_INITIAL) 
      PRINT*, "TIME INITIAL ",T_INITIAL 
!$OMP PARALLEL DO PRIVATE(I,J,TID) 

      DO I=1,RTOT 
       DO J=1,STOT 
       TID=OMP_GET_THREAD_NUM() 
       CALL STIFF_DRIVER(TID,I,J,RTOT,STOT) 
       END DO 
      END DO 
!$OMP END PARALLEL DO 

      CALL CPU_TIME(T_FINAL) 
      PRINT*, "TIME FINAL ",T_FINAL 
      PRINT*, "TIME ELAPSED ",(T_FINAL-T_INITIAL)/NUM_THREADS 
     END PROGRAM OPENMP_PARALLEL_STIFF 

     SUBROUTINE STIFF_DRIVER(TID,II,JJ,RTOT,STOT) 

      USE USEFUL_PARAMETERS_N_FUNC 

      USE DVODE_F90_M 

!  Type declarations: 

      IMPLICIT NONE 


!  Number of odes for the problem: 

      INTEGER :: SERIAL_NUMBER, TID 
      INTEGER :: II, JJ, RTOT, STOT, IND 
      INTEGER :: J, NTOUT 
      INTEGER :: ITASK, ISTATE, ISTATS, I 

!  parameters : declaration 

      DOUBLE PRECISION, PARAMETER :: s0=0.450D0, dr=1.0D-4, ds=1.0D-2 

      DOUBLE PRECISION, DIMENSION(NEQ) :: Y, YOUT 
      DOUBLE PRECISION :: ATOL, RTOL, RSTATS, T, TOUT, EPS, TFINAL, DELTAT 
      DIMENSION :: RSTATS(22), ISTATS(31) 
      DOUBLE PRECISION :: bb, cc, ba, ba1, eta 
      CHARACTER(len=45) :: filename 

      TYPE (VODE_OPTS) :: OPTIONS 

      SERIAL_NUMBER=3011+II+(JJ-1)*RTOT 
      IND=TID+3011+II+(JJ-1)*RTOT 
      WRITE (*,12)SERIAL_NUMBER,TID 
    12 FORMAT ("SL. NO. ",I5," THREAD NO.",I3) 

      r=(II-1)*dr 
      s=s0+JJ*ds 

      EPS = 1.0D-9 

!   Open the output file: 

      WRITE (filename,93)r,s 
    93 FORMAT ("r_",f6.4,"_s_",f4.2,".txt") 
      OPEN (UNIT=IND,FILE=filename,STATUS='UNKNOWN',ACTION='WRITE') 

!  Parameters for the stiff ODE system 

      q0 = 0.60D0; v = 3.0D0 
      Va = 20.0D-4; Vs = 1.0D-1 
      e1 = 1.0D-1; e2 = 1.10D-5; e3 = 2.3D-3; e4=3.0D-4 
      del = 1.7D-4; mu = 5.9D-4 
      al = 1.70D-4; be = 8.9D-4; ga = 2.5D-1 

!   S and r dependent parameters 

      e1s = e1/s; e2s = e2/(s**2); e3s = e3/s; e4s = e4/s 
      dels = del*s; rs = r*s 
      e1v = e1/v;  e2v = e2/(v**2); e3v = e3/v; e4v = e4/v 
      delv = del*v;  rv = r*v 

!   SET INITIAL PARAMETERS for INTEGRATION ROUTINES 

      T = 0.0D0 
      TFINAL = 200.0D0 
      DELTAT = 0.10D0 
      NTOUT = INT(TFINAL/DELTAT) 
      RTOL = EPS 
      ATOL = EPS 
      ITASK = 1 
      ISTATE = 1 

!   Set the initial conditions: USING MODULE USEFUL_PARAMETERS_N_FUNC 

      CALL Y_INITIAL(NEQ,Y) 

!  Set the VODE_F90 options: 

      OPTIONS = SET_OPTS(DENSE_J=.TRUE.,USER_SUPPLIED_JACOBIAN=.FALSE., & 
      RELERR=RTOL,ABSERR=ATOL,MXSTEP=100000) 

!   Integration: 

      DO I=1,NTOUT 

      TOUT = (I-1)*DELTAT 

      CALL DVODE_F90(F_FUNC,NEQ,Y,T,TOUT,ITASK,ISTATE,OPTIONS) 

!   Stop the integration in case of an error 

      IF (ISTATE<0) THEN 
      WRITE (*,*)"ISTATE ", ISTATE 
      STOP 
      END IF 

!   WRITE DATA TO FILE 

      WRITE (IND,*) TOUT,T, Y(NEQ-2) 

     END DO 


     CLOSE(UNIT=IND) 

     RETURN 
    END SUBROUTINE STIFF_DRIVER 

At line ** of file openmp_parallel_stiff.f90 (unit = 3013) Fortran runtime error: File already opened in another unit

+1

'stiff_driver'では、2つの別々の' II'と 'JJ'ペアの' r'と 's'の値は同じです(小数点以下4桁と2桁まで)。それを確認できますか? – francescalus

+0

あなたのコードが現在立っているので、1つのスレッドは 'STIFF_DRIVER'を同時に呼び出すことはないので、より簡単なスキームを使用してユニット番号を導き出すことができます。 '3010 + tid'。 Fortran 2008コンパイラでは、 'OPEN(NEWUNIT = ind、...).... CLOSE(UNIT = ind)'を実行することもできます。 'OPEN(NEWUNIT = ind、...) 'を呼び出すと、未使用のユニット番号にファイルが接続され、' ind'に後者のファイルが返されます。 Fortranランタイムがスレッドセーフでない場合は、 'OPEN'ステートメントと' CLOSE'ステートメントをクリティカルセクションで囲む必要があります。 –

答えて

0

問題は、あなたが選択したフォーマットです。次に、出力はすべてのスレッドでr>=10のすべての値に対して6つのアスタリスク******(コンパイラによって異なる)になります。 sについても同様です。

私は、これらの値の範囲を制限/確認するか、より多くの数字を守るためにフォーマットを拡張することをお勧めします。


@francescalusに述べたように、別の可能性は、IIrsが同一であるJJの組み合わせをヒットします。 r=sから

r=(II-1)*dr 
s=s0+JJ*ds 

は定数s0=0.450D0, dr=1.0D-4, ds=1.0D-2利回り

を使用して

(II-1)*dr = s0+JJ*ds 

または

II = 1 + s0/dr + JJ*ds/dr 

に従います - ちょうどそれの楽しみのため

のは数学をやらせます0

II = 4501 + JJ*10 

したがって、一度に2つ(またはそれ以上)のスレッドでこの組み合わせがtrueになると、問題が発生します。

この場合の簡単な解決方法:スレッド番号をファイル名に追加します。

+0

@francescalusとAlexanderありがとうございました。両方のあなたが正しく指摘したように、FORMATは問題です。 –