Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
registry_entry.f90
Go to the documentation of this file.
1! Copyright (c) 2025-2026, The Neko Authors
2! All rights reserved.
3!
4! Redistribution and use in source and binary forms, with or without
5! modification, are permitted provided that the following conditions
6! are met:
7!
8! * Redistributions of source code must retain the above copyright
9! notice, this list of conditions and the following disclaimer.
10!
11! * Redistributions in binary form must reproduce the above
12! copyright notice, this list of conditions and the following
13! disclaimer in the documentation and/or other materials provided
14! with the distribution.
15!
16! * Neither the name of the authors nor the names of its
17! contributors may be used to endorse or promote products derived
18! from this software without specific prior written permission.
19!
20! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21! "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22! LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23! FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24! COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25! INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26! BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27! LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29! LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30! ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31! POSSIBILITY OF SUCH DAMAGE.
32!
37 use num_types, only : rp
38 use host_array, only : host_array_t
40 use vector, only : vector_t
41 use matrix, only : matrix_t
42 use tensor3, only : tensor3_t
43 use tensor4, only : tensor4_t
44 use field, only : field_t
45
46 use dofmap, only : dofmap_t
47 use utils, only : neko_error
48 implicit none
49 private
50
51 type, public :: registry_entry_t
53 character(len=80), private :: name = ""
55 character(len=80), private :: type = ""
57 logical, private :: allocated = .false.
58
59 ! Storage. Only one of these will be allocated at a time.
60 real(kind=rp), private :: real_scalar = 0.0_rp
61 integer, private :: integer_scalar = 0
62
63 ! Array objects
64 type(host_array_t), private, pointer :: host_array_ptr => null()
65 type(device_array_t), private, pointer :: device_array_ptr => null()
66
67 ! Mathematical objects
68 type(vector_t), private, pointer :: vector_ptr => null()
69 type(matrix_t), private, pointer :: matrix_ptr => null()
70 type(tensor3_t), private, pointer :: tensor3_ptr => null()
71 type(tensor4_t), private, pointer :: tensor4_ptr => null()
72
73 ! Complex objects
74 type(field_t), private, pointer :: field_ptr => null()
75
76 contains
77 ! Constructors
78 procedure, pass(this) :: init_real_scalar => init_register_real_scalar
79 procedure, pass(this) :: init_integer_scalar => &
81 procedure, pass(this) :: init_host_array => init_register_host_array
82 procedure, pass(this) :: init_device_array => init_register_device_array
83 procedure, pass(this) :: init_vector => init_register_vector
84 procedure, pass(this) :: init_matrix => init_register_matrix
85 procedure, pass(this) :: init_tensor3 => init_register_tensor3
86 procedure, pass(this) :: init_tensor4 => init_register_tensor4
87 procedure, pass(this) :: init_field => init_register_field
88
90 procedure, pass(this) :: free => free_register
91
93 procedure, pass(this) :: get_name
94 procedure, pass(this) :: get_type
95 procedure, pass(this) :: get_real_scalar
96 procedure, pass(this) :: get_integer_scalar
97 procedure, pass(this) :: get_host_array
98 procedure, pass(this) :: get_device_array
99 procedure, pass(this) :: get_vector
100 procedure, pass(this) :: get_matrix
101 procedure, pass(this) :: get_tensor3
102 procedure, pass(this) :: get_tensor4
103 procedure, pass(this) :: get_field
104
105 procedure, pass(this) :: is_allocated
106 procedure, pass(this) :: is_type
107 procedure, pass(this) :: move_from => move_from_registry_entry
108 end type registry_entry_t
109
110contains
111
113 subroutine init_register_host_array(this, n, name)
114 class(registry_entry_t), intent(inout) :: this
115 integer, intent(in) :: n
116 character(len=*), optional, intent(in) :: name
117
118 if (this%allocated) then
119 call neko_error("init_register_host_array: " // &
120 "Register entry is already allocated.")
121 end if
122
123 call this%free()
124
125 allocate(this%host_array_ptr)
126 call this%host_array_ptr%init(n)
127
128 if (present(name)) this%name = trim(name)
129 this%type = 'host_array'
130 this%allocated = .true.
131
132 end subroutine init_register_host_array
133
135 subroutine init_register_device_array(this, n, name)
136 class(registry_entry_t), intent(inout) :: this
137 integer, intent(in) :: n
138 character(len=*), optional, intent(in) :: name
139
140 if (this%allocated) then
141 call neko_error("init_register_device_array: " // &
142 "Register entry is already allocated.")
143 end if
144
145 call this%free()
146
147 allocate(this%device_array_ptr)
148 call this%device_array_ptr%init(n)
149
150 if (present(name)) this%name = trim(name)
151 this%type = 'device_array'
152 this%allocated = .true.
153
154 end subroutine init_register_device_array
155
157 subroutine init_register_vector(this, n, name)
158 class(registry_entry_t), intent(inout) :: this
159 integer, intent(in) :: n
160 character(len=*), optional, intent(in) :: name
161
162 if (this%allocated) then
163 call neko_error("init_register_vector: " &
164 // "Register entry is already allocated.")
165 end if
166
167 call this%free()
168
169 allocate(this%vector_ptr)
170 call this%vector_ptr%init(n)
171
172 if (present(name)) this%name = trim(name)
173 this%type = 'vector'
174 this%allocated = .true.
175
176 end subroutine init_register_vector
177
179 subroutine init_register_matrix(this, nrows, ncols, name)
180 class(registry_entry_t), intent(inout) :: this
181 integer, intent(in) :: nrows, ncols
182 character(len=*), optional, intent(in) :: name
183
184 if (this%allocated) then
185 call neko_error("init_register_matrix: " &
186 // "Register entry is already allocated.")
187 end if
188
189 call this%free()
190
191 allocate(this%matrix_ptr)
192 call this%matrix_ptr%init(nrows, ncols)
193
194 if (present(name)) this%name = trim(name)
195 this%type = 'matrix'
196 this%allocated = .true.
197
198 end subroutine init_register_matrix
199
201 subroutine init_register_tensor3(this, n, m, l, name)
202 class(registry_entry_t), intent(inout) :: this
203 integer, intent(in) :: n, m, l
204 character(len=*), optional, intent(in) :: name
205
206 if (this%allocated) then
207 call neko_error("init_register_tensor3: " &
208 // "Register entry is already allocated.")
209 end if
210
211 call this%free()
212
213 allocate(this%tensor3_ptr)
214 call this%tensor3_ptr%init(n, m, l)
215
216 if (present(name)) this%name = trim(name)
217 this%type = 'tensor3'
218 this%allocated = .true.
219
220 end subroutine init_register_tensor3
221
223 subroutine init_register_tensor4(this, n, m, l, k, name)
224 class(registry_entry_t), intent(inout) :: this
225 integer, intent(in) :: n, m, l, k
226 character(len=*), optional, intent(in) :: name
227
228 if (this%allocated) then
229 call neko_error("init_register_tensor4: " &
230 // "Register entry is already allocated.")
231 end if
232
233 call this%free()
234
235 allocate(this%tensor4_ptr)
236 call this%tensor4_ptr%init(n, m, l, k)
237
238 if (present(name)) this%name = trim(name)
239 this%type = 'tensor4'
240 this%allocated = .true.
241
242 end subroutine init_register_tensor4
243
245 subroutine init_register_field(this, dof, name)
246 class(registry_entry_t), intent(inout) :: this
247 type(dofmap_t), target, intent(in) :: dof
248 character(len=*), intent(in) :: name
249
250 if (this%allocated) then
251 call neko_error("init_register_field: " &
252 // "Register entry is already allocated.")
253 end if
254
255 call this%free()
256
257 allocate(this%field_ptr)
258 call this%field_ptr%init(dof, trim(name))
259
260 this%name = trim(name)
261 this%type = 'field'
262 this%allocated = .true.
263
264 end subroutine init_register_field
265
267 subroutine init_register_real_scalar(this, val, name)
268 class(registry_entry_t), intent(inout) :: this
269 real(kind=rp), intent(in) :: val
270 character(len=*), optional, intent(in) :: name
271
272 if (this%allocated) then
273 call neko_error("init_register_real_scalar: " &
274 // "Register entry is already allocated.")
275 end if
276
277 call this%free()
278
279 this%real_scalar = val
280
281 if (present(name)) this%name = trim(name)
282 this%type = 'real_scalar'
283 this%allocated = .true.
284
285 end subroutine init_register_real_scalar
286
288 subroutine init_register_integer_scalar(this, val, name)
289 class(registry_entry_t), intent(inout) :: this
290 integer, intent(in) :: val
291 character(len=*), optional, intent(in) :: name
292
293 if (this%allocated) then
294 call neko_error("init_register_integer_scalar: " &
295 // "Register entry is already allocated.")
296 end if
297
298 call this%free()
299
300 this%integer_scalar = val
301
302 if (present(name)) this%name = trim(name)
303 this%type = 'integer_scalar'
304 this%allocated = .true.
305
306 end subroutine init_register_integer_scalar
307
309 subroutine free_register(this)
310 class(registry_entry_t), intent(inout) :: this
311
312 if (associated(this%host_array_ptr)) then
313 call this%host_array_ptr%free()
314 deallocate(this%host_array_ptr)
315 end if
316
317 if (associated(this%device_array_ptr)) then
318 call this%device_array_ptr%free()
319 deallocate(this%device_array_ptr)
320 end if
321
322 if (associated(this%vector_ptr)) then
323 call this%vector_ptr%free()
324 deallocate(this%vector_ptr)
325 end if
326
327 if (associated(this%matrix_ptr)) then
328 call this%matrix_ptr%free()
329 deallocate(this%matrix_ptr)
330 end if
331
332 if (associated(this%tensor3_ptr)) then
333 call this%tensor3_ptr%free()
334 deallocate(this%tensor3_ptr)
335 end if
336
337 if (associated(this%tensor4_ptr)) then
338 call this%tensor4_ptr%free()
339 deallocate(this%tensor4_ptr)
340 end if
341
342 if (associated(this%field_ptr)) then
343 call this%field_ptr%free()
344 deallocate(this%field_ptr)
345 end if
346
347 this%real_scalar = 0.0_rp
348 this%integer_scalar = 0
349
350 this%name = ""
351 this%type = ""
352 this%allocated = .false.
353
354 end subroutine free_register
355
357 pure function get_name(this) result(name)
358 class(registry_entry_t), intent(in) :: this
359 character(len=:), allocatable :: name
360 name = trim(this%name)
361 end function get_name
362
364 pure function get_type(this) result(type)
365 class(registry_entry_t), intent(in) :: this
366 character(len=:), allocatable :: type
367 type = trim(this%type)
368 end function get_type
369
371 pure function is_allocated(this) result(allocated)
372 class(registry_entry_t), intent(in) :: this
373 logical :: allocated
374 allocated = this%allocated
375 end function is_allocated
376
378 pure logical function is_type(this, type_str)
379 class(registry_entry_t), intent(in) :: this
380 character(len=*), intent(in) :: type_str
381 is_type = trim(this%type) .eq. trim(type_str)
382 end function is_type
383
385 function get_host_array(this) result(host_array_ptr)
386 class(registry_entry_t), target, intent(in) :: this
387 type(host_array_t), pointer :: host_array_ptr
388 if (this%get_type() .ne. 'host_array') then
389 call neko_error("registry_entry::get_host_array: " &
390 // "Registry entry is not of type 'host_array'.")
391 end if
392 host_array_ptr => this%host_array_ptr
393 end function get_host_array
394
396 function get_device_array(this) result(device_array_ptr)
397 class(registry_entry_t), target, intent(in) :: this
398 type(device_array_t), pointer :: device_array_ptr
399 if (this%get_type() .ne. 'device_array') then
400 call neko_error("registry_entry::get_device_array: " &
401 // "Registry entry is not of type 'device_array'.")
402 end if
403 device_array_ptr => this%device_array_ptr
404 end function get_device_array
405
407 function get_vector(this) result(vector_ptr)
408 class(registry_entry_t), target, intent(in) :: this
409 type(vector_t), pointer :: vector_ptr
410 if (this%get_type() .ne. 'vector') then
411 call neko_error("registry_entry::get_vector: " &
412 // "Registry entry is not of type 'vector'.")
413 end if
414 vector_ptr => this%vector_ptr
415 end function get_vector
416
418 function get_matrix(this) result(matrix_ptr)
419 class(registry_entry_t), target, intent(in) :: this
420 type(matrix_t), pointer :: matrix_ptr
421 if (this%get_type() .ne. 'matrix') then
422 call neko_error("registry_entry::get_field: " &
423 // "Registry entry is not of type 'matrix'.")
424 end if
425 matrix_ptr => this%matrix_ptr
426 end function get_matrix
427
429 function get_tensor3(this) result(tensor3_ptr)
430 class(registry_entry_t), target, intent(in) :: this
431 type(tensor3_t), pointer :: tensor3_ptr
432 if (this%get_type() .ne. 'tensor3') then
433 call neko_error("registry_entry::get_field: " &
434 // "Registry entry is not of type 'tensor3'.")
435 end if
436 tensor3_ptr => this%tensor3_ptr
437 end function get_tensor3
438
440 function get_tensor4(this) result(tensor4_ptr)
441 class(registry_entry_t), target, intent(in) :: this
442 type(tensor4_t), pointer :: tensor4_ptr
443 if (this%get_type() .ne. 'tensor4') then
444 call neko_error("registry_entry::get_field: " &
445 // "Registry entry is not of type 'tensor4'.")
446 end if
447 tensor4_ptr => this%tensor4_ptr
448 end function get_tensor4
449
451 function get_field(this) result(field_ptr)
452 class(registry_entry_t), target, intent(in) :: this
453 type(field_t), pointer :: field_ptr
454 if (this%get_type() .ne. 'field') then
455 call neko_error("registry_entry::get_field: " &
456 // "Registry entry is not of type 'field'.")
457 end if
458 field_ptr => this%field_ptr
459 end function get_field
460
462 function get_real_scalar(this) result(scalar_ptr)
463 class(registry_entry_t), target, intent(in) :: this
464 real(kind=rp), pointer :: scalar_ptr
465 if (this%get_type() .ne. 'real_scalar') then
466 call neko_error("registry_entry::get_real_scalar: " &
467 // "Registry entry is not of type 'real_scalar'.")
468 end if
469 scalar_ptr => this%real_scalar
470 end function get_real_scalar
471
473 function get_integer_scalar(this) result(scalar_ptr)
474 class(registry_entry_t), target, intent(in) :: this
475 integer, pointer :: scalar_ptr
476 if (this%get_type() .ne. 'integer_scalar') then
477 call neko_error("registry_entry::get_integer_scalar: " &
478 // "Registry entry is not of type 'integer_scalar'.")
479 end if
480 scalar_ptr => this%integer_scalar
481 end function get_integer_scalar
482
484 subroutine move_from_registry_entry(this, source)
485 class(registry_entry_t), intent(inout) :: this
486 class(registry_entry_t), intent(inout) :: source
487
488 if (.not. source%is_allocated()) return
489 call this%free()
490
491 this%name = source%name
492 this%type = source%type
493 this%allocated = source%allocated
494
495 select case (trim(this%type))
496 case ('real_scalar')
497 this%real_scalar = source%real_scalar
498 case ('integer_scalar')
499 this%integer_scalar = source%integer_scalar
500 case ('host_array')
501 this%host_array_ptr => source%host_array_ptr
502 nullify(source%host_array_ptr)
503 case ('device_array')
504 this%device_array_ptr => source%device_array_ptr
505 nullify(source%device_array_ptr)
506 case ('vector')
507 this%vector_ptr => source%vector_ptr
508 nullify(source%vector_ptr)
509 case ('matrix')
510 this%matrix_ptr => source%matrix_ptr
511 nullify(source%matrix_ptr)
512 case ('tensor3')
513 this%tensor3_ptr => source%tensor3_ptr
514 nullify(source%tensor3_ptr)
515 case ('tensor4')
516 this%tensor4_ptr => source%tensor4_ptr
517 nullify(source%tensor4_ptr)
518 case ('field')
519 this%field_ptr => source%field_ptr
520 nullify(source%field_ptr)
521 case default
522 call neko_error("move_from_registry_entry: " // &
523 "Unsupported registry entry type: " // trim(this%type))
524 end select
525
526 ! Free the source entry after moving
527 call source%free()
528
529 end subroutine move_from_registry_entry
530end module registry_entry
Module containing device only array type.
Defines a mapping of the degrees of freedom.
Definition dofmap.f90:35
Defines a field.
Definition field.f90:34
Module containing host-only array type.
Defines a matrix.
Definition matrix.f90:34
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:14
Defines a registry entry for storing and requesting temporary objects This is used in the registries ...
real(kind=rp) function, pointer get_real_scalar(this)
Get the real scalar pointer of the registry entry.
subroutine init_register_field(this, dof, name)
Initialize a register entry.
type(tensor3_t) function, pointer get_tensor3(this)
Get the tensor3 pointer of the registry entry.
subroutine init_register_host_array(this, n, name)
Initialize by a host array.
pure character(len=:) function, allocatable get_name(this)
Get the name of the registry entry.
subroutine init_register_tensor4(this, n, m, l, k, name)
Initialize a register entry.
subroutine init_register_device_array(this, n, name)
Initialize by a device array.
type(tensor4_t) function, pointer get_tensor4(this)
Get the tensor4 pointer of the registry entry.
subroutine init_register_tensor3(this, n, m, l, name)
Initialize a register entry.
subroutine init_register_real_scalar(this, val, name)
Initialize a scalar register entry.
subroutine init_register_matrix(this, nrows, ncols, name)
Initialize a register entry.
type(device_array_t) function, pointer get_device_array(this)
Get the device_array pointer of the registry entry.
pure logical function is_type(this, type_str)
Check if the registry entry is of a specific type.
subroutine init_register_vector(this, n, name)
Initialize a register entry.
subroutine init_register_integer_scalar(this, val, name)
Initialize an integer scalar register entry.
subroutine move_from_registry_entry(this, source)
Move a registry entry from another entry.
type(field_t) function, pointer get_field(this)
Get the field pointer of the registry entry.
subroutine free_register(this)
Free a register entry.
type(host_array_t) function, pointer get_host_array(this)
Get the host array pointer of the registry entry.
pure logical function is_allocated(this)
Check if the registry entry is allocated.
type(vector_t) function, pointer get_vector(this)
Get the vector pointer of the registry entry.
type(matrix_t) function, pointer get_matrix(this)
Get the matrix pointer of the registry entry.
pure character(len=:) function, allocatable get_type(this)
Get the type of the registry entry.
integer function, pointer get_integer_scalar(this)
Get the integer scalar pointer of the registry entry.
Defines a rank-3 tensor.
Definition tensor3.f90:34
Defines a rank-4 tensor.
Definition tensor4.f90:34
Utilities.
Definition utils.f90:35
Defines a vector.
Definition vector.f90:34
Device-only temporary array.
Host-only temporary array.