2016-08-31 24 views
0

Fortranでブロック三重対角行列を作成しようとしています。今度はA_matrixのメイン対角線に配置された行列だけを扱うこのコードを用意しました。これはすべてのステップの1つの新しい行列iです。ブロック三角対角行列の作成

do i = gs+1, total_mesh_points 

    start_line = (3*i)-2 
    start_colu = (3*i)-2 
    final_line = (3*i) 
    final_colu = (3*i) 

    do ii = 1, 3 
    do jj = 1, 3 
     A_matrix(start_line:final_line,start_colu:final_colu) = & 
      impflux(ii,jj) 
    end do 
    end do 

end do 

ここに私のA_matrix(i,j)は、その主対角線に別の3×3行列(impflux)を受け取ります大行列です。 iの各ステップでは、新しいimpflux行列をA_matrixのメイン対角線に配置する必要があることに注意してください。

私はこの問題のより簡単な解決策は考えられません。人々が通常Fortranで対角行列をブロックする方法

+0

このコードはあまり意味がありません。 'ii'と' jj 'で索引付けされたループの中で、 'a_matrix'の同じ要素を最初に' impflux(1,1) '、' impflux(1,2) '、* etc *と繰り返して更新します。あなたが作成しようとしているものの小さな例を私たちに示したなら、私はおそらくよく理解できるでしょう。 –

+0

お返事ありがとうございます。私は偏微分方程式の暗黙の方法を扱っています。これらの方法では、メッシュ内の各点に対して3つの行列(3x3)を作成する必要があります。コードの最初のループはメッシュ内のすべての点を通過します。残りのコードは、A_matrix内の行列impflux(メッシュ内の各点に対して生成された)の正しい配置を処理します。最終的な結果は、A_matrixの主対角線の内側に一連のimpflux行列があることです。 –

+0

理想的な世界は、関数に3つのベクトルa(i、j、nm)、b(i、j、nm)とc(i、j、nm)を渡して、 3つの主対角線を形成するこれらの3つの行列(a、b、c)を有する行列(C)である。 –

答えて

3

ブロック三重対角行列を作成する方法の1つです。いくつかのよく知られている図書館の外に、通常の方法であるがあることはわかりません。これはプログラムですが、関数に変換するためにあなたに任せておきます。

PROGRAM test 

    USE iso_fortran_env 

    IMPLICIT NONE 

    INTEGER :: k ! submatrix size 
    INTEGER :: n ! number of submatrices along main diagonal 
    INTEGER :: ix ! loop index 

    ! the submatrices, a (lower diagonal) b (main diagonal) c (upper diagonal) 
    REAL(real64), DIMENSION(:,:,:), ALLOCATABLE :: amx, bmx, cmx 

    ! the block tridiagonal matrix 
    REAL(real64), DIMENSION(:,:), ALLOCATABLE :: mat_a 

    k = 3 ! set these values as you wish 
    n = 4 

    ALLOCATE(amx(n-1,k,k), bmx(n,k,k), cmx(n-1,k,k)) 
    ALLOCATE(mat_a(n*k,n*k)) 

    mat_a = 0.0 

    ! populate these as you wish 
    amx = 1.0 
    bmx = 2.0 
    cmx = 3.0 

    ! first the lower diagonal 
    DO ix = 1,k*(n-1),k 
    mat_a(ix+k:ix+2*k-1,ix:ix+k-1) = amx(CEILING(REAL(ix)/REAL(k)),:,:) 
    END DO 

    ! now the main diagonal 
    DO ix = 1,k*n,k 
    mat_a(ix:ix+k-1,ix:ix+k-1) = bmx(CEILING(REAL(ix)/REAL(k)),:,:) 
    END DO 

    ! finally the upper diagonal 
    DO ix = 1,k*(n-1),k 
    mat_a(ix:ix+k-1,ix+k:ix+2*k-1) = cmx(CEILING(REAL(ix)/REAL(k)),:,:) 
    END DO 

END PROGRAM test 

ここでエラーをチェックすることは一切ありません。私はいくつかのテストを行いました。

1つの明白な選択肢は、同じ繰り返しでamxbmxcmxを挿入し、一度だけmat_aの行をループになりますが、これは、最初と最後の反復のための特別な処理を必要とし、おそらく多くのより複雑になります。パフォーマンスに関しては、いくつかのテストを実行することが重要な場合。

これは密度の高いマトリックスを生成することにも注意してください。行列が非常に大きくなると、対角要素だけを格納するアプローチがより役に立ちます。それは、派生した型と操作に向けて私たちを連れて行きます。それはまったく別の質問です。

+0

あなたの返信のためのハイパフォーマンスマークありがとうございました。私はあなたのプログラムに取り組んでいます! –

関連する問題