gtool5 Fortran 90/95 ライブラリ 1.0.0-rc5
English
Loading...
Searching...
No Matches
gtdata_internal_vartable.f90
Go to the documentation of this file.
1!> @file gtdata_internal_vartable.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 Internal variable table module
9!>
10!> @private
11!> This module should not be used directly by users.
12!> @enden
13!>
14!> @ja
15!> @brief 内部変数テーブルモジュール
16!>
17!> @private
18!> このモジュールはユーザが直接使用すべきではありません。
19!> @endja
20!>
21
22!>
23!> @en
24!> @brief gtool variable table management
25!>
26!> @private
27!> This module is not directly referenced from the gtool module,
28!> therefore naming conventions are quite flexible. Users must not call this.
29!>
30!> A gtool variable is actually just a handle and multi-dimensional iterator,
31!> where the handle is a small integer value.
32!> To access the actual entity, first lookup the map table using the handle value,
33!> then lookup the variable table using the vid obtained there to get
34!> the class and class-specific variable number. This is at most
35!> pointer + offset reference cost.
36!> While gtool variables create as many iterators as needed from entity variables,
37!> this variable table creates only one entry per entity variable, so it has a reference count.
38!> This eliminates the need for entity variables to manage reference counts.
39!> @enden
40!>
41!> @ja
42!> @brief gtool 変数表管理
43!>
44!> @private
45!> このモジュールは gtool モジュールから直接には引用されないため、
46!> 相当むちゃな名前の使い方をしている。ユーザは呼んではならない。
47!>
48!> gtool 変数というのは実は単なるハンドルと多次元イテレータであり、
49!> ハンドルは小さな整数値である。
50!> 実体にアクセスするためには、ハンドル値をキーにしてまずマップ表を引き、
51!> そこで得られた vid をキーにして変数表を引いて、
52!> 種別と種別ごとの変数番号を得る。これらはたかだかポインタ+オフセット
53!> 参照程度のコストである。
54!> gtool 変数は実体変数からイテレータが必要なだけ作成されるが、
55!> この変数表は実体変数につき1エントリしか作成しないので、参照数を持つ。
56!> このため、実体変数は変数に付いて参照数管理をしなくてもよくなる。
57!> @endja
58!>
60
62 use dc_types, only: string
63 implicit none
64 private
65
66 integer, parameter, public :: vid_invalid = -1
67
68 integer, parameter, public :: vtb_class_unused = 0
69 integer, parameter, public :: vtb_class_netcdf = 1
70 integer, parameter, public :: classes_max = 2
71
72 type var_table_entry
73 integer:: class
74 integer:: cid
75 integer:: refcount
76 end type var_table_entry
77
78 type(var_table_entry), save, allocatable:: table(:)
79 integer, parameter:: table_ini_size = 16
80
81 type(gd_nc_variable_search), public, save:: gdnc_search
82
84 public:: vartable_dump
86 private:: var_table_entry, table, table_ini_size
87 private:: entry_cleanup
88
89 interface dimrange
90 module procedure dimrange_direct
91 end interface
92
93contains
94
95 !>
96 !> @en
97 !> @brief Dump variable table entry for debugging
98 !> @param[in] vid Variable ID to dump
99 !> @enden
100 !>
101 !> @ja
102 !> @brief デバッグ用変数テーブルエントリのダンプ
103 !> @param[in] vid ダンプする変数ID
104 !> @endja
105 !>
106 subroutine vartable_dump(vid)
107 use dc_trace, only: dbgmessage
110 integer, intent(in):: vid
111 character(10):: class
112 if (.not. allocated(table)) return
113 if (vid <= 0 .or. vid > size(table)) return
114 select case(table(vid)%class)
115 case(vtb_class_netcdf)
116 class = 'netcdf'
117 case default
118 write(class, fmt="(i10)") table(vid)%class
119 end select
120 call dbgmessage('[vartable %d: class=%c cid=%d ref=%d]', &
121 & i=(/vid, table(vid)%cid, table(vid)%refcount/), &
122 & c1=trim(class))
123 select case(table(vid)%class)
124 case(vtb_class_netcdf)
125 call dbgmessage('[%c]', c1=trim(tostring(gd_nc_variable(table(vid)%cid))))
126 end select
127 end subroutine vartable_dump
128
129 !>
130 !> @en
131 !> @brief Initialize variable table entries to unused state
132 !> @param[out] vtb_entry Array of table entries to initialize
133 !> @enden
134 !>
135 !> @ja
136 !> @brief 変数テーブルエントリを未使用状態に初期化
137 !> @param[out] vtb_entry 初期化するテーブルエントリ配列
138 !> @endja
139 !>
140 subroutine entry_cleanup(vtb_entry)
141 type(var_table_entry), intent(out):: vtb_entry(:)
142 vtb_entry(:)%class = vtb_class_unused
143 vtb_entry(:)%cid = -1
144 vtb_entry(:)%refcount = 0
145 end subroutine entry_cleanup
146
147 !>
148 !> @en
149 !> @brief Add entry to variable table
150 !>
151 !> If an entry with the same class and cid already exists,
152 !> increments its reference count. Otherwise, creates a new entry.
153 !> @param[out] vid Assigned variable ID
154 !> @param[in] class Variable class (VTB_CLASS_NETCDF, etc.)
155 !> @param[in] cid Class-specific ID
156 !> @enden
157 !>
158 !> @ja
159 !> @brief 変数テーブルにエントリを追加
160 !>
161 !> 同じ class と cid を持つエントリが既に存在する場合、
162 !> その参照カウントを増加します。そうでなければ新しいエントリを作成します。
163 !> @param[out] vid 割り当てられた変数ID
164 !> @param[in] class 変数クラス (VTB_CLASS_NETCDF 等)
165 !> @param[in] cid クラス固有のID
166 !> @endja
167 !>
168 subroutine vartableadd(vid, class, cid)
169 use dc_trace, only: dbgmessage
170 integer, intent(out):: vid
171 integer, intent(in):: class, cid
172 type(var_table_entry), allocatable:: tmp_table(:)
173 integer:: n
174 continue
175 ! 必要ならば初期幅確保
176 if (.not. allocated(table)) then
177 allocate(table(table_ini_size))
178 call entry_cleanup(table(:))
179 endif
180 ! 該当があれば参照数増加
181 do, n = 1, size(table)
182 if (table(n)%class == class .and. table(n)%cid == cid) then
183 table(n)%refcount = table(n)%refcount + 1
184 call dbgmessage('gtdata_vartable.add(class=%d cid=%d) found (ref=%d)', &
185 & i=(/table(n)%class, table(n)%cid, table(n)%refcount/))
186 vid = n
187 return
188 endif
189 enddo
190 ! もし空きが無ければ表を拡張
191 if (all(table(:)%class /= vtb_class_unused)) then
192 n = size(table)
193 allocate(tmp_table(n))
194 tmp_table(:) = table(:)
195 deallocate(table)
196 allocate(table(n * 2))
197 table(1:n) = tmp_table(1:n)
198 deallocate(tmp_table)
199 table(n+1:n*2) = var_table_entry(vtb_class_unused, -1, 0)
200 endif
201 do, n = 1, size(table)
202 if (table(n)%class == vtb_class_unused) then
203 table(n)%class = class
204 table(n)%cid = cid
205 table(n)%refcount = 1
206 vid = n
207 return
208 endif
209 enddo
210 vid = vid_invalid
211 end subroutine vartableadd
212
213 !>
214 !> @en
215 !> @brief Delete entry from variable table
216 !>
217 !> Decrements the reference count. When it reaches zero,
218 !> action is set to .true. indicating actual deletion should occur.
219 !> @param[in] vid Variable ID to delete
220 !> @param[out] action .true. if actual deletion should be performed
221 !> @param[out] err Error flag (optional)
222 !> @enden
223 !>
224 !> @ja
225 !> @brief 変数テーブルからエントリを削除
226 !>
227 !> 参照カウントを減少させます。ゼロになった場合、
228 !> 実際の削除を行うべきことを示すために action に .true. が設定されます。
229 !> @param[in] vid 削除する変数ID
230 !> @param[out] action 実際の削除を行うべきかどうか
231 !> @param[out] err エラーフラグ (省略可能)
232 !> @endja
233 !>
234 subroutine vartabledelete(vid, action, err)
235 integer, intent(in):: vid
236 logical, intent(out):: action
237 logical, intent(out), optional:: err
238 if (.not. allocated(table)) goto 999
239 if (vid <= 0 .or. vid > size(table)) goto 999
240 if (table(vid)%class <= vtb_class_unused) goto 999
241 if (table(vid)%class > classes_max) goto 999
242 table(vid)%refcount = max(table(vid)%refcount - 1, 0)
243 action = (table(vid)%refcount == 0)
244 if (present(err)) err = .false.
245 return
246999 continue
247 action = .false.
248 if (present(err)) err = .true.
249 end subroutine vartabledelete
250
251 !>
252 !> @en
253 !> @brief Look up variable table entry
254 !>
255 !> Returns the class and cid of the entry with the specified vid.
256 !> @param[in] vid Variable ID to look up
257 !> @param[out] class Variable class (optional)
258 !> @param[out] cid Class-specific ID (optional)
259 !> @enden
260 !>
261 !> @ja
262 !> @brief 変数テーブルエントリを検索
263 !>
264 !> 指定された vid を持つエントリの class と cid を返します。
265 !> @param[in] vid 検索する変数ID
266 !> @param[out] class 変数クラス (省略可能)
267 !> @param[out] cid クラス固有のID (省略可能)
268 !> @endja
269 !>
270 subroutine vartablelookup(vid, class, cid)
271 integer, intent(in):: vid
272 integer, intent(out), optional:: class, cid
273 if (.not. allocated(table)) goto 999
274 if (vid <= 0 .or. vid > size(table)) goto 999
275 if (table(vid)%class <= vtb_class_unused) goto 999
276 if (table(vid)%class > classes_max) goto 999
277 if (present(class)) class = table(vid)%class
278 if (present(cid)) cid = table(vid)%cid
279 return
280999 continue
281 if (present(class)) class = vtb_class_unused
282 end subroutine vartablelookup
283
284 !>
285 !> @en
286 !> @brief Increment reference count of variable table entry
287 !> @param[in] vid Variable ID
288 !> @param[out] err Error flag (optional)
289 !> @enden
290 !>
291 !> @ja
292 !> @brief 変数テーブルエントリの参照カウントを増加
293 !> @param[in] vid 変数ID
294 !> @param[out] err エラーフラグ (省略可能)
295 !> @endja
296 !>
297 subroutine vartablemore(vid, err)
298 integer, intent(in):: vid
299 logical, intent(out), optional:: err
300 if (.not. allocated(table)) goto 999
301 if (vid <= 0 .or. vid > size(table)) goto 999
302 if (table(vid)%class <= vtb_class_unused) goto 999
303 if (table(vid)%class > classes_max) goto 999
304 table(vid)%refcount = table(vid)%refcount + 1
305 if (present(err)) err = .false.
306 return
307999 continue
308 if (present(err)) err = .true.
309 end subroutine vartablemore
310
311 !>
312 !> @en
313 !> @brief Get dimension range of variable
314 !> @param[in] vid Variable ID
315 !> @param[out] dimlo Lower bound of dimension (always 1)
316 !> @param[out] dimhi Upper bound of dimension (total length)
317 !> @enden
318 !>
319 !> @ja
320 !> @brief 変数の次元範囲を取得
321 !> @param[in] vid 変数ID
322 !> @param[out] dimlo 次元の下限 (常に1)
323 !> @param[out] dimhi 次元の上限 (全長)
324 !> @endja
325 !>
326 subroutine dimrange_direct(vid, dimlo, dimhi)
328 use gtdata_netcdf_generic, only: gdncinquire => inquire
329 use dc_error, only: storeerror, nf90_einval
330 integer, intent(in):: vid
331 integer, intent(out):: dimlo, dimhi
332 integer:: class, cid
333 call vartablelookup(vid, class, cid)
334 select case(class)
335 case(vtb_class_netcdf)
336 dimlo = 1
337 call gdncinquire(gd_nc_variable(cid), dimlen=dimhi)
338 case default
339 call storeerror(nf90_einval, 'gtdata::dimrange')
340 end select
341 end subroutine dimrange_direct
342
343 !>
344 !> @en
345 !> @brief Get number of dimensions of variable
346 !> @param[in] vid Variable ID
347 !> @return Number of dimensions
348 !> @enden
349 !>
350 !> @ja
351 !> @brief 変数の次元数を取得
352 !> @param[in] vid 変数ID
353 !> @return 次元数
354 !> @endja
355 !>
356 integer function ndims(vid) result(result)
358 use gtdata_netcdf_generic, only: gdncinquire => inquire
359 use dc_error, only: storeerror, nf90_einval
360 integer, intent(in):: vid
361 integer:: class, cid
362 call vartablelookup(vid, class, cid)
363 select case(class)
364 case(vtb_class_netcdf)
365 call gdncinquire(gd_nc_variable(cid), ndims=result)
366 case default
367 call storeerror(nf90_einval, 'gtdata::ndims')
368 end select
369 end function ndims
370
371 !>
372 !> @en
373 !> @brief Query whether variable has unlimited dimension
374 !> @param[in] vid Variable ID
375 !> @param[out] result .true. if variable has unlimited dimension
376 !> @enden
377 !>
378 !> @ja
379 !> @brief 変数が無制限次元を持つか問い合わせ
380 !> @param[in] vid 変数ID
381 !> @param[out] result 無制限次元を持つ場合 .true.
382 !> @endja
383 !>
384 subroutine query_growable(vid, result)
387 use dc_error, only: storeerror, nf90_einval
388 integer, intent(in):: vid
389 logical, intent(out):: result
390 integer:: class, cid
391 call vartablelookup(vid, class, cid)
392 select case(class)
393 case(vtb_class_netcdf)
394 call inquire(gd_nc_variable(cid), growable=result)
395 case default
396 call storeerror(nf90_einval, 'gtdata::ndims')
397 end select
398 end subroutine query_growable
399
変数に関する問い合わせ
エラー処理用モジュール
Definition dc_error.f90:454
subroutine, public storeerror(number, where, err, cause_c, cause_i)
Definition dc_error.f90:891
デバッグ時の追跡用モジュール
Definition dc_trace.f90:150
subroutine, public dbgmessage(fmt, i, r, d, l, n, c1, c2, c3, ca)
Definition dc_trace.f90:661
種別型パラメタを提供します。
Definition dc_types.f90:55
integer, parameter, public string
文字列を保持する 文字型変数の種別型パラメタ
Definition dc_types.f90:137
subroutine, public vartabledelete(vid, action, err)
subroutine, public vartablelookup(vid, class, cid)
integer, parameter, public classes_max
integer, parameter, public vid_invalid
subroutine, public query_growable(vid, result)
subroutine, public vartablemore(vid, err)
subroutine, public vartableadd(vid, class, cid)
integer, parameter, public vtb_class_netcdf
type(gd_nc_variable_search), save, public gdnc_search
subroutine, public vartable_dump(vid)
integer function, public ndims(vid)
integer, parameter, public vtb_class_unused