1

私は、大部分が1を保持する21x21の行列を持っています。特定の要素は、個別の数値で初期化する必要があります。既存のソリューションは 2 段階の初期化です。最初にすべての要素を 1 に設定し、次に選択した要素を個別の数値に再割り当てします。

これは従来の FORTRAN77 コードで実装されています。以下を参照してください。また、gfortran-4.9で適切にコンパイルされます(警告なしでも)。

ただし、 gfortran-4.4を実行している古いサーバーでコンパイルする必要があります。f2cg95コンパイラなどの代替ツールを使用すると、「初期化の重複」が原因で失敗します。

では、特殊な BLOCK DATA プログラム単位でこのオーバーラップを回避するという問題をどのように再コーディングできますか? また、インテル Fortran コンパイラでは可能ですが、初期化の順序が保証されないため、お勧めできません。

      SUBROUTINE TEST 
      REAL*8 MAT(21,21)
      COMMON /PARAMETERS/ MAT
      END

      BLOCK DATA 
      REAL*8 MAT(21,21)
      COMMON /PARAMETERS/ MAT
      DATA MAT/441*1/
      DATA (MAT(1,J),J=2,19)/
     &     0.971440D0, 0.940444D0, 1, 0.994435D0, 0.708218D0,
     &     0.931484D0, 1.170520D0, 0.990124D0, 1, 1.019530D0,
     &     0.989844D0, 1.002350D0, 0.999248D0, 1.107274D0, 0.880880D0,
     &     0.880973D0, 0.881047D0, 0.881141D0/
      DATA (MAT(2,J),J=3,14)/
     &     1.022740D0, 0.970120D0, 0.945939D0, 0.744954D0, 0.902271D0,
     &     1.084320D0, 1.005710D0, 1.021000D0, 0.944914D0, 0.973384D0,
     &     0.959340D0, 0.945520D0/
      DATA (MAT(3,J),J=4,19)/
     &     0.925053D0, 0.940237D0, 0.849408D0, 0.955052D0, 1.281790D0,
     &     1.5D0, 1, 0.904849D0, 0.897342D0, 0.724255D0,
     &     0.859744D0, 0.855134D0, 0.831229D0, 0.808310D0, 0.784323D0,
     &     0.745171D0/
      DATA (MAT(4,J),J=5,14)/1.022540D0, 0.493148D0, 0.944871D0,
     &     1.144440D0, 3*1, 1.013040D0, 1, 1.00532D0/
      DATA (MAT(5,J),J=8,12)/1.034787D0, 3*1, 1.0049D0/
      DATA (MAT(7,J),J=15,19)/1.008492D0, 1.010124D0, 1.011501D0,
     &     1.012821D0, 1.014089D0/
      DATA (MAT(8,J),J=9,12)/1.1D0, 1, 1.3D0, 1.3D0/
      END
4

2 に答える 2

2

「重複する初期化」が許可されていない場合、単純なアプローチはn*1、特定のデータの前後に挿入し、残りの部分を 1 で埋めることです。たとえば、

      BLOCK DATA 
      REAL*8 MAT(21,21)
      COMMON /PARAMETERS/ MAT
      DATA MAT(1,:) / 1,
     &     0.971440D0, 0.940444D0, 1, 0.994435D0, 0.708218D0,
     &     0.931484D0, 1.170520D0, 0.990124D0, 1, 1.019530D0,
     &     0.989844D0, 1.002350D0, 0.999248D0, 1.107274D0, 0.880880D0,
     &     0.880973D0, 0.881047D0, 0.881141D0, 2*1 /
      DATA MAT(2,:) / 2*1,
     &     1.022740D0, 0.970120D0, 0.945939D0, 0.744954D0, 0.902271D0,
     &     1.084320D0, 1.005710D0, 1.021000D0, 0.944914D0, 0.973384D0,
     &     0.959340D0, 0.945520D0, 7*1 /
      DATA MAT(3,:) / 3*1,
     &     0.925053D0, 0.940237D0, 0.849408D0, 0.955052D0, 1.281790D0,
     &     1.5D0, 1, 0.904849D0, 0.897342D0, 0.724255D0,
     &     0.859744D0, 0.855134D0, 0.831229D0, 0.808310D0, 0.784323D0,
     &     0.745171D0, 2*1 /
      DATA MAT(4,:) / 4*1,
     &     1.022540D0, 0.493148D0, 0.944871D0,
     &     1.144440D0, 3*1, 1.013040D0, 1, 1.00532D0, 7*1 /
      DATA MAT(5,:) / 7*1, 1.034787D0, 3*1, 1.0049D0, 9*1 /
      DATA MAT(6,:) / 21*1 /
      DATA MAT(7,:) / 14*1,
     &     1.008492D0, 1.010124D0, 1.011501D0,
     &     1.012821D0, 1.014089D0, 2*1 /
      DATA MAT(8,:) / 8*1, 1.1D0, 1, 1.3D0, 1.3D0, 9*1 /
      DATA MAT(9:21,:) / 273*1 /
      END

コメントで提案されているように、別のアプローチは、すべての DATA ステートメントを配列の割り当てに置き換えることです。たとえば、

      SUBROUTINE init_data
      IMPLICIT NONE
      REAL*8 MAT(21,21), ONE
      COMMON /PARAMETERS/ MAT
      PARAMETER ( ONE = 1.0D0 )
      INTEGER i

      MAT(:,:) = ONE

      MAT(1, 2:19) = [
     &     0.971440D0, 0.940444D0, ONE,        0.994435D0, 0.708218D0,
     &     0.931484D0, 1.170520D0, 0.990124D0, ONE,        1.019530D0,
     &     0.989844D0, 1.002350D0, 0.999248D0, 1.107274D0, 0.880880D0,
     &     0.880973D0, 0.881047D0, 0.881141D0 ]
      MAT(2, 3:14) = [
     &     1.022740D0, 0.970120D0, 0.945939D0, 0.744954D0, 0.902271D0,
     &     1.084320D0, 1.005710D0, 1.021000D0, 0.944914D0, 0.973384D0,
     &     0.959340D0, 0.945520D0 ]
      MAT(3, 4:19) = [
     &     0.925053D0, 0.940237D0, 0.849408D0, 0.955052D0, 1.281790D0,
     &     1.5D0,      ONE,        0.904849D0, 0.897342D0, 0.724255D0,
     &     0.859744D0, 0.855134D0, 0.831229D0, 0.808310D0, 0.784323D0,
     &     0.745171D0 ]
      MAT(4, 5:14) = [ 1.022540D0, 0.493148D0, 0.944871D0,
     &     1.144440D0, (ONE,i=1,3), 1.013040D0, ONE, 1.00532D0 ]
      MAT(5, 8:12) = [ 1.034787D0, (ONE,i=1,3), 1.0049D0 ]
      MAT(7, 15:19) = [ 1.008492D0, 1.010124D0, 1.011501D0,
     &                  1.012821D0, 1.014089D0 ]
      MAT(8, 9:12) = [ 1.1D0, ONE, 1.3D0, 1.3D0 ]
      END

これは私にはややすっきりしているように見えます。このコードが gfortran 4.4.7 で動作することは確認しています(/.../)[...](/ 1.0d0, 2.0d0, ... /). また、2 番目のアプローチでは、プログラムの実行時にデータが自動的に初期化されるのinit_dataとは対照的に、プログラムのある時点で呼び出す必要があることに注意してください。BLOCK DATA

于 2015-12-03T20:53:23.577 に答える