配列上で要素ごとに操作する
-
27-10-2019 - |
質問
Fortranの範囲外の要素にアクセスして、配列がナンセンスを返しているかどうかを確認しようとしています。そして、私はこれらの値が1未満であることを確認したいと思います、そして、もしそうなら、それらを1に変更してください。
これは私のコードの一部であり、問題を引き起こしています:
lastNeighLabel=(/clusterLabel(jj-1,kk,ll), clusterLabel(jj,kk-1,ll), clusterLabel(jj,kk,ll-1)/)
LastNeighLabelには、それぞれx、y、z方向の最後の隣人のクラスターラベル(1とnの間、nは見つかった一意の別々のクラスターの総数)が含まれています。
とき jj
または kk
または ll
は1であり、配列内の0番目の要素にアクセスしようとします。 FORTRAN
配列の1から数えて、宇宙を破壊しようとします。私は現在、すべての不測の事態のためにコーディングしようとしている約8if/elseifステートメントのもつれた混乱に陥っています。しかし、私は各要素を操作する方法があることを望んでいました。だから基本的に私は言いたいのですが where((/jj-1,kk-1,ll-1/).lt.1) do clusterLabel(jj-1,kk,ll)=0 etc
どの要素が問題を引き起こしているかに応じて。
しかし、whereは渡された変数のみを操作し、同じインデックスの異なる配列を操作しないため、それを行う方法を考えることはできません。それとも私は間違っていますか?
これが意味をなさない場合は喜んで編集します。
解決
多分あなたは関数を使うことができますか?
real function f(A,i,j,k)
real :: A(:,:,:)
integer :: i,j,k
if (i==0.or.j==0.or.k==0) then
f=0
else
f=A(i,j,k)
endif
end function f
そして、f(clusterLabel、jj-1、kk、ll)などを使用します。
他のヒント
Fortranが1つから始まる配列にアクセスすることは必須ではありません。任意の開始値が許可されます。インデックス付きのゼロ配列を使用する方が便利な場合は、配列を次のように宣言します:
real, dimension (0:N-1, 0:M-1) :: array
または
real, dimension (0:N, 0:M) :: array
そして、特別なケースをキャッチするために0のインデックスを余分にしてください。
ゼロインデックス値が合法であるため、これは問題の別の解決策になる可能性があります。
これにアプローチするもう1つの可能な方法は、拡張クラスターラベル配列(インデックス境界が0から始まる)を作成することです。これは、外側にゼロのレイヤーがタックされたクラスターラベル配列と等しくなります。その後、jj、kk、およびllのすべての値に対してループを安全に実行させることができます。これが実行可能な解決策であるかどうかは、配列のサイズに依存します。
integer :: extended_cluster_label(0:size(cluster_label,1), & 0:size(cluster_label,2), & 0:size(cluster_label,3) & ) extended_cluster_label(0,:,:) = 0 extended_cluster_label(:,0,:) = 0 extended_cluster_label(:,:,0) = 0 extended_cluster_label(1:, 1:, 1:) = cluster_label