gtool5 Fortran 90/95 ライブラリ 1.0.0-rc5
English
Loading...
Searching...
No Matches
Functions/Subroutines
gtvarlimit.f90 File Reference

入出力範囲の拘束 More...

Go to the source code of this file.

Functions/Subroutines

subroutine gtvarlimit_iiii (var, dimord, start, count, stride, err)
 
subroutine gtvarlimit (var, string, err)
 
subroutine limit_one (string)
 

Detailed Description

入出力範囲の拘束

Author
Eizi TOYODA, Yasuhiro MORIKAWA

Definition in file gtvarlimit.f90.

Function/Subroutine Documentation

◆ gtvarlimit()

subroutine gtvarlimit ( type(gt_variable), intent(inout)  var,
character(len = *), intent(in)  string,
logical, intent(out), optional  err 
)

入出力範囲の拘束 (文字列で指定)

変数 var 次元の入出力範囲を拘束します。 string にコンマ記法の範囲指定表現を用います:

<dim>=<lower>
<dim>=<lower>:<upper>
<dim>=<lower>:<upper>:<stride>

ここで <dim> は次元番号または次元名であり、 <lower>, <upper> は座標値または "^" を前置した格子番号です。 <stride> は格子数です。

エラーが生じた場合、メッセージを出力してプログラムは強制終了します。 err を与えてある場合にはの引数に .true. が返り、プログラムは終了しません。

Parameters
[in,out]var変数ハンドル
[in]string範囲指定文字列
[out]errエラーフラグ (省略可能)

Definition at line 213 of file gtvarlimit.f90.

214 use gtdata_types, only: gt_variable
215 use dc_trace, only: beginsub, endsub
216 use dc_url, only: gt_comma
218 type(GT_VARIABLE), intent(inout):: var
219 character(len = *), intent(in) :: string
220 logical, intent(out), optional :: err
221 integer:: is, ie
222continue
223 call beginsub('GTVarLimit', 'var=%d lim=<%c>', i=(/var%mapid/), c1=trim(string))
224 call gtvar_dump(var)
225 ! コンマで区切って解釈
226 is = 1
227 do
228 ie = index(string(is: ), gt_comma)
229 if (ie == 0) exit
230 call limit_one(string(is: is+ie-2))
231 is = is + ie
232 if (is > len(string)) exit
233 enddo
234 call limit_one(string(is: ))
235 if (present(err)) err = .false.
236 call endsub('GTVarLimit')
237 return
238contains
239
240 subroutine limit_one(string)
241 use dc_url, only: gt_equal
242 use dc_string, only: strieq, stoi
245 character(len = *), intent(in):: string
246 integer:: equal, dimord
247 integer:: start, count, stride, strhead
248 logical:: myerr
249
250 if (string == '') return
251
252 strhead = 4
253 if (len(string) < 4) strhead = len(string)
254
255 if (strieq(string(1:strhead), "IGN:")) then
256 ! 隠蔽型指定子 ign:<dim> または ign:<dim>=<start>
257 equal = index(string, gt_equal)
258 if (equal == 0) then
259 start = 1
260 else
261 start = stoi(string(equal+1: ), default=1)
262 endif
263 dimord = dimname_to_dimord(var, string(5: equal-1))
264 call limit(var, dimord, start, 1, 1, err)
265 call del_dim(var, dimord, myerr)
266 return
267 endif
268
269 ! 限定型指定子 <dim>=<start>:<finish>:<stride>
270 ! いまは実装がバグっていて <start>:<count>:<stride> になってる
271 !
272 equal = index(string, gt_equal)
273 if (equal == 0) return
274 dimord = dimname_to_dimord(var, string(1: equal-1))
275 if (dimord <= 0) return
276 !
277 call region_spec(dimord, string(equal+1: ), start, count, stride)
278 call limit(var, dimord, start, count, stride, err)
279 end subroutine limit_one
280
281 !
282 ! 範囲指定の = のあとを : で区切ってマップにいれる
283 !
284 subroutine region_spec(dimord, string, start, count, stride)
285 use dc_types, only: token
286 use dc_string, only: index_ofs, stoi
287 use dc_url, only: gt_circumflex, gt_colon
289 integer, intent(in):: dimord
290 integer, intent(out):: start, count, stride
291 character(len = *), intent(in):: string
292 integer:: colon, prev_colon, finish, dimlo, dimhi
293 character(len = token):: val(3)
294 continue
295 colon = index(string, gt_colon)
296 if (colon == 0) then
297 ! コロンがない場合は上下端に同じ値
298 val(1) = string(1: )
299 val(2) = val(1)
300 val(3) = ""
301 else
302 val(1) = string(1: colon - 1)
303 prev_colon = colon
304 colon = index_ofs(string, colon + 1, gt_colon)
305 if (colon > 0) then
306 val(2) = string(prev_colon + 1: colon - 1)
307 val(3) = string(colon + 1: )
308 else
309 val(2) = string(prev_colon + 1: )
310 val(3) = ""
311 endif
312 endif
313 if (val(3) == "") val(3) = "^1"
314
315 if (val(1)(1:1) == gt_circumflex) then
316 start = stoi(val(1)(2: ))
317 else if (val(1) == val(2)) then
318 start = nint(value_to_index(dimord, val(1)))
319 else
320 start = floor(value_to_index(dimord, val(1)))
321 endif
322 if (val(2) == val(1)) then
323 finish = start
324 else if (val(2)(1:1) == gt_circumflex) then
325 finish = stoi(val(2)(2: ))
326 else
327 finish = ceiling(value_to_index(dimord, val(2)))
328 endif
329
330 call dimrange(var, dimord, dimlo, dimhi)
331 start = min(max(dimlo, start), dimhi)
332 finish = min(max(dimlo, finish), dimhi)
333 count = abs(finish - start) + 1
334
335 if (val(3)(1:1) == gt_circumflex) then
336 stride = stoi(val(3)(2: ))
337 else
338 stride = stoi(val(3))
339 endif
340 stride = sign(stride, finish - start)
341 end subroutine region_spec
342
343 real function value_to_index(dimord, value) result(result)
344 !
345 ! GTVarLimit の引数 *var* に格納される変数の次元 *dimord*
346 ! に格納されるデータのうち, *value* が格納される
347 ! 格子番号を整数値にして返します.
348 !
349 ! 例えば次元に以下のデータが格納されているとします.
350 !
351 ! 0.05 0.1 0.15 0.20 0.25 0.30
352 !
353 ! この場合, *value* に 0.15 が与えられれば戻り値は 3. となります.
354 ! また *value* に 0.225 が与えられれば戻り値は 4.5 となります.
355 !
356 !
357 use gtdata_types, only: gt_variable
358 use gtdata_generic, only: get, open, close, inquire
359 use dc_string, only: stod
360 use dc_types, only: sp_eps
362 integer, intent(in):: dimord
363 character(len = *), intent(in):: value
364 type(GT_VARIABLE):: axisvar
365 real, allocatable:: axisval(:)
366 real:: val
367 integer:: i, n
368 logical:: myerr
369 continue
370
371 call beginsub('value_to_index', 'var=%d dimord=%d value=%c', &
372 & i=(/var%mapid, dimord/), c1=trim(value))
373
374 call open(axisvar, var, dimord, count_compact=.true., &
375 & inherit_slice=.false., err=myerr)
376 if (myerr) then
377 result = -1.0
378 return
379 endif
380 call inquire(axisvar, allcount=n)
381 allocate(axisval(n))
382 call get(axisvar, axisval, n, err=myerr)
383 call close(axisvar)
384 if (myerr) then
385 result = -1.0
386 return
387 else if (size(axisval) < 2) then
388 result = 1.0
389 goto 900
390 endif
391
392 val = real(stod(value), kind=kind(axisval))
393
394 ! call DbgMessage('value=%f axis=(/%*r/)', r=(/val, axisval(:)/), &
395 ! & n=(/size(axisval)/))
396
397 do, i = 1, size(axisval) - 1
398 if (abs(axisval(i + 1) - axisval(i)) <= sp_eps) then
399 result = real(i) + 0.5
400 goto 900
401 endif
402 result = i + (val - axisval(i)) / (axisval(i + 1) - axisval(i))
403 if (result <= (i + 1)) goto 900
404 enddo
405
406900 continue
407 call endsub('value_to_index', '(%c) = %r', &
408 & c1=trim(value), r=(/result/))
409 if (allocated(axisval)) then
410 deallocate(axisval)
411 endif
412 end function value_to_index
413
subroutine limit_one(string)
文字型変数の操作
Definition dc_string.f90:83
デバッグ時の追跡用モジュール
Definition dc_trace.f90:150
subroutine, public dbgmessage(fmt, i, r, d, l, n, c1, c2, c3, ca)
Definition dc_trace.f90:680
subroutine, public beginsub(name, fmt, i, r, d, l, n, c1, c2, c3, ca, version)
Definition dc_trace.f90:476
subroutine, public endsub(name, fmt, i, r, d, l, n, c1, c2, c3, ca)
Definition dc_trace.f90:599
種別型パラメタを提供します。
Definition dc_types.f90:55
real(sp), parameter, public sp_eps
単精度実数型変数のマシンイプシロン.
Definition dc_types.f90:87
integer, parameter, public token
単語やキーワードを保持する文字型変数の種別型パラメタ
Definition dc_types.f90:128
変数 URL の文字列解析
Definition dc_url.f90:61
character, parameter, public gt_comma
Definition dc_url.f90:102
character, parameter, public gt_equal
Definition dc_url.f90:104
character, parameter, public gt_colon
Definition dc_url.f90:100
character, parameter, public gt_circumflex
Definition dc_url.f90:106

References dc_trace::beginsub(), dc_trace::endsub(), dc_url::gt_comma, gtdata_internal_map::gtvar_dump(), and limit_one().

Here is the call graph for this function:

◆ gtvarlimit_iiii()

subroutine gtvarlimit_iiii ( type(gt_variable), intent(inout)  var,
integer, intent(in)  dimord,
integer, intent(in), optional  start,
integer, intent(in), optional  count,
integer, intent(in), optional  stride,
logical, intent(out), optional  err 
)

入出力範囲の拘束 (数値で指定)

変数 var 次元の入出力範囲を拘束します。 Limit を呼び出した後では Slice でその範囲の外に入出力範囲を 設定できなくなります。これにより、変数全体ではなく一部を Slice_Next サブルーチンを用いて走査できるようになります。

指定方法は、変数 var の dimord 番目の次元を基点 start, 格子総数 count, 間隔 stride に限定します。

エラーが生じた場合、メッセージを出力してプログラムは強制終了します。 err を与えてある場合にはの引数に .true. が返り、プログラムは終了しません。

Limit は 2 つのサブルーチンの総称名であり、 コンマ記法を用いて指定することも可能です。

Parameters
[in,out]var変数ハンドル
[in]dimord次元順序番号
[in]start開始インデックス (省略可能)
[in]count格子総数 (省略可能)
[in]stride間隔 (省略可能)
[out]errエラーフラグ (省略可能)

Definition at line 71 of file gtvarlimit.f90.

72 use gtdata_types, only: gt_variable
74 use dc_error, only: nf90_einval, storeerror
76 implicit none
77 type(GT_VARIABLE), intent(inout):: var
78 integer, intent(in) :: dimord
79 integer, intent(in) , optional :: start, count, stride
80 logical, intent(out), optional :: err
81 type(gt_dimmap), allocatable:: map(:)
82 integer:: iolo, iohi, uilo, uihi, lowerlim, upperlim, dimlo, dimhi
83 integer:: ndims, stat
84
85 stat = nf90_einval
86 call beginsub('GTVarLimit_iiii', &
87 & 'var%d-dim%d start=%d count=%d stride=%d', &
88 & i=(/var%mapid, dimord, start, count, stride/))
89 ! エラーチェック
90 if (dimord < 1) then
91 print *, "dimord =", dimord, " < 1"
92 goto 999
93 endif
94 if (stride == 0) then
95 print *, "stride == 0"
96 goto 999
97 endif
98 call map_lookup(var, ndims=ndims)
99 if (ndims <= 0) then
100 print *, "ndims =", ndims, " <= 0"
101 goto 999
102 endif
103 if (dimord > ndims) then
104 print *, "dimrod =", dimord, " > ndims =", ndims
105 goto 999
106 endif
107 if (allocated(map)) then
108 deallocate(map)
109 end if
110 allocate(map(ndims))
111 call map_lookup(var, map=map)
112 ! (/lowerlim, upperlim/) は内部格子の範囲 (降順可)
113 lowerlim = min(start, start + (count - 1) * stride)
114 upperlim = max(start, start + (count - 1) * stride)
115 call dimrange(var, dimord, dimlo, dimhi)
116 if (lowerlim < dimlo) then
117 print *, "lowerlim = ", lowerlim, " < dimlo =", dimlo
118 goto 999
119 endif
120 if (upperlim > dimhi) then
121 print *, "upperlim = ", upperlim, " < dimhi =", dimhi
122 goto 999
123 endif
124
125 call dbgmessage('@ lowerlim=%d upperlim=%d', i=(/lowerlim, upperlim/))
126
127 ! 入出力範囲を内部格子番号に変えておく
128 uilo = map(dimord)%start
129 iolo = 1 + map(dimord)%step * (uilo - 1) + map(dimord)%offset
130 uihi = map(dimord)%start + (map(dimord)%count - 1) * map(dimord)%stride
131 iohi = 1 + map(dimord)%step * (uihi - 1) + map(dimord)%offset
132
133 call dbgmessage('@ userindex=%d %d, internal=%d %d', &
134 & i=(/uilo, uihi, iolo, iohi/))
135 call dbgmessage('@ DbgMessage offset %d -> %d step=%d', &
136 & i=(/map(dimord)%offset, (start-1), stride/))
137
138 ! 制限を課す。offset が変わればユーザ格子番号の意味が変わる
139 map(dimord)%offset = start - 1
140 map(dimord)%allcount = count
141 map(dimord)%step = stride
142
143 ! 入出力範囲を内部格子番号からユーザ格子番号に戻す
144 uilo = 1 + (iolo - 1 - map(dimord)%offset) / map(dimord)%step
145 uihi = 1 + (iohi - 1 - map(dimord)%offset) / map(dimord)%step
146 call dbgmessage('@ userindex=%d %d', i=(/uilo, uihi/))
147
148 ! それぞれは制限 [1 .. allcount] の中になければならない
149 uilo = max(1, min(map(dimord)%allcount, uilo))
150 uihi = max(1, min(map(dimord)%allcount, uihi))
151
152 call dbgmessage('@ userindex=%d %d orig_stride=%d', &
153 & i=(/uilo, uihi, map(dimord)%stride/))
154
155 ! 元のストライドの符号は無視し、正に固定する
156 map(dimord)%stride = max(1, abs(map(dimord)%stride))
157 map(dimord)%start = min(uilo, uihi)
158 map(dimord)%count = 1 + abs(uihi - uilo) / map(dimord)%stride
159
160 call map_set(var, map, stat)
161 if (stat /= 0) call dbgmessage("map_set fail")
162
163999 continue
164 call storeerror(stat, 'GTVarLimit_iiii', err)
165 call endsub('GTVarLimit_iiii')
エラー処理用モジュール
Definition dc_error.f90:454
subroutine, public storeerror(number, where, err, cause_c, cause_i)
Definition dc_error.f90:891
subroutine, public map_lookup(var, vid, map, ndims)
subroutine map_set(var, map, stat)

References dc_trace::beginsub(), dc_trace::dbgmessage(), dc_trace::endsub(), gtdata_internal_map::map_lookup(), gtdata_internal_map::map_set(), and dc_error::storeerror().

Here is the call graph for this function:

◆ limit_one()

subroutine gtvarlimit::limit_one ( character(len = *), intent(in)  string)

Definition at line 240 of file gtvarlimit.f90.

241 use dc_url, only: gt_equal
242 use dc_string, only: strieq, stoi
245 character(len = *), intent(in):: string
246 integer:: equal, dimord
247 integer:: start, count, stride, strhead
248 logical:: myerr
249
250 if (string == '') return
251
252 strhead = 4
253 if (len(string) < 4) strhead = len(string)
254
255 if (strieq(string(1:strhead), "IGN:")) then
256 ! 隠蔽型指定子 ign:<dim> または ign:<dim>=<start>
257 equal = index(string, gt_equal)
258 if (equal == 0) then
259 start = 1
260 else
261 start = stoi(string(equal+1: ), default=1)
262 endif
263 dimord = dimname_to_dimord(var, string(5: equal-1))
264 call limit(var, dimord, start, 1, 1, err)
265 call del_dim(var, dimord, myerr)
266 return
267 endif
268
269 ! 限定型指定子 <dim>=<start>:<finish>:<stride>
270 ! いまは実装がバグっていて <start>:<count>:<stride> になってる
271 !
272 equal = index(string, gt_equal)
273 if (equal == 0) return
274 dimord = dimname_to_dimord(var, string(1: equal-1))
275 if (dimord <= 0) return
276 !
277 call region_spec(dimord, string(equal+1: ), start, count, stride)
278 call limit(var, dimord, start, count, stride, err)

References dc_trace::beginsub(), dc_trace::dbgmessage(), dc_trace::endsub(), dc_url::gt_circumflex, dc_url::gt_colon, dc_url::gt_equal, dc_types::sp_eps, and dc_types::token.

Here is the call graph for this function: