gtool5 Fortran 90/95 ライブラリ 1.0.0-rc5
English
Loading...
Searching...
No Matches
gtvarslice.f90
Go to the documentation of this file.
1!> @file gtvarslice.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 Specification of I/O range
9!>
10!> These subroutines are provided as gtdata_generic#Slice
11!> through gtdata_generic.
12!> @enden
13!>
14!> @ja
15!> @brief 入出力範囲の指定
16!>
17!> これらのサブルーチンは gtdata_generic から gtdata_generic#Slice
18!> として提供されます。
19!> @endja
20
21!>
22!> @en
23!> @brief Specify I/O range numerically
24!>
25!> Specifies the I/O range of variable var.
26!>
27!> Sets the I/O range of the dimord-th dimension of variable var
28!> to count elements starting from start with stride interval.
29!> If start, count, or stride is omitted, 1 is assumed.
30!> There is no argument to return success/failure.
31!> If an unspecifiable range is given, the widest range containing
32!> the specified range is set.
33!>
34!> Slice is a generic name for multiple subroutines;
35!> other methods using strings or numbers are also available.
36!> @param[in] var Variable handle
37!> @param[in] dimord Dimension order number
38!> @param[in] start Start position (optional)
39!> @param[in] count Number of elements (optional)
40!> @param[in] stride Stride interval (optional)
41!> @enden
42!>
43!> @ja
44!> @brief 入出力範囲を数値で指定
45!>
46!> 変数 var の入出力範囲を指定します。
47!>
48!> 変数 var の dimord 番目の次元の入出力範囲を start から
49!> stride 個おきに count 個とします。start, count,
50!> stride のいずれを省略しても 1 が仮定されます。成功し
51!> たか否かを返す引数はありません。仮に指定できない範囲が指定され
52!> た場合には、指定範囲を含むなるべく広い範囲を設定します。
53!>
54!> Slice は複数のサブルーチンの総称名であり、
55!> 他にも文字列や番号で指定する方法があります。
56!> @param[in] var 変数ハンドル
57!> @param[in] dimord 次元順序番号
58!> @param[in] start 開始位置 (省略可能)
59!> @param[in] count 要素数 (省略可能)
60!> @param[in] stride 刻み幅 (省略可能)
61!> @endja
62!>
63subroutine gtvarslice(var, dimord, start, count, stride)
64 use gtdata_types, only: gt_variable
67 use dc_error, only: nf90_enotvar, storeerror
69 implicit none
70 type(gt_variable), intent(in):: var
71 integer, intent(in):: dimord
72 integer, intent(in), optional:: start
73 integer, intent(in), optional:: count
74 integer, intent(in), optional:: stride
75 type(gt_dimmap), allocatable:: map(:)
76 integer:: vid, maxindex, maxcount, nd, stat
77 logical:: growable_dimension
78continue
79 call beginsub('GTVarSlice', 'var%%mapid=%d dimord=%d', &
80 & i=(/var%mapid, dimord/))
81 call gtvar_dump(var)
82 call map_lookup(var, vid=vid, ndims=nd)
83 if (vid < 0) then
84 call storeerror(nf90_enotvar, "GTVarSlice")
85 endif
86
87 if (vid > 0) then
88 call query_growable(vid, growable_dimension)
89 else
90 growable_dimension = .false.
91 endif
92
93 if (nd == 0) goto 999
94 allocate(map(nd))
95 call map_lookup(var, map=map)
96
97 if (dimord <= 0 .or. dimord > size(map)) goto 998
98
99 call dbgmessage('map(dimord): originally start=%d count=%d stride=%d', &
100 & i=(/map(dimord)%start, map(dimord)%count, map(dimord)%stride/))
101 maxindex = map(dimord)%allcount
102 if (.not. growable_dimension) then
103 call dbgmessage('maxindex=%d', i=(/maxindex/))
104 endif
105
106 if (present(start)) then
107 if (start < 0) then
108 map(dimord)%start = max(1, maxindex + 1 + start)
109 else if (growable_dimension) then
110 map(dimord)%start = max(1, start)
111 else
112 map(dimord)%start = min(maxindex, max(1, start))
113 endif
114 call dbgmessage('start=%d (%d specified)', i=(/map(dimord)%start, start/))
115 endif
116
117 if (present(stride)) then
118 map(dimord)%stride = stride
119 if (stride == 0) map(dimord)%stride = 1
120 call dbgmessage('stride=%d (%d specified)', &
121 & i=(/map(dimord)%stride, stride/))
122 endif
123
124 if (present(count)) then
125 map(dimord)%count = abs(count)
126 if (count == 0) map(dimord)%count = 1
127 call dbgmessage('count=%d (%d specified)', &
128 & i=(/map(dimord)%count, count/))
129 if (growable_dimension) then
130 maxcount = map(dimord)%start + &
131 & (map(dimord)%count - 1) * abs(map(dimord)%stride)
132 map(dimord)%allcount = max(map(dimord)%allcount, maxcount)
133 call dbgmessage('allcount=%d ', i=(/map(dimord)%allcount/))
134 end if
135 endif
136
137 if (.not. growable_dimension) then
138 maxcount = 1 + (maxindex - map(dimord)%start) / map(dimord)%stride
139 map(dimord)%count = max(1, min(maxcount, map(dimord)%count))
140 call dbgmessage('count=%d ', i=(/map(dimord)%count/))
141 endif
142 call map_set(var, map, stat)
143 if (stat /= 0) goto 998
144
145 call endsub('GTVarSlice')
146 deallocate(map)
147 return
148
149998 continue
150 deallocate(map)
151999 continue
152 call endsub('GTVarSlice', 'err skipped')
153end subroutine gtvarslice
154
155!>
156!> @en
157!> @brief Specify I/O range by string
158!>
159!> Specifies the I/O range of variable var according to string.
160!> string uses range specification expressions described in
161!> "5.4 Comma notation" of the gtool4 netCDF convention.
162!> Examples:
163!> @code
164!> <dim>=<lower>
165!> <dim>=<lower>:<upper>
166!> <dim>=<lower>:<upper>:<stride>
167!> @endcode
168!>
169!> Here, <dim> is a dimension number or name,
170!> <lower>, <upper> are coordinate values or grid numbers
171!> prefixed with "^", and <stride> is a grid count.
172!>
173!> Currently err always returns .false..
174!>
175!> Slice is a generic name for multiple subroutines;
176!> other methods using strings or numbers are also available.
177!> @param[inout] var Variable handle
178!> @param[in] string Range specification string
179!> @param[out] err Error flag
180!> @enden
181!>
182!> @ja
183!> @brief 入出力範囲を文字列で指定
184!>
185!> 変数 var の入出力範囲を、string に応じて指定します。
186!> string には gtool4 netCDF 規約の
187!> 「5.4 コンマ記法」に述べられる範囲指定表現を用います。
188!> 凡例を以下に挙げます。
189!> @code
190!> <dim>=<lower>
191!> <dim>=<lower>:<upper>
192!> <dim>=<lower>:<upper>:<stride>
193!> @endcode
194!>
195!> ここで、<dim> は次元番号または次元名であり、
196!> <lower>, <upper>
197!> は座標値または "^" を前置した格子番号です。
198!> <stride> は格子数です。
199!>
200!> 現在 err は必ず .false. を返すことになっています。
201!>
202!> Slice は複数のサブルーチンの総称名であり、
203!> 他にも文字列や番号で指定する方法があります。
204!> @param[inout] var 変数ハンドル
205!> @param[in] string 範囲指定文字列
206!> @param[out] err エラーフラグ
207!> @endja
208!>
209subroutine gtvarslicec(var, string, err)
210 use gtdata_types, only: gt_variable
211 use gtdata_generic, only: slice
212 use dc_trace, only: beginsub, endsub
213 use dc_url, only: gt_comma
215 type(gt_variable), intent(inout) :: var
216 character(len = *), intent(in) :: string
217 logical, intent(out) :: err
218 integer:: is, ie
219continue
220 call beginsub('GTVarSliceC', 'var=%d lim=<%c>', &
221 & i=(/var%mapid/), c1=trim(string))
222 call gtvar_dump(var)
223 ! コンマで区切って解釈
224 is = 1
225 do
226 ie = index(string(is: ), gt_comma)
227 if (ie == 0) exit
228 call limit_one(string(is: is+ie-2))
229 is = is + ie
230 if (is > len(string)) exit
231 enddo
232 call limit_one(string(is: ))
233 err = .false.
234 call endsub('GTVarSliceC')
235 return
236contains
237
238 subroutine limit_one(string)
239 use dc_url, only: gt_equal
240 use dc_string, only: strieq, stoi
242 character(len = *), intent(in):: string
243 integer:: equal, dimord
244 integer:: start, count, stride
245 logical:: myerr
246
247 if (string == '') return
248
249 if (strieq(string(1:4), "IGN:")) then
250 ! 隠蔽型指定子 ign:<dim> または ign:<dim>=<start>
251 equal = index(string, gt_equal)
252 if (equal == 0) then
253 start = 1
254 else
255 start = stoi(string(equal+1: ), default=1)
256 endif
257 dimord = dimname_to_dimord(var, string(5: equal-1))
258 call slice(var, dimord, start, 1, 1)
259 call del_dim(var, dimord, myerr)
260 return
261 endif
262
263 ! 限定型指定子 <dim>=<start>:<finish>:<stride>
264 !
265 equal = index(string, gt_equal)
266 if (equal == 0) return
267 dimord = dimname_to_dimord(var, string(1: equal-1))
268 if (dimord <= 0) return
269 !
270 call region_spec(dimord, string(equal+1: ), start, count, stride)
271 call slice(var, dimord, start, count, stride)
272 end subroutine limit_one
273
274 !
275 ! 範囲指定の = のあとを : で区切ってマップにいれる
276 !
277 subroutine region_spec(dimord, string, start, count, stride)
278 use dc_types, only: token
279 use dc_string, only: index_ofs, stoi
280 use dc_url, only: gt_circumflex, gt_colon
282 integer, intent(in):: dimord
283 integer, intent(out):: start, count, stride
284 character(len = *), intent(in):: string
285 integer:: colon, prev_colon, finish, dimlo, dimhi
286 character(len = token):: val(3)
287 continue
288 colon = index(string, gt_colon)
289 if (colon == 0) then
290 ! コロンがない場合は上下端に同じ値
291 val(1) = string(1: )
292 val(2) = val(1)
293 val(3) = ""
294 else
295 val(1) = string(1: colon - 1)
296 prev_colon = colon
297 colon = index_ofs(string, colon + 1, gt_colon)
298 if (colon > 0) then
299 val(2) = string(prev_colon + 1: colon - 1)
300 val(3) = string(colon + 1: )
301 else
302 val(2) = string(prev_colon + 1: )
303 val(3) = ""
304 endif
305 endif
306 if (val(3) == "") val(3) = "^1"
307
308 if (val(1)(1:1) == gt_circumflex) then
309 start = stoi(val(1)(2: ))
310 else if (val(1) == val(2)) then
311 start = nint(value_to_index(dimord, val(1)))
312 else
313 start = floor(value_to_index(dimord, val(1)))
314 endif
315 if (val(2) == val(1)) then
316 finish = start
317 else if (val(2)(1:1) == gt_circumflex) then
318 finish = stoi(val(2)(2: ))
319 else
320 finish = ceiling(value_to_index(dimord, val(2)))
321 endif
322
323 call dimrange(var, dimord, dimlo, dimhi)
324 start = min(max(dimlo, start), dimhi)
325 finish = min(max(dimlo, finish), dimhi)
326 count = abs(finish - start) + 1
327
328 if (val(3)(1:1) == gt_circumflex) then
329 stride = stoi(val(3)(2: ))
330 else
331 stride = stoi(val(3))
332 endif
333 stride = sign(stride, finish - start)
334 end subroutine region_spec
335
336 real function value_to_index(dimord, value) result(result)
337 !
338 ! GTVarSlice の引数 *var* に格納される変数の次元 *dimord*
339 ! に格納されるデータのうち, *value* が格納される
340 ! 格子番号を整数値にして返します.
341 !
342 ! 例えば次元に以下のデータが格納されているとします.
343 !
344 ! 0.05 0.1 0.15 0.20 0.25 0.30
345 !
346 ! この場合, *value* に 0.15 が与えられれば戻り値は 3. となります.
347 ! また *value* に 0.225 が与えられれば戻り値は 4.5 となります.
348 !
349 !
350 use gtdata_types, only: gt_variable
351 use gtdata_generic, only: get, open, close, inquire
352 use dc_string, only: stod
353 use dc_types, only: sp_eps
355 integer, intent(in):: dimord
356 character(len = *), intent(in):: value
357 type(gt_variable):: axisvar
358 real, allocatable:: axisval(:)
359 real:: val
360 integer:: i, n
361 logical:: myerr
362 continue
363 call beginsub('value_to_index', 'var=%d dimord=%d value=%c', &
364 & i=(/var%mapid, dimord/), c1=trim(value))
365
366 call open(axisvar, var, dimord, count_compact=.true., &
367 & inherit_slice=.false., err=myerr)
368 if (myerr) then
369 result = -1.0
370 return
371 endif
372 call inquire(axisvar, allcount=n)
373 allocate(axisval(n))
374 call get(axisvar, axisval, n, err=myerr)
375 call close(axisvar)
376 if (myerr) then
377 result = -1.0
378 return
379 else if (size(axisval) < 2) then
380 result = 1.0
381 goto 900
382 endif
383
384 val = real(stod(value), kind=kind(axisval))
385
386 ! call DbgMessage('value=%f axis=(/%*r/)', r=(/val, axisval(:)/), &
387 ! & n=(/size(axisval)/))
388
389 do, i = 1, size(axisval) - 1
390 if (abs(axisval(i + 1) - axisval(i)) <= sp_eps) then
391 result = real(i) + 0.5
392 goto 900
393 endif
394 result = real(i) + (val - axisval(i)) / (axisval(i + 1) - axisval(i))
395 if (result <= (i + 1)) goto 900
396 enddo
397
398900 continue
399 call endsub('value_to_index', 'value(%c) =~ index(%r)', &
400 & c1=trim(value), r=(/result/))
401 if (allocated(axisval)) then
402 deallocate(axisval)
403 endif
404 end function value_to_index
405
406end subroutine gtvarslicec
subroutine gtvarslicec(var, string, err)
subroutine gtvarslice(var, dimord, start, count, stride)
subroutine limit_one(string)
エラー処理用モジュール
Definition dc_error.f90:454
subroutine, public storeerror(number, where, err, cause_c, cause_i)
Definition dc_error.f90:891
文字型変数の操作
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
integer, parameter, public token
単語やキーワードを保持する文字型変数の種別型パラメタ
Definition dc_types.f90:128
real(sp), parameter, public sp_eps
単精度実数型変数のマシンイプシロン.
Definition dc_types.f90:87
変数 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
subroutine, public map_lookup(var, vid, map, ndims)
subroutine map_set(var, map, stat)
subroutine, public query_growable(vid, result)
integer function, public ndims(vid)