57 use,
intrinsic :: iso_c_binding, only : c_ptr
77 logical,
private,
allocatable :: inuse(:)
79 integer,
private :: n_entries = 0
81 integer,
private :: expansion_size = 10
83 type(
dofmap_t),
private,
pointer :: dof => null()
97 procedure, pass(this) :: set_expansion_size => &
219 integer,
optional,
intent(in) :: size
220 integer,
optional,
intent(in) :: expansion_size
221 type(
dofmap_t),
target,
intent(in),
optional :: dof
222 integer :: initial_size
227 if (
present(dof)) this%dof => dof
228 if (
present(expansion_size)) this%expansion_size = expansion_size
231 initial_size = this%expansion_size
232 if (
present(size)) initial_size =
size
234 if (initial_size .lt. 0)
then
235 call neko_error(
"scratch_registry::init: " // &
236 "Initial size must be non-negative.")
239 if (this%expansion_size .le. 0)
then
240 call neko_error(
"scratch_registry::init: " // &
241 "Expansion size must be positive.")
244 allocate(this%entries(initial_size))
245 allocate(this%inuse(initial_size), source = .false.)
254 if (this%get_n_inuse() .ne. 0)
then
255 call neko_error(
"scratch_registry::free: " // &
256 "Cannot free scratch registry with entries still in use.")
259 if (
allocated(this%entries))
then
260 do i = 1, this%n_entries
261 call this%entries(i)%free()
263 deallocate(this%entries)
266 if (
allocated(this%inuse))
deallocate(this%inuse)
267 if (
associated(this%dof))
nullify(this%dof)
271 this%expansion_size = 10
281 type(
dofmap_t),
target,
intent(in) :: dof
283 if (
associated(this%dof, dof))
then
285 else if (
associated(this%dof))
then
286 call neko_error(
"scratch_registry::set_dofmap: "&
287 //
"Dofmap is already assigned to scratch registry.")
297 integer,
intent(in) :: expansion_size
299 if (expansion_size .le. 0)
then
300 call neko_error(
"scratch_registry::set_expansion_size: "&
301 //
"Expansion size must be positive.")
304 this%expansion_size = expansion_size
323 if (
allocated(this%inuse))
then
324 n = count(this%inuse)
337 if (
allocated(this%entries))
then
338 n =
size(this%entries)
350 n = this%expansion_size
356 integer,
intent(in) :: index
374 real(kind=
rp),
pointer,
dimension(:),
intent(inout) :: scratch_entry
375 integer,
intent(inout) :: index
376 integer,
intent(in) :: n
377 logical,
intent(in) :: clear
384 do index = 1, this%n_entries
387 if (this%inuse(index)) cycle
388 if (.not. this%entries(index)%is_type(
'host_array')) cycle
391 ptr => this%entries(index)%get_host_array()
392 if (ptr%size() .eq. n)
then
393 this%inuse(index) = .true.
400 if (index .gt. this%n_entries)
then
401 this%n_entries = this%n_entries + 1
403 if (this%n_entries .gt.
size(this%entries))
call this%expand()
404 call this%entries(this%n_entries)%init_host_array(n)
405 ptr => this%entries(this%n_entries)%get_host_array()
407 this%inuse(this%n_entries) = .true.
412 scratch_entry => ptr%x
413 if (clear)
call rzero(scratch_entry, n)
422 integer,
intent(in) :: index
424 call this%relinquish_type(index,
'host_array')
431 integer,
intent(in) :: indices(:)
434 do i = 1,
size(indices)
435 call this%relinquish_type(indices(i),
'host_array')
447 type(c_ptr),
intent(inout) :: scratch_entry
448 integer,
intent(inout) :: index
449 integer,
intent(in) :: n
450 logical,
intent(in) :: clear
457 do index = 1, this%n_entries
460 if (this%inuse(index)) cycle
461 if (.not. this%entries(index)%is_type(
'device_array')) cycle
464 ptr => this%entries(index)%get_device_array()
465 if (ptr%size() .eq. n)
then
466 this%inuse(index) = .true.
473 if (index .gt. this%n_entries)
then
474 this%n_entries = this%n_entries + 1
476 if (this%n_entries .gt.
size(this%entries))
call this%expand()
477 call this%entries(this%n_entries)%init_device_array(n)
478 ptr => this%entries(this%n_entries)%get_device_array()
480 this%inuse(this%n_entries) = .true.
485 scratch_entry = ptr%x_d
495 integer,
intent(in) :: index
497 call this%relinquish_type(index,
'device_array')
504 integer,
intent(in) :: indices(:)
507 do i = 1,
size(indices)
508 call this%relinquish_type(indices(i),
'device_array')
519 type(
vector_t),
pointer,
intent(inout) :: scratch_entry
520 integer,
intent(inout) :: index
521 integer,
intent(in) :: n
522 logical,
intent(in) :: clear
526 do index = 1, this%n_entries
529 if (this%inuse(index)) cycle
530 if (.not. this%entries(index)%is_type(
'vector')) cycle
533 scratch_entry => this%entries(index)%get_vector()
534 if (scratch_entry%size() .eq. n)
then
535 this%inuse(index) = .true.
538 nullify(scratch_entry)
542 if (index .gt. this%n_entries)
then
543 this%n_entries = this%n_entries + 1
545 if (this%n_entries .gt.
size(this%entries))
call this%expand()
546 call this%entries(this%n_entries)%init_vector(n)
547 scratch_entry => this%entries(this%n_entries)%get_vector()
549 this%inuse(this%n_entries) = .true.
562 integer,
intent(in) :: index
564 call this%relinquish_type(index,
'vector')
571 integer,
intent(in) :: indices(:)
574 do i = 1,
size(indices)
575 call this%relinquish_type(indices(i),
'vector')
587 type(
matrix_t),
pointer,
intent(inout) :: scratch_entry
588 integer,
intent(inout) :: index
589 integer,
intent(in) :: nrows, ncols
590 logical,
intent(in) :: clear
594 do index = 1, this%n_entries
597 if (this%inuse(index)) cycle
598 if (.not. this%entries(index)%is_type(
'matrix')) cycle
601 scratch_entry => this%entries(index)%get_matrix()
602 if (all(scratch_entry%get_dims() .eq. [nrows, ncols]))
then
603 this%inuse(index) = .true.
606 nullify(scratch_entry)
610 if (index .gt. this%n_entries)
then
611 this%n_entries = this%n_entries + 1
613 if (this%n_entries .gt.
size(this%entries))
call this%expand()
614 call this%entries(this%n_entries)%init_matrix(nrows, ncols)
615 scratch_entry => this%entries(this%n_entries)%get_matrix()
617 this%inuse(this%n_entries) = .true.
630 integer,
intent(in) :: index
632 call this%relinquish_type(index,
'matrix')
639 integer,
intent(in) :: indices(:)
642 do i = 1,
size(indices)
643 call this%relinquish_type(indices(i),
'matrix')
656 type(
tensor3_t),
pointer,
intent(inout) :: scratch_entry
657 integer,
intent(inout) :: index
658 integer,
intent(in) :: n, m, l
659 logical,
intent(in) :: clear
663 do index = 1, this%n_entries
666 if (this%inuse(index)) cycle
667 if (.not. this%entries(index)%is_type(
'tensor3')) cycle
670 scratch_entry => this%entries(index)%get_tensor3()
671 if (all(scratch_entry%get_dims() .eq. [n, m, l]))
then
672 this%inuse(index) = .true.
675 nullify(scratch_entry)
679 if (index .gt. this%n_entries)
then
680 this%n_entries = this%n_entries + 1
682 if (this%n_entries .gt.
size(this%entries))
call this%expand()
683 call this%entries(this%n_entries)%init_tensor3(n, m, l)
684 scratch_entry => this%entries(this%n_entries)%get_tensor3()
686 this%inuse(this%n_entries) = .true.
693 call device_rzero(scratch_entry%x_d, scratch_entry%size())
695 call rzero(scratch_entry%x, scratch_entry%size())
705 integer,
intent(in) :: index
707 call this%relinquish_type(index,
'tensor3')
714 integer,
intent(in) :: indices(:)
717 do i = 1,
size(indices)
718 call this%relinquish_type(indices(i),
'tensor3')
732 type(
tensor4_t),
pointer,
intent(inout) :: scratch_entry
733 integer,
intent(inout) :: index
734 integer,
intent(in) :: n, m, l, k
735 logical,
intent(in) :: clear
739 do index = 1, this%n_entries
742 if (this%inuse(index)) cycle
743 if (.not. this%entries(index)%is_type(
'tensor4')) cycle
746 scratch_entry => this%entries(index)%get_tensor4()
747 if (all(scratch_entry%get_dims() .eq. [n, m, l, k]))
then
748 this%inuse(index) = .true.
751 nullify(scratch_entry)
755 if (index .gt. this%n_entries)
then
756 this%n_entries = this%n_entries + 1
758 if (this%n_entries .gt.
size(this%entries))
call this%expand()
759 call this%entries(this%n_entries)%init_tensor4(n, m, l, k)
760 scratch_entry => this%entries(this%n_entries)%get_tensor4()
762 this%inuse(this%n_entries) = .true.
769 call device_rzero(scratch_entry%x_d, scratch_entry%size())
771 call rzero(scratch_entry%x, scratch_entry%size())
781 integer,
intent(in) :: index
783 call this%relinquish_type(index,
'tensor4')
790 integer,
intent(in) :: indices(:)
793 do i = 1,
size(indices)
794 call this%relinquish_type(indices(i),
'tensor4')
804 type(
field_t),
pointer,
intent(inout) :: scratch_entry
805 integer,
intent(inout) :: index
806 logical,
intent(in) :: clear
807 character(len=10) :: name
809 if (.not.
associated(this%dof))
then
810 call neko_error(
"scratch_registry::request_field_stored_dof: " &
811 //
"No dofmap assigned to scratch registry.")
816 do index = 1, this%n_entries
819 if (this%inuse(index)) cycle
820 if (.not. this%entries(index)%is_type(
'field')) cycle
823 scratch_entry => this%entries(index)%get_field()
824 if (
associated(scratch_entry%dof, this%dof))
then
825 this%inuse(index) = .true.
828 nullify(scratch_entry)
832 if (index .gt. this%n_entries)
then
833 this%n_entries = this%n_entries + 1
835 if (this%n_entries .gt.
size(this%entries))
call this%expand()
836 write(name,
"(A3,I0.3)")
"wrk", this%n_entries
837 call this%entries(this%n_entries)%init_field(this%dof, name)
838 scratch_entry => this%entries(this%n_entries)%get_field()
840 this%inuse(this%n_entries) = .true.
856 type(
field_t),
pointer,
intent(inout) :: scratch_entry
857 integer,
intent(inout) :: index
858 type(
dofmap_t),
target,
intent(in) :: dof
859 logical,
intent(in) :: clear
860 character(len=10) :: name
864 do index = 1, this%n_entries
867 if (this%inuse(index)) cycle
868 if (.not. this%entries(index)%is_type(
'field')) cycle
871 scratch_entry => this%entries(index)%get_field()
872 if (
associated(scratch_entry%dof, dof))
then
873 this%inuse(index) = .true.
876 nullify(scratch_entry)
880 if (index .gt. this%n_entries)
then
881 this%n_entries = this%n_entries + 1
883 if (this%n_entries .gt.
size(this%entries))
call this%expand()
884 write(name,
"(A3,I0.3)")
"wrk", this%n_entries
885 call this%entries(this%n_entries)%init_field(dof, name)
886 scratch_entry => this%entries(this%n_entries)%get_field()
888 this%inuse(this%n_entries) = .true.
900 integer,
intent(in) :: index
902 call this%relinquish_type(index,
'field')
909 integer,
intent(in) :: indices(:)
912 do i = 1,
size(indices)
913 call this%relinquish_type(indices(i),
'field')
924 integer,
intent(in) :: index
927 this%inuse(index) = .false.
936 integer,
intent(in) :: indices(:)
939 do i = 1,
size(indices)
940 call this%relinquish_single(indices(i))
952 integer,
intent(in) :: index
953 character(len=*),
intent(in) :: type
954 character(len=256) :: msg
957 if (trim(this%entries(index)%get_type()) .ne. type)
then
958 write(msg,
"(A,1X,A,1X,A,A)")
"scratch_registry::relinquish:", &
959 "Entry is not a", trim(type),
"."
963 this%inuse(index) = .false.
971 logical,
allocatable :: temp2(:)
974 n =
size(this%entries)
976 call move_alloc(this%entries, temp)
977 call move_alloc(this%inuse, temp2)
980 allocate(this%entries(n + this%expansion_size))
981 allocate(this%inuse(n + this%expansion_size), source = .false.)
985 call this%entries(i)%move_from(temp(i))
986 this%inuse(i) = temp2(i)
991 if (
allocated(temp))
deallocate(temp)
992 if (
allocated(temp2))
deallocate(temp2)
Module containing device only array type.
subroutine, public device_rzero(a_d, n, strm)
Zero a real vector.
Defines a mapping of the degrees of freedom.
subroutine, public field_rzero(a, n)
Zero a real vector.
Module containing host-only array type.
subroutine, public rzero(a, n)
Zero a real vector.
subroutine, public matrix_rzero(a, n)
Zero a real matrix .
integer, parameter neko_bcknd_device
integer, parameter, public rp
Global precision used in computations.
Defines a registry entry for storing and requesting temporary objects This is used in the registries ...
Defines a registry for storing and requesting temporary objects This can be used when you have a func...
logical function get_inuse(this, index)
Get the inuse status for a given index.
subroutine relinquish_matrix_single(this, index)
Relinquish the use of a matrix in the registry.
subroutine scratch_registry_free(this)
Destructor.
subroutine request_tensor3(this, scratch_entry, index, n, m, l, clear)
Get a tensor3 from the registry by assigning it to a pointer.
subroutine relinquish_matrix_multiple(this, indices)
Relinquish the use of multiple matrices in the registry.
subroutine request_vector(this, scratch_entry, index, n, clear)
Get a vector from the registry by assigning it to a pointer.
subroutine relinquish_host_array_single(this, index)
Relinquish the use of a host_array in the registry.
subroutine request_field_free_dof(this, scratch_entry, index, dof, clear)
Get a field from the registry by assigning it to a pointer.
subroutine relinquish_device_array_multiple(this, indices)
Relinquish the use of multiple device_arrays in the registry.
subroutine relinquish_tensor3_single(this, index)
Relinquish the use of a tensor3 in the registry.
integer function get_n_entries(this)
Get the number of objects stored in the registry.
subroutine request_device_array(this, scratch_entry, index, n, clear)
Get a device array from the registry by assigning it to a pointer.
subroutine relinquish_field_single(this, index)
Relinquish the use of a field in the registry.
subroutine relinquish_host_array_multiple(this, indices)
Relinquish the use of multiple host_arrays in the registry.
subroutine relinquish_tensor3_multiple(this, indices)
Relinquish the use of multiple tensor3s in the registry.
subroutine scratch_registry_set_dofmap(this, dof)
Assign a dofmap to the scratch registry.
subroutine relinquish_field_multiple(this, indices)
Relinquish the use of multiple fields in the registry.
subroutine request_host_array(this, scratch_entry, index, n, clear)
Get a host array from the registry by assigning it to a pointer.
type(scratch_registry_t), target, public neko_scratch_registry
Global scratch registry.
subroutine relinquish_vector_multiple(this, indices)
Relinquish the use of multiple vectors in the registry.
integer function get_size(this)
Get the size of the objects array.
subroutine request_tensor4(this, scratch_entry, index, n, m, l, k, clear)
Get a tensor4 from the registry by assigning it to a pointer.
subroutine scratch_registry_set_expansion_size(this, expansion_size)
Assign a new expansion size to the scratch registry.
subroutine expand(this)
Expand the registry by expansion_size.
subroutine request_matrix(this, scratch_entry, index, nrows, ncols, clear)
Get a matrix from the registry by assigning it to a pointer.
subroutine relinquish_device_array_single(this, index)
Relinquish the use of a device_array in the registry.
integer function get_n_inuse(this)
Get the number of objects currently in use.
subroutine relinquish_tensor4_single(this, index)
Relinquish the use of a tensor4 in the registry.
subroutine request_field_stored_dof(this, scratch_entry, index, clear)
Get a field from the registry by assigning it to a pointer.
subroutine relinquish_vector_single(this, index)
Relinquish the use of a vector in the registry.
subroutine scratch_registry_init(this, size, expansion_size, dof)
Constructor, optionally taking initial registry and expansion size as argument.
subroutine relinquish_type(this, index, type)
Relinquish a single index based on a specified type.
subroutine relinquish_multiple(this, indices)
Relinquish the use of multiple objects in the registry.
subroutine relinquish_single(this, index)
Relinquish the use of an object in the registry.
subroutine relinquish_tensor4_multiple(this, indices)
Relinquish the use of multiple tensor4s in the registry.
pure integer function get_expansion_size(this)
Get the expansion size.
subroutine, public vector_rzero(a, n)
Zero a real vector.
Device-only temporary array.
Host-only temporary array.