Neko 1.99.2
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
registry.f90
Go to the documentation of this file.
1! Copyright (c) 2018-2025, 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!
35 use, intrinsic :: iso_fortran_env, only: error_unit
36 use field, only : field_t
37 use vector, only : vector_t
38 use matrix, only : matrix_t
40 use dofmap, only : dofmap_t
41 use utils, only : neko_error
42 use htable, only : h_cptr_t
43 use utils, only: neko_error
44 use comm, only : pe_rank
45 use json_module, only : json_file
46 use json_utils, only : json_get
47 use logger, only : neko_log, log_size
48 implicit none
49 private
50
51 type, public :: registry_t
53 type(registry_entry_t), private, allocatable :: entries(:)
55 type(json_file), private :: aliases
57 integer, private :: n_entries_ = 0
59 integer, private :: n_aliases_ = 0
61 integer, private :: expansion_size_ = 5
62 contains
64 procedure, pass(this) :: init => registry_init
66 procedure, pass(this) :: free => registry_free
68 procedure, private, pass(this) :: expand => registry_expand
69
71 procedure, pass(this) :: add_field => registry_add_field
73 procedure, pass(this) :: add_vector => registry_add_vector
75 procedure, pass(this) :: add_matrix => registry_add_matrix
77 procedure, pass(this) :: add_alias => registry_add_alias
78
80 procedure, pass(this) :: get_field_by_index => registry_get_field_by_index
82 procedure, pass(this) :: get_vector_by_index => &
85 procedure, pass(this) :: get_matrix_by_index => &
87
89 procedure, pass(this) :: get_field_by_name => registry_get_field_by_name
91 procedure, pass(this) :: get_vector_by_name => registry_get_vector_by_name
93 procedure, pass(this) :: get_matrix_by_name => registry_get_matrix_by_name
94
96 generic :: get_field => get_field_by_index, get_field_by_name
98 generic :: get_vector => get_vector_by_index, get_vector_by_name
100 generic :: get_matrix => get_matrix_by_index, get_matrix_by_name
101
103 procedure, pass(this) :: entry_exists => registry_entry_exists
105 procedure, pass(this) :: field_exists => registry_field_exists
107 procedure, pass(this) :: vector_exists => registry_vector_exists
109 procedure, pass(this) :: matrix_exists => registry_matrix_exists
110
112 procedure, pass(this) :: get_size => registry_get_size
114 procedure, pass(this) :: n_entries => registry_n_entries
116 procedure, pass(this) :: n_fields => registry_n_fields
118 procedure, pass(this) :: n_vectors => registry_n_vectors
120 procedure, pass(this) :: n_matrices => registry_n_matrices
122 procedure, pass(this) :: n_aliases => registry_n_aliases
124 procedure, pass(this) :: get_expansion_size => registry_get_expansion_size
125 end type registry_t
126
128 type(registry_t), public, target :: neko_registry
129
130contains
131 ! ========================================================================== !
132 ! Constructors/Destructors
133
137 subroutine registry_init(this, size, expansion_size)
138 class(registry_t), intent(inout):: this
139 integer, optional, intent(in) :: size
140 integer, optional, intent(in) :: expansion_size
141
142 call this%free()
143
144 if (present(size)) then
145 allocate(this%entries(size))
146 else
147 allocate(this%entries(25))
148 end if
149
150 call this%aliases%initialize()
151
152 if (present(expansion_size)) then
153 this%expansion_size_ = expansion_size
154 end if
155
156 end subroutine registry_init
157
159 subroutine registry_free(this)
160 class(registry_t), intent(inout):: this
161 integer :: i
162
163 if (allocated(this%entries)) then
164 do i = 1, this%n_entries()
165 call this%entries(i)%free()
166 end do
167 deallocate(this%entries)
168 end if
169
170 call this%aliases%destroy()
171
172 this%n_entries_ = 0
173 this%n_aliases_ = 0
174 this%expansion_size_ = 5
175 end subroutine registry_free
176
178 subroutine registry_expand(this)
179 class(registry_t), intent(inout) :: this
180 type(registry_entry_t), allocatable :: temp(:)
181
182 allocate(temp(this%n_entries_ + this%expansion_size_))
183 temp(1:this%n_entries_) = this%entries(1:this%n_entries_)
184 call move_alloc(temp, this%entries)
185 end subroutine registry_expand
186
187 ! ========================================================================== !
188 ! Methods for adding objects to the registry
189
195 subroutine registry_add_field(this, dof, name, ignore_existing)
196 class(registry_t), intent(inout) :: this
197 type(dofmap_t), target, intent(in) :: dof
198 character(len=*), target, intent(in) :: name
199 logical, optional, intent(in) :: ignore_existing
200 logical :: ignore_existing_
201
202 ignore_existing_ = .false.
203 if (present(ignore_existing)) then
204 ignore_existing_ = ignore_existing
205 end if
206
207 if (this%field_exists(name)) then
208 if (ignore_existing_) then
209 return
210 else
211 call neko_error("Field with name " // name // &
212 " is already registered")
213 end if
214 end if
215
216 if (this%n_entries() .eq. this%get_size()) then
217 call this%expand()
218 end if
219
220 this%n_entries_ = this%n_entries_ + 1
221
222 ! initialize the field at the appropriate index
223 call this%entries(this%n_entries_)%init_field(dof, name)
224
225 end subroutine registry_add_field
226
232 subroutine registry_add_vector(this, n, name, ignore_existing)
233 class(registry_t), intent(inout) :: this
234 integer, intent(in) :: n
235 character(len=*), target, intent(in) :: name
236 logical, optional, intent(in) :: ignore_existing
237 logical :: ignore_existing_
238
239 ignore_existing_ = .false.
240 if (present(ignore_existing)) then
241 ignore_existing_ = ignore_existing
242 end if
243
244 if (this%vector_exists(name)) then
245 if (ignore_existing_) then
246 return
247 else
248 call neko_error("Vector with name " // name // &
249 " is already registered")
250 end if
251 end if
252
253 if (this%n_entries() .eq. this%get_size()) then
254 call this%expand()
255 end if
256
257 this%n_entries_ = this%n_entries_ + 1
258
259 ! Initialize the named vector at the appropriate index
260 call this%entries(this%n_entries_)%init_vector(n, name)
261
262 end subroutine registry_add_vector
263
269 subroutine registry_add_matrix(this, nrows, ncols, name, ignore_existing)
270 class(registry_t), intent(inout) :: this
271 integer, intent(in) :: nrows, ncols
272 character(len=*), target, intent(in) :: name
273 logical, optional, intent(in) :: ignore_existing
274 logical :: ignore_existing_
275
276 ignore_existing_ = .false.
277 if (present(ignore_existing)) then
278 ignore_existing_ = ignore_existing
279 end if
280
281 if (this%matrix_exists(name)) then
282 if (ignore_existing_) then
283 return
284 else
285 call neko_error("Vector with name " // name // &
286 " is already registered")
287 end if
288 end if
289
290 if (this%n_entries() .eq. this%get_size()) then
291 call this%expand()
292 end if
293
294 this%n_entries_ = this%n_entries_ + 1
295
296 ! Initialize the named matrix at the appropriate index
297 call this%entries(this%n_entries_)%init_matrix(nrows, ncols, name)
298
299 end subroutine registry_add_matrix
300
304 subroutine registry_add_alias(this, alias, name)
305 class(registry_t), intent(inout) :: this
306 character(len=*), intent(in) :: alias
307 character(len=*), intent(in) :: name
308
309 if (this%entry_exists(alias)) then
310 call neko_error("Cannot create alias. Entry " // alias // &
311 " already exists in the registry")
312 end if
313
314 if (this%entry_exists(name)) then
315 this%n_aliases_ = this%n_aliases_ + 1
316 call this%aliases%add(trim(alias), trim(name))
317 else
318 call neko_error("Cannot create alias. Entry " // name // &
319 " could not be found in the registry")
320 end if
321 end subroutine registry_add_alias
322
323 ! ========================================================================== !
324 ! Methods for retrieving objects from the registry by index
325
327 function registry_get_field_by_index(this, i) result(f)
328 class(registry_t), target, intent(in) :: this
329 integer, intent(in) :: i
330 type(field_t), pointer :: f
331 character(len=:), allocatable :: buffer
332
333 if (i < 1) then
334 call neko_error("Field index must be > 1")
335 else if (i > this%n_entries()) then
336 call neko_error("Field index exceeds number of stored fields")
337 endif
338
339 if (this%entries(i)%get_type() .ne. 'field') then
340 write(buffer, *) "Requested index ", i, " is not a field, but a ", &
341 this%entries(i)%get_type()
342 call neko_error(buffer)
343 end if
344
345 f => this%entries(i)%get_field()
346 end function registry_get_field_by_index
347
349 function registry_get_vector_by_index(this, i) result(f)
350 class(registry_t), target, intent(in) :: this
351 integer, intent(in) :: i
352 type(vector_t), pointer :: f
353 character(len=:), allocatable :: buffer
354
355 if (i < 1) then
356 call neko_error("Vector index must be > 1")
357 else if (i > this%n_entries()) then
358 call neko_error("Vector index exceeds number of stored vectors")
359 endif
360
361 if (this%entries(i)%get_type() .ne. 'vector') then
362 write(buffer, *) "Requested index ", i, " is not a vector, but a ", &
363 this%entries(i)%get_type()
364 call neko_error(buffer)
365 end if
366
367 f => this%entries(i)%get_vector()
369
371 function registry_get_matrix_by_index(this, i) result(f)
372 class(registry_t), target, intent(in) :: this
373 integer, intent(in) :: i
374 type(matrix_t), pointer :: f
375 character(len=:), allocatable :: buffer
376
377 if (i < 1) then
378 call neko_error("Matrix index must be > 1")
379 else if (i > this%n_entries()) then
380 call neko_error("Matrix index exceeds number of stored matrices")
381 endif
382
383 if (this%entries(i)%get_type() .ne. 'matrix') then
384 write(buffer, *) "Requested index ", i, " is not a matrix, but a ", &
385 this%entries(i)%get_type()
386 call neko_error(buffer)
387 end if
388
389 f => this%entries(i)%get_matrix()
391
392 ! ========================================================================== !
393 ! Methods for retrieving objects from the registry by name
394
396 recursive function registry_get_field_by_name(this, name) result(f)
397 class(registry_t), target, intent(inout) :: this
398 character(len=*), intent(in) :: name
399 character(len=:), allocatable :: alias_target
400 type(field_t), pointer :: f
401 logical :: found
402 integer :: i
403
404 do i = 1, this%n_entries()
405 if (this%entries(i)%get_type() .eq. 'field' .and. &
406 this%entries(i)%get_name() .eq. trim(name)) then
407 f => this%entries(i)%get_field()
408 return
409 end if
410 end do
411
412 call this%aliases%get(name, alias_target, found)
413 if (found) then
414 f => this%get_field_by_name(alias_target)
415 return
416 end if
417
418 if (pe_rank .eq. 0) then
419 write(error_unit, *) "Current registry contents:"
420
421 do i = 1, this%n_entries()
422 write(error_unit, *) "- ", this%entries(i)%get_name()
423 end do
424 end if
425 call neko_error("Field " // name // " could not be found in the registry")
426
427 end function registry_get_field_by_name
428
429
431 recursive function registry_get_vector_by_name(this, name) result(f)
432 class(registry_t), target, intent(inout) :: this
433 character(len=*), intent(in) :: name
434 character(len=:), allocatable :: alias_target
435 type(vector_t), pointer :: f
436 logical :: found
437 integer :: i
438
439 found = .false.
440
441 do i = 1, this%n_entries()
442 if (this%entries(i)%get_type() .eq. 'vector' .and. &
443 this%entries(i)%get_name() .eq. trim(name)) then
444 f => this%entries(i)%get_vector()
445 return
446 end if
447 end do
448
449 call this%aliases%get(name, alias_target, found)
450 if (found) then
451 f => this%get_vector_by_name(alias_target)
452 return
453 end if
454
455 if (pe_rank .eq. 0) then
456 write(error_unit, *) "Current registry contents:"
457
458 do i = 1, this%n_entries()
459 write(error_unit, *) "- ", this%entries(i)%get_name()
460 end do
461 end if
462 call neko_error("Vector " // name // " could not be found in the registry")
463
464 end function registry_get_vector_by_name
465
467 recursive function registry_get_matrix_by_name(this, name) result(f)
468 class(registry_t), target, intent(inout) :: this
469 character(len=*), intent(in) :: name
470 character(len=:), allocatable :: alias_target
471 type(matrix_t), pointer :: f
472 logical :: found
473 integer :: i
474
475 found = .false.
476
477 do i = 1, this%n_entries()
478 if (this%entries(i)%get_type() .eq. 'matrix' .and. &
479 this%entries(i)%get_name() .eq. trim(name)) then
480 f => this%entries(i)%get_matrix()
481 return
482 end if
483 end do
484
485 call this%aliases%get(name, alias_target, found)
486 if (found) then
487 f => this%get_matrix_by_name(alias_target)
488 return
489 end if
490
491 if (pe_rank .eq. 0) then
492 write(error_unit, *) "Current registry contents:"
493
494 do i = 1, this%n_entries()
495 write(error_unit, *) "- ", this%entries(i)%get_name()
496 end do
497 end if
498 call neko_error("Matrix " // name // " could not be found in the registry")
499
500 end function registry_get_matrix_by_name
501
502 ! ========================================================================== !
503 ! Methods for checking existence of objects in the registry
504
506 function registry_entry_exists(this, name) result(found)
507 class(registry_t), target, intent(inout) :: this
508 character(len=*), intent(in) :: name
509 logical :: found
510 integer :: i
511
512 found = .false.
513 do i = 1, this%n_entries()
514 if (trim(this%entries(i)%get_name()) .eq. trim(name)) then
515 found = .true.
516 return
517 end if
518 end do
519
520 found = this%aliases%valid_path(name)
521 end function registry_entry_exists
522
524 function registry_field_exists(this, name) result(found)
525 class(registry_t), target, intent(inout) :: this
526 character(len=*), intent(in) :: name
527 logical :: found
528 integer :: i
529
530 found = .false.
531 do i = 1, this%n_entries()
532 if (this%entries(i)%get_type() .eq. 'field' .and. &
533 this%entries(i)%get_name() .eq. trim(name)) then
534 found = .true.
535 return
536 end if
537 end do
538
539 found = this%aliases%valid_path(name)
540 end function registry_field_exists
541
543 function registry_vector_exists(this, name) result(found)
544 class(registry_t), target, intent(inout) :: this
545 character(len=*), intent(in) :: name
546 logical :: found
547 integer :: i
548
549 found = .false.
550 do i = 1, this%n_entries()
551 if (this%entries(i)%get_type() .eq. 'vector' .and. &
552 this%entries(i)%get_name() .eq. trim(name)) then
553 found = .true.
554 return
555 end if
556 end do
557
558 found = this%aliases%valid_path(name)
559 end function registry_vector_exists
560
562 function registry_matrix_exists(this, name) result(found)
563 class(registry_t), target, intent(inout) :: this
564 character(len=*), intent(in) :: name
565 logical :: found
566 integer :: i
567
568 found = .false.
569 do i = 1, this%n_entries()
570 if (this%entries(i)%get_type() .eq. 'matrix' .and. &
571 this%entries(i)%get_name() .eq. trim(name)) then
572 found = .true.
573 return
574 end if
575 end do
576
577 found = this%aliases%valid_path(name)
578 end function registry_matrix_exists
579
580 ! ========================================================================== !
581 ! Generic component accessor methods
582
584 pure function registry_n_entries(this) result(n)
585 class(registry_t), intent(in) :: this
586 integer :: n
587
588 n = this%n_entries_
589 end function registry_n_entries
590
592 pure function registry_n_fields(this) result(n)
593 class(registry_t), intent(in) :: this
594 integer :: n, i
595
596 n = 0
597 do i = 1, this%n_entries()
598 if (this%entries(i)%get_type() .eq. 'field') then
599 n = n + 1
600 end if
601 end do
602 end function registry_n_fields
603
605 pure function registry_n_vectors(this) result(n)
606 class(registry_t), intent(in) :: this
607 integer :: n, i
608
609 n = 0
610 do i = 1, this%n_entries()
611 if (this%entries(i)%get_type() .eq. 'vector') then
612 n = n + 1
613 end if
614 end do
615 end function registry_n_vectors
616
618 pure function registry_n_matrices(this) result(n)
619 class(registry_t), intent(in) :: this
620 integer :: n, i
621
622 n = 0
623 do i = 1, this%n_entries()
624 if (this%entries(i)%get_type() .eq. 'matrix') then
625 n = n + 1
626 end if
627 end do
628 end function registry_n_matrices
629
631 pure function registry_n_aliases(this) result(n)
632 class(registry_t), intent(in) :: this
633 integer :: n
634
635 n = this%n_aliases_
636 end function registry_n_aliases
637
639 pure function registry_get_size(this) result(n)
640 class(registry_t), intent(in) :: this
641 integer :: n
642
643 if (allocated(this%entries)) then
644 n = size(this%entries)
645 else
646 n = 0
647 end if
648 end function registry_get_size
649
651 pure function registry_get_expansion_size(this) result(n)
652 class(registry_t), intent(in) :: this
653 integer :: n
654
655 n = this%expansion_size_
656 end function registry_get_expansion_size
657
659 subroutine registry_print(this)
660 class(registry_t), intent(in) :: this
661 character(len=LOG_SIZE), allocatable :: buffer
662 integer :: i
663
664 call neko_log%section("Field Registry Contents")
665 do i = 1, this%n_entries()
666 write(buffer, '(A,I4,A,A)') "- [", i, "] ", &
667 this%entries(i)%get_type(), ": ", this%entries(i)%get_name()
668 call neko_log%message(trim(buffer))
669 end do
670
671 call neko_log%end_section()
672 end subroutine registry_print
673
674end module registry
Retrieves a parameter by name or throws an error.
Generic buffer that is extended with buffers of varying rank.
Definition buffer.F90:34
Definition comm.F90:1
integer, public pe_rank
MPI rank.
Definition comm.F90:56
Defines a mapping of the degrees of freedom.
Definition dofmap.f90:35
Defines a field.
Definition field.f90:34
Implements a hash table ADT.
Definition htable.f90:36
Utilities for retrieving parameters from the case files.
Logging routines.
Definition log.f90:34
type(log_t), public neko_log
Global log stream.
Definition log.f90:76
integer, parameter, public log_size
Definition log.f90:46
Defines a matrix.
Definition matrix.f90:34
Defines a registry entry for storing and requesting temporary objects This is used in the scratch reg...
type(field_t) function, pointer get_field(this)
Get the field pointer of the registry entry.
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.
Defines a registry for storing solution fields.
Definition registry.f90:34
type(matrix_t) function, pointer registry_get_matrix_by_index(this, i)
Get pointer to a stored matrix by index.
Definition registry.f90:372
type(registry_t), target, public neko_registry
Global field registry.
Definition registry.f90:128
subroutine registry_free(this)
Destructor.
Definition registry.f90:160
recursive type(vector_t) function, pointer registry_get_vector_by_name(this, name)
Get pointer to a stored vector by name.
Definition registry.f90:432
type(vector_t) function, pointer registry_get_vector_by_index(this, i)
Get pointer to a stored vector by index.
Definition registry.f90:350
pure integer function registry_get_size(this)
Get the size of the fields array.
Definition registry.f90:640
subroutine registry_print(this)
Print the contents of the registry to standard output.
Definition registry.f90:660
subroutine registry_add_matrix(this, nrows, ncols, name, ignore_existing)
Add a matrix to the registry.
Definition registry.f90:270
subroutine registry_init(this, size, expansion_size)
Constructor.
Definition registry.f90:138
pure integer function registry_get_expansion_size(this)
Get the expansion size.
Definition registry.f90:652
pure integer function registry_n_vectors(this)
Get the number of vector stored in the registry.
Definition registry.f90:606
pure integer function registry_n_aliases(this)
Get the number of aliases stored in the registry.
Definition registry.f90:632
logical function registry_matrix_exists(this, name)
Check if a matrix with a given name is already in the registry.
Definition registry.f90:563
pure integer function registry_n_fields(this)
Get the number of fields stored in the registry.
Definition registry.f90:593
subroutine registry_add_alias(this, alias, name)
Add an alias for an existing entry in the registry.
Definition registry.f90:305
subroutine registry_add_field(this, dof, name, ignore_existing)
Add a field to the registry.
Definition registry.f90:196
recursive type(matrix_t) function, pointer registry_get_matrix_by_name(this, name)
Get pointer to a stored matrix by name.
Definition registry.f90:468
logical function registry_entry_exists(this, name)
Check if a field with a given name is already in the registry.
Definition registry.f90:507
pure integer function registry_n_entries(this)
Get number of registered entries.
Definition registry.f90:585
subroutine registry_expand(this)
Expand the fields array so as to accommodate more fields.
Definition registry.f90:179
pure integer function registry_n_matrices(this)
Get the number of matrix stored in the registry.
Definition registry.f90:619
logical function registry_vector_exists(this, name)
Check if a vector with a given name is already in the registry.
Definition registry.f90:544
recursive type(field_t) function, pointer registry_get_field_by_name(this, name)
Get pointer to a stored field by field name.
Definition registry.f90:397
subroutine registry_add_vector(this, n, name, ignore_existing)
Add a vector to the registry.
Definition registry.f90:233
type(field_t) function, pointer registry_get_field_by_index(this, i)
Get pointer to a stored field by index.
Definition registry.f90:328
logical function registry_field_exists(this, name)
Check if a field with a given name is already in the registry.
Definition registry.f90:525
Utilities.
Definition utils.f90:35
Defines a vector.
Definition vector.f90:34