Neko  0.8.99
A portable framework for high-order spectral element flow simulations
scratch_registry.f90
Go to the documentation of this file.
1 ! Copyright (c) 2018-2023, 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 !
38  use field, only : field_t, field_ptr_t
39  use dofmap, only : dofmap_t
40  implicit none
41  private
42 
43 
44  type, public :: scratch_registry_t
46  type(field_ptr_t), private, allocatable :: fields(:)
48  logical, private, allocatable :: inuse(:)
50  integer, private :: nfields
52  integer, private :: nfields_inuse
54  integer, private :: expansion_size
56  type(dofmap_t), pointer :: dof
57  contains
58  procedure, private, pass(this) :: expand
60  procedure, pass(this) :: free => scratch_registry_free
62  procedure, pass(this) :: get_nfields
64  procedure, pass(this) :: get_nfields_inuse
66  procedure, pass(this) :: get_expansion_size
68  procedure, pass(this) :: get_size
70  procedure, pass(this) :: get_inuse
72  procedure, pass(this) :: request_field
73  procedure, pass(this) :: relinquish_field_single
74  procedure, pass(this) :: relinquish_field_multiple
76  generic :: relinquish_field => relinquish_field_single, &
78  end type scratch_registry_t
79 
80  interface scratch_registry_t
81  procedure :: init
82  end interface scratch_registry_t
83 
85  type(scratch_registry_t), public, target :: neko_scratch_registry
86 
87 contains
88 
91  type(scratch_registry_t) function init(dof, size, expansion_size) result(this)
92  type(dofmap_t), target, intent(in) :: dof
93  integer, optional, intent(in) :: size
94  integer, optional, intent(in) :: expansion_size
95  integer :: i
96 
97  this%dof => dof
98 
99  if (present(size)) then
100  allocate (this%fields(size))
101  do i= 1, size
102  allocate(this%fields(i)%ptr)
103  end do
104  allocate (this%inuse(size))
105  else
106  allocate (this%fields(10))
107  allocate (this%inuse(10))
108  end if
109 
110  this%inuse(:) = .false.
111  if (present(expansion_size)) then
112  this%expansion_size = expansion_size
113  else
114  this%expansion_size = 10
115  end if
116 
117  this%nfields = 0
118  this%nfields_inuse = 0
119  end function init
120 
122  subroutine scratch_registry_free(this)
123  class(scratch_registry_t), intent(inout):: this
124  integer :: i
125 
126  if (allocated(this%fields)) then
127  do i=1, this%nfields
128  call this%fields(i)%ptr%free()
129  deallocate(this%fields(i)%ptr)
130  end do
131 
132  deallocate(this%fields)
133  deallocate(this%inuse)
134  end if
135 
136  nullify(this%dof)
137 
138  end subroutine scratch_registry_free
139 
140 
142  pure function get_nfields(this) result(n)
143  class(scratch_registry_t), intent(in) :: this
144  integer :: n
145 
146  n = this%nfields
147  end function get_nfields
148 
149  pure function get_nfields_inuse(this) result(n)
150  class(scratch_registry_t), intent(in) :: this
151  integer :: n, i
152 
153  n = 0
154  do i=1,this%get_size()
155  if (this%inuse(i)) n = n + 1
156  end do
157  end function get_nfields_inuse
158 
160  pure function get_size(this) result(n)
161  class(scratch_registry_t), intent(in) :: this
162  integer :: n
163 
164  n = size(this%fields)
165  end function get_size
166 
168  pure function get_expansion_size(this) result(n)
169  class(scratch_registry_t), intent(in) :: this
170  integer :: n
171 
172  n = this%expansion_size
173  end function get_expansion_size
174 
175  subroutine expand(this)
176  class(scratch_registry_t), intent(inout) :: this
177  type(field_ptr_t), allocatable :: temp(:)
178  logical, allocatable :: temp2(:)
179  integer :: i
180 
181  allocate(temp(this%get_size() + this%expansion_size))
182  temp(1:this%nfields) = this%fields(1:this%nfields)
183 
184  do i=this%nfields +1, size(temp)
185  allocate(temp(i)%ptr)
186  enddo
187 
188  call move_alloc(temp, this%fields)
189 
190  allocate(temp2(this%get_size() + this%expansion_size))
191  temp2(1:this%nfields) = this%inuse(1:this%nfields)
192  temp2(this%nfields+1:) = .false.
193  this%inuse = temp2
194  end subroutine expand
195 
196 
198  subroutine request_field(this, f, index)
199  class(scratch_registry_t), target, intent(inout) :: this
200  type(field_t), pointer, intent(inout) :: f
201  integer, intent(inout) :: index
202  character(len=10) :: name
203 
204 
205  associate(nfields => this%nfields, nfields_inuse => this%nfields_inuse)
206 
207  do index=1,this%get_size()
208  if (this%inuse(index) .eqv. .false.) then
209  write (name, "(A3,I0.3)") "wrk", index
210 
211  if (.not. allocated(this%fields(index)%ptr%x)) then
212  call this%fields(index)%ptr%init(this%dof, trim(name))
213  nfields = nfields + 1
214  end if
215  f => this%fields(index)%ptr
216  this%inuse(index) = .true.
217  this%nfields_inuse = this%nfields_inuse + 1
218  return
219  end if
220  end do
221  ! all existing fields in use, we need to expand to add a new one
222  index = nfields +1
223  call this%expand()
224  nfields = nfields + 1
225  nfields_inuse = nfields_inuse + 1
226  this%inuse(nfields) = .true.
227  write (name, "(A3,I0.3)") "wrk", index
228  call this%fields(nfields)%ptr%init(this%dof, trim(name))
229  f => this%fields(nfields)%ptr
230 
231  end associate
232  end subroutine request_field
233 
235  subroutine relinquish_field_single(this, index)
236  class(scratch_registry_t), target, intent(inout) :: this
237  integer, intent(inout) :: index
238 
239  this%inuse(index) = .false.
240  this%nfields_inuse = this%nfields_inuse - 1
241  end subroutine relinquish_field_single
242 
243  subroutine relinquish_field_multiple(this, indices)
244  class(scratch_registry_t), target, intent(inout) :: this
245  integer, intent(inout) :: indices(:)
246  integer :: i
247 
248  do i=1, size(indices)
249  this%inuse(indices(i)) = .false.
250  end do
251  this%nfields_inuse = this%nfields_inuse - size(indices)
252  end subroutine relinquish_field_multiple
253 
254  logical function get_inuse(this, index)
255  class(scratch_registry_t), target, intent(inout) :: this
256  integer, intent(inout) :: index
257 
258  get_inuse = this%inuse(index)
259  end function get_inuse
260 
261 end module scratch_registry
Defines a mapping of the degrees of freedom.
Definition: dofmap.f90:35
Defines a field.
Definition: field.f90:34
Defines a registry for storing and requesting temporary fields This can be used when you have a funct...
logical function get_inuse(this, index)
pure integer function get_nfields_inuse(this)
subroutine scratch_registry_free(this)
Destructor.
type(scratch_registry_t) function init(dof, size, expansion_size)
Constructor, optionally taking initial registry and expansion size as argument.
subroutine relinquish_field_single(this, index)
Relinquish the use of a field in the registry.
pure integer function get_size(this)
Get the size of the fields array.
subroutine relinquish_field_multiple(this, indices)
type(scratch_registry_t), target, public neko_scratch_registry
Global scratch registry.
subroutine request_field(this, f, index)
Get a field from the registry by assigning it to a pointer.
subroutine expand(this)
pure integer function get_nfields(this)
Get the number of fields stored in the registry.
pure integer function get_expansion_size(this)
Get the expansion size.
field_ptr_t, To easily obtain a pointer to a field
Definition: field.f90:80