9.3 配列の一部分だけを描く

配列の一部分だけを作画するにはどうしたらよいのでしょう? これまでと同じ データで, その一部分だけを描くことを考えてみましょう(u2d4).

経度80$^{\circ}$から320$^{\circ}$, 緯度 -60$^{\circ}$から60$^{\circ}$の 部分だけを描くことにします. 6行めのパラメータ文で与えているように, 格 子点の範囲はx方向に9 ≦ i ≦ 33, y方向に7 ≦ j ≦ 31  となります. ウインドウの設定をこの範囲とし, 36行めのudcntr ルーチ ンで等高線図を描くのですが, ここで一工夫が必要です. 最初の引数としては, この矩形領域の左下に対応する配列要素 P(KXMN,KYMN) を陽に与え, 2 番めには実際に宣言した配列の第1次元寸法 nx, 3, 4番めには実際の作 画に使う配列の第1次元および第2次元寸法 (KXMX-KXMN+1,KYMX-KYMN+1) を与えることによって配列の一部分だけを作画することができます.

この辺の事情を正しく理解するためには, FORTRAN において, 2次元の配列要 素が記憶領域上でどのように順序づけられ, メソッド(元サブルーチン)の引数にある配列が どのように扱われているかを知る必要があります. FORTRAN マニュアルなどを 参照してください.

# u2d4.rb


require "narray"
require "numru/dcl"
include NumRu
include Math


nx = 37
ny = 37
xmin = 0
xmax = 360
ymin = -90
ymax = 90
drad = PI / 180
kxmn = 9
kxmx = 33
kymn = 7
kymx = 31

p = NArray.sfloat(nx, ny)
alon = NArray.sfloat(nx)
alat = NArray.sfloat(ny)

#-- data ---
for i in 0..nx-1
  alon[i] = xmin + (xmax-xmin)*i/(nx-1).to_f
end
for j in 0..ny-1
  alat[j] = ymin + (ymax-ymin)*j/(ny-1).to_f
end

for j in 0..ny-1
  slat = sin(alat[j]*drad)
  for i in 0..nx-1
    p[i,j] = 3*sqrt(1-slat**2)*slat*cos(alon[i]*drad) - 0.5*(3*slat**2-1)
  end
end

#-- graph ---
iws = (ARGV[0] || (puts ' WORKSTATION ID (I)  ? ;'; DCL::sgpwsn; gets)).to_i
DCL::gropn iws

DCL::grfrm

DCL::grswnd(alon[kxmn-1], alon[kxmx-1], alat[kymn-1], alat[kymx-1])
DCL::grsvpt(0.2, 0.8, 0.2, 0.8)
DCL::grstrn(1)
DCL::grstrf

DCL::usdaxs
DCL::udcntr(p[(kxmn-1)..(kxmx-1), (kymn-1)..(kymx-1)])

DCL::grcls

program u2d4

\resizebox{10cm}{!}{\includegraphics{u2d1/u2d4.eps}}
u2d4.rb: frame1
 

 

FORTRANのひけつ 2

多次元配列の記憶順序

FORTRAN77では多次元(7次元まで)の配列を定義できますが,実際の記憶装置が多次元構造を持っているわけではなくて,1次元的に管理されています.多次元配列を1次元的に展開する順序は,FORTRAN77の規格で定めてありますから,多次元配列を1次元配列と結合することが可能です.

例えば

REAL X(6), Y(2,3)
COMPLEX Z(3)
EQUIVALENCE (X,Y,Z)

という場合,変数 x, y, z はどれも長さが6語の配列で, EQUIVALENCE文により同じ記憶領域を占めます.この時, それぞれの変数の並び方は

 

+----------+----------+----------+----------+----------+----------+
| X(1)     | X(2)     | X(3)     | X(4)     | X(5)     | X(6)     |
|----------|----------|----------|----------|----------|----------|
| Y(1,1)   | Y(2,1)   | Y(1,2)   | Y(2,2)   | Y(1,3)   | Y(2,3)   |
|----------|----------|----------|----------|----------|----------|
| Re(Z(1)) | Im(Z(1)) | Re(Z(2)) | Im(Z(2)) | Re(Z(3)) | Im(Z(3)) |
+----------+----------+----------+----------+----------+----------+

 

という様に,2次元配列 y は添字の左側の数字から変るように1次元的に展開されます.また,複素数データ z は2つの実数が並んだ形で展開されます.したがって,X(3) の数値は,Y(1,2), Re(Z(2)) と同じになります.

この規則は多くのプログラムで積極的に使われており,多次元配列を1次元配列として扱ったり,複素数データを実数データと見なして処理したりすることが行われています.この規則は,計算機のハードウェアに近い部分の規則なので,計算機によって異なるように思えるかもしれませんが,FORTRAN77規格で定められた「標準語」です.例えば,「岩波FORTRAN辞典」(西村恕彦/酒井俊夫・高田正之 著)の「記憶列の結合」を御覧下さい.