gtool5 Fortran 90/95 Library 1.0.0-rc5
日本語
Loading...
Searching...
No Matches
gtvarlimit.f90
Go to the documentation of this file.
1!> @file gtvarlimit.f90
2!>
3!> @author Eizi TOYODA, Yasuhiro MORIKAWA
4!> @copyright Copyright (C) GFD Dennou Club, 2000-2026. All rights reserved. <br/>
5!> License is BSD-2-Clause. See [COPYRIGHT](@ref COPYRIGHT) in detail
6!>
7!> @en
8!> @brief Constrain I/O range
9!>
10!> These subroutines are provided as gtdata_generic#Limit
11!> through gtdata_generic.
12!> @enden
13!>
14!> @ja
15!> @brief 入出力範囲の拘束
16!>
17!> これらのサブルーチンは gtdata_generic から gtdata_generic#Limit
18!> として提供されます。
19!> @endja
20!>
21
22!>
23!> @en
24!> @brief Constrain I/O range (numeric specification)
25!>
26!> Constrains the I/O range of variable var dimensions.
27!> After calling Limit, Slice cannot set the I/O range outside
28!> the constrained range. This allows scanning a portion of
29!> the variable using Slice_Next.
30!>
31!> The specification limits the dimord-th dimension of var to
32!> start point start, total count count, and interval stride.
33!>
34!> If an error occurs, outputs a message and terminates.
35!> If err is provided, returns .true. and does not terminate.
36!>
37!> Limit is a generic name for 2 subroutines; string specification
38!> using comma notation is also available.
39!> @param[inout] var Variable handle
40!> @param[in] dimord Dimension order number
41!> @param[in] start Start index (optional)
42!> @param[in] count Total grid count (optional)
43!> @param[in] stride Interval (optional)
44!> @param[out] err Error flag (optional)
45!> @enden
46!>
47!> @ja
48!> @brief 入出力範囲の拘束 (数値で指定)
49!>
50!> 変数 var 次元の入出力範囲を拘束します。
51!> Limit を呼び出した後では Slice でその範囲の外に入出力範囲を
52!> 設定できなくなります。これにより、変数全体ではなく一部を
53!> Slice_Next サブルーチンを用いて走査できるようになります。
54!>
55!> 指定方法は、変数 var の dimord 番目の次元を基点 start,
56!> 格子総数 count, 間隔 stride に限定します。
57!>
58!> エラーが生じた場合、メッセージを出力してプログラムは強制終了します。
59!> err を与えてある場合にはの引数に .true. が返り、プログラムは終了しません。
60!>
61!> Limit は 2 つのサブルーチンの総称名であり、
62!> コンマ記法を用いて指定することも可能です。
63!> @param[inout] var 変数ハンドル
64!> @param[in] dimord 次元順序番号
65!> @param[in] start 開始インデックス (省略可能)
66!> @param[in] count 格子総数 (省略可能)
67!> @param[in] stride 間隔 (省略可能)
68!> @param[out] err エラーフラグ (省略可能)
69!> @endja
70!>
71subroutine gtvarlimit_iiii(var, dimord, start, count, stride, err)
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')
166end subroutine gtvarlimit_iiii
167
168!>
169!> @en
170!> @brief Constrain I/O range (string specification)
171!>
172!> Constrains the I/O range of variable var dimensions using
173!> range specification expressions in comma notation:
174!> @code
175!> <dim>=<lower>
176!> <dim>=<lower>:<upper>
177!> <dim>=<lower>:<upper>:<stride>
178!> @endcode
179!>
180!> Here, <dim> is a dimension number or name, <lower> and <upper>
181!> are coordinate values or grid numbers prefixed with "^",
182!> and <stride> is a grid count.
183!>
184!> If an error occurs, outputs a message and terminates.
185!> If err is provided, returns .true. and does not terminate.
186!> @param[inout] var Variable handle
187!> @param[in] string Range specification string
188!> @param[out] err Error flag (optional)
189!> @enden
190!>
191!> @ja
192!> @brief 入出力範囲の拘束 (文字列で指定)
193!>
194!> 変数 var 次元の入出力範囲を拘束します。
195!> string にコンマ記法の範囲指定表現を用います:
196!> @code
197!> <dim>=<lower>
198!> <dim>=<lower>:<upper>
199!> <dim>=<lower>:<upper>:<stride>
200!> @endcode
201!>
202!> ここで <dim> は次元番号または次元名であり、
203!> <lower>, <upper> は座標値または "^" を前置した格子番号です。
204!> <stride> は格子数です。
205!>
206!> エラーが生じた場合、メッセージを出力してプログラムは強制終了します。
207!> err を与えてある場合にはの引数に .true. が返り、プログラムは終了しません。
208!> @param[inout] var 変数ハンドル
209!> @param[in] string 範囲指定文字列
210!> @param[out] err エラーフラグ (省略可能)
211!> @endja
212!>
213subroutine gtvarlimit(var, string, err)
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
414end subroutine gtvarlimit
subroutine gtvarlimit(var, string, err)
subroutine limit_one(string)
subroutine gtvarlimit_iiii(var, dimord, start, count, stride, err)
Error handling module.
Definition dc_error.f90:454
subroutine, public storeerror(number, where, err, cause_c, cause_i)
Definition dc_error.f90:891
Handling character types.
Definition dc_string.f90:83
Debug tracing module.
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
Provides kind type parameter values.
Definition dc_types.f90:55
integer, parameter, public token
Character length for word, token
Definition dc_types.f90:128
real(sp), parameter, public sp_eps
Machine epsilon for single precision real number.
Definition dc_types.f90:87
Variable URL string parser.
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
subroutine, public map_lookup(var, vid, map, ndims)
subroutine map_set(var, map, stat)