Neko 1.99.2
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
scratch_registry.f90
Go to the documentation of this file.
1! Copyright (c) 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!
39 use field, only : field_t
40 use vector, only : vector_t
41 use matrix, only : matrix_t
42
43 use field_math, only : field_rzero
44 use vector_math, only : vector_rzero
45 use matrix_math, only : matrix_rzero
46
47 use dofmap, only : dofmap_t
48 use utils, only : neko_error
49 implicit none
50 private
51
52 type, public :: scratch_registry_t
54 type(registry_entry_t), private, allocatable :: entries(:)
56 logical, private, allocatable :: inuse(:)
58 integer, private :: n_entries = 0
60 integer, private :: n_inuse = 0
62 integer, private :: expansion_size = 10
64 type(dofmap_t), pointer :: dof => null()
65 contains
66 procedure, private, pass(this) :: expand
68 procedure, pass(this) :: init => scratch_registry_init
70 procedure, pass(this) :: free => scratch_registry_free
72 procedure, pass(this) :: set_dofmap => scratch_registry_set_dofmap
74 procedure, pass(this) :: get_n_entries
76 procedure, pass(this) :: get_n_inuse
78 procedure, pass(this) :: get_expansion_size
80 procedure, pass(this) :: get_size
82 procedure, pass(this) :: get_inuse
83
85 procedure, pass(this) :: request_field
86 procedure, pass(this) :: relinquish_field_single
87 procedure, pass(this) :: relinquish_field_multiple
89 generic :: relinquish_field => relinquish_field_single, &
91
93 procedure, pass(this) :: request_vector
94 procedure, pass(this) :: relinquish_vector_single
95 procedure, pass(this) :: relinquish_vector_multiple
97 generic :: relinquish_vector => relinquish_vector_single, &
99
101 procedure, pass(this) :: request_matrix
102 procedure, pass(this) :: relinquish_matrix_single
103 procedure, pass(this) :: relinquish_matrix_multiple
105 generic :: relinquish_matrix => relinquish_matrix_single, &
107
110 procedure, pass(this) :: relinquish_single
111 procedure, pass(this) :: relinquish_multiple
113 generic :: relinquish => relinquish_single, relinquish_multiple
114 end type scratch_registry_t
115
118
119contains
120
129 subroutine scratch_registry_init(this, size, expansion_size, dof)
130 class(scratch_registry_t), intent(inout) :: this
131 integer, optional, intent(in) :: size
132 integer, optional, intent(in) :: expansion_size
133 type(dofmap_t), target, intent(in), optional :: dof
134 integer :: s
135
136 call this%free()
137
138 s = 10
139 if (present(size)) s = size
140 if (present(dof)) this%dof => dof
141
142 allocate(this%entries(s))
143 allocate(this%inuse(s))
144 this%inuse(:) = .false.
145
146 this%expansion_size = 10
147 if (present(expansion_size)) this%expansion_size = expansion_size
148
149 end subroutine scratch_registry_init
150
152 subroutine scratch_registry_free(this)
153 class(scratch_registry_t), intent(inout):: this
154 integer :: i
155
156 if (allocated(this%inuse)) then
157 if(any(this%inuse)) then
158 call neko_error("scratch_registry::free: "&
159 // "Cannot free scratch registry with in-use entries.")
160 end if
161 deallocate(this%inuse)
162 end if
163
164 if (allocated(this%entries)) then
165 do i = 1, this%n_entries
166 call this%entries(i)%free()
167 end do
168
169 deallocate(this%entries)
170 end if
171
172 if (associated(this%dof)) nullify(this%dof)
173
174 ! Reset to default values
175 this%n_entries = 0
176 this%n_inuse = 0
177 this%expansion_size = 10
178
179 end subroutine scratch_registry_free
180
185 subroutine scratch_registry_set_dofmap(this, dof)
186 class(scratch_registry_t), intent(inout) :: this
187 type(dofmap_t), target, intent(in) :: dof
188
189 if (associated(this%dof, dof)) then
190 return
191 else if (associated(this%dof)) then
192 call neko_error("scratch_registry::set_dofmap: "&
193 // "Dofmap is already assigned to scratch registry.")
194 end if
195
196 this%dof => dof
197 end subroutine scratch_registry_set_dofmap
198
200 pure function get_n_entries(this) result(n)
201 class(scratch_registry_t), intent(in) :: this
202 integer :: n
203
204 n = this%n_entries
205 end function get_n_entries
206
208 pure function get_n_inuse(this) result(n)
209 class(scratch_registry_t), intent(in) :: this
210 integer :: n, i
211
212 n = count(this%inuse)
213 end function get_n_inuse
214
216 pure function get_size(this) result(n)
217 class(scratch_registry_t), intent(in) :: this
218 integer :: n
219
220 if (allocated(this%entries)) then
221 n = size(this%entries)
222 else
223 n = 0
224 end if
225 end function get_size
226
228 pure function get_expansion_size(this) result(n)
229 class(scratch_registry_t), intent(in) :: this
230 integer :: n
231
232 n = this%expansion_size
233 end function get_expansion_size
234
236 pure logical function get_inuse(this, index)
237 class(scratch_registry_t), target, intent(in) :: this
238 integer, intent(in) :: index
239
240 get_inuse = this%inuse(index)
241 end function get_inuse
242
243 subroutine expand(this)
244 class(scratch_registry_t), intent(inout) :: this
245 type(registry_entry_t), allocatable :: temp(:)
246 logical, allocatable :: temp2(:)
247
248 allocate(temp(this%get_size() + this%expansion_size))
249 temp(1:this%n_entries) = this%entries(1:this%n_entries)
250
251 call move_alloc(temp, this%entries)
252
253 allocate(temp2(this%get_size() + this%expansion_size))
254 temp2(1:this%n_entries) = this%inuse(1:this%n_entries)
255 temp2(this%n_entries+1:) = .false.
256 this%inuse = temp2
257 end subroutine expand
258
263 subroutine request_field(this, f, index, clear)
264 class(scratch_registry_t), target, intent(inout) :: this
265 type(field_t), pointer, intent(inout) :: f
266 integer, intent(inout) :: index
267 logical, intent(in) :: clear
268 character(len=10) :: name
269
270 if (.not. associated(this%dof)) then
271 call neko_error("scratch_registry::request_field: "&
272 // "No dofmap assigned to scratch registry.")
273 end if
274
275 associate(n_entries => this%n_entries, n_inuse => this%n_inuse)
276
277 do index = 1, this%get_size()
278 if (.not. this%inuse(index)) then
279
280 if (.not. this%entries(index)%is_allocated()) then
281 write(name, "(A3,I0.3)") "wrk", index
282 call this%entries(index)%init_field(this%dof, trim(name))
283 n_entries = n_entries + 1
284 else if (this%entries(index)%get_type() .ne. 'field') then
285 cycle
286 end if
287
288 f => this%entries(index)%get_field()
289 if (clear) call field_rzero(f)
290 this%inuse(index) = .true.
291 this%n_inuse = this%n_inuse + 1
292 return
293 end if
294 end do
295
296 ! all existing fields in use, we need to expand to add a new one
297 index = n_entries + 1
298 call this%expand()
299 n_entries = n_entries + 1
300 n_inuse = n_inuse + 1
301 this%inuse(n_entries) = .true.
302 write (name, "(A3,I0.3)") "wrk", index
303 call this%entries(n_entries)%init_field(this%dof, trim(name))
304 f => this%entries(n_entries)%get_field()
305
306 end associate
307 end subroutine request_field
308
314 subroutine request_vector(this, v, index, n, clear)
315 class(scratch_registry_t), target, intent(inout) :: this
316 type(vector_t), pointer, intent(inout) :: v
317 integer, intent(inout) :: index
318 integer, intent(in) :: n
319 logical, intent(in) :: clear
320
321 associate(n_entries => this%n_entries, n_inuse => this%n_inuse)
322
323 do index = 1, this%get_size()
324 if (.not. this%inuse(index)) then
325
326 if (.not. this%entries(index)%is_allocated()) then
327 call this%entries(index)%init_vector(n)
328 n_entries = n_entries + 1
329 else if (trim(this%entries(index)%get_type()) .ne. 'vector') then
330 cycle
331 end if
332
333 v => this%entries(index)%get_vector()
334 if (v%size() .ne. n) then
335 nullify(v)
336 cycle
337 end if
338
339 if (clear) call vector_rzero(v)
340 this%inuse(index) = .true.
341 this%n_inuse = this%n_inuse + 1
342 return
343 end if
344 end do
345
346 ! all existing vectors in use, we need to expand to add a new one
347 index = n_entries + 1
348 call this%expand()
349 n_entries = n_entries + 1
350 n_inuse = n_inuse + 1
351 this%inuse(n_entries) = .true.
352 call this%entries(n_entries)%init_vector(n)
353 v => this%entries(n_entries)%get_vector()
354
355 end associate
356 end subroutine request_vector
357
364 subroutine request_matrix(this, m, index, nrows, ncols, clear)
365 class(scratch_registry_t), target, intent(inout) :: this
366 type(matrix_t), pointer, intent(inout) :: m
367 integer, intent(inout) :: index
368 integer, intent(in) :: nrows, ncols
369 logical, intent(in) :: clear
370
371 associate(n_entries => this%n_entries, n_inuse => this%n_inuse)
372
373 do index = 1, this%get_size()
374 if (.not. this%inuse(index)) then
375
376 if (.not. this%entries(index)%is_allocated()) then
377 call this%entries(index)%init_matrix(nrows, ncols)
378 n_entries = n_entries + 1
379 else if (trim(this%entries(index)%get_type()) .ne. 'matrix') then
380 cycle
381 end if
382
383 m => this%entries(index)%get_matrix()
384 if (m%get_nrows() .ne. nrows .or. &
385 m%get_ncols() .ne. ncols) then
386 nullify(m)
387 cycle
388 end if
389
390 if (clear) call matrix_rzero(m)
391 this%inuse(index) = .true.
392 this%n_inuse = this%n_inuse + 1
393 return
394 end if
395 end do
396
397 ! all existing matrices in use, we need to expand to add a new one
398 index = n_entries + 1
399 call this%expand()
400 n_entries = n_entries + 1
401 n_inuse = n_inuse + 1
402 this%inuse(n_entries) = .true.
403 call this%entries(n_entries)%init_matrix(nrows, ncols)
404 m => this%entries(n_entries)%get_matrix()
405
406 end associate
407 end subroutine request_matrix
408
411 subroutine relinquish_field_single(this, index)
412 class(scratch_registry_t), target, intent(inout) :: this
413 integer, intent(inout) :: index
414
415 if (trim(this%entries(index)%get_type()) .ne. 'field') then
416 call neko_error("scratch_registry::relinquish_field_single: " &
417 // "Register entry is not a field.")
418 end if
419
420 this%inuse(index) = .false.
421 this%n_inuse = this%n_inuse - 1
422 end subroutine relinquish_field_single
423
426 subroutine relinquish_field_multiple(this, indices)
427 class(scratch_registry_t), target, intent(inout) :: this
428 integer, intent(inout) :: indices(:)
429 integer :: i
430
431 do i = 1, size(indices)
432 if (trim(this%entries(indices(i))%get_type()) .ne. 'field') then
433 call neko_error("scratch_registry::relinquish_field_single: " &
434 // "Register entry is not a field.")
435 end if
436
437 this%inuse(indices(i)) = .false.
438 end do
439 this%n_inuse = this%n_inuse - size(indices)
440 end subroutine relinquish_field_multiple
441
444 subroutine relinquish_vector_single(this, index)
445 class(scratch_registry_t), target, intent(inout) :: this
446 integer, intent(inout) :: index
447
448 if (trim(this%entries(index)%get_type()) .ne. 'vector') then
449 call neko_error("scratch_registry::relinquish_vector_single: " &
450 // "Register entry is not a vector.")
451 end if
452
453 this%inuse(index) = .false.
454 this%n_inuse = this%n_inuse - 1
455 end subroutine relinquish_vector_single
456
459 subroutine relinquish_vector_multiple(this, indices)
460 class(scratch_registry_t), target, intent(inout) :: this
461 integer, intent(inout) :: indices(:)
462 integer :: i
463
464 do i = 1, size(indices)
465 if (trim(this%entries(indices(i))%get_type()) .ne. 'vector') then
466 call neko_error("scratch_registry::relinquish_vector_single: " &
467 // "Register entry is not a vector.")
468 end if
469
470 this%inuse(indices(i)) = .false.
471 end do
472 this%n_inuse = this%n_inuse - size(indices)
473 end subroutine relinquish_vector_multiple
474
477 subroutine relinquish_matrix_single(this, index)
478 class(scratch_registry_t), target, intent(inout) :: this
479 integer, intent(inout) :: index
480
481 if (trim(this%entries(index)%get_type()) .ne. 'matrix') then
482 call neko_error("scratch_registry::relinquish_matrix_single: " &
483 // "Register entry is not a matrix.")
484 end if
485
486 this%inuse(index) = .false.
487 this%n_inuse = this%n_inuse - 1
488 end subroutine relinquish_matrix_single
489
492 subroutine relinquish_matrix_multiple(this, indices)
493 class(scratch_registry_t), target, intent(inout) :: this
494 integer, intent(inout) :: indices(:)
495 integer :: i
496
497 do i = 1, size(indices)
498 if (trim(this%entries(indices(i))%get_type()) .ne. 'matrix') then
499 call neko_error("scratch_registry::relinquish_matrix_single: " &
500 // "Register entry is not a matrix.")
501 end if
502
503 this%inuse(indices(i)) = .false.
504 end do
505 this%n_inuse = this%n_inuse - size(indices)
506 end subroutine relinquish_matrix_multiple
507
510 subroutine relinquish_single(this, index)
511 class(scratch_registry_t), target, intent(inout) :: this
512 integer, intent(inout) :: index
513
514 this%inuse(index) = .false.
515 this%n_inuse = this%n_inuse - 1
516 end subroutine relinquish_single
517
520 subroutine relinquish_multiple(this, indices)
521 class(scratch_registry_t), target, intent(inout) :: this
522 integer, intent(inout) :: indices(:)
523 integer :: i
524
525 do i = 1, size(indices)
526 this%inuse(indices(i)) = .false.
527 end do
528 this%n_inuse = this%n_inuse - size(indices)
529 end subroutine relinquish_multiple
530
531end module scratch_registry
Defines a mapping of the degrees of freedom.
Definition dofmap.f90:35
subroutine, public field_rzero(a, n)
Zero a real vector.
Defines a field.
Definition field.f90:34
subroutine, public matrix_rzero(a, n)
Zero a real matrix .
Defines a matrix.
Definition matrix.f90:34
Defines a registry entry for storing and requesting temporary objects This is used in the scratch reg...
Defines a registry for storing and requesting temporary objects This can be used when you have a func...
subroutine relinquish_matrix_single(this, index)
Relinquish the use of a matrix in the registry.
pure logical function get_inuse(this, index)
Get the inuse status for a given index.
pure integer function get_n_inuse(this)
Get the number of objects currently in use.
subroutine scratch_registry_free(this)
Destructor.
subroutine request_field(this, f, index, clear)
Get a field from the registry by assigning it to a pointer.
subroutine relinquish_matrix_multiple(this, indices)
Relinquish the use of multiple matrices in the registry.
pure integer function get_n_entries(this)
Get the number of objects stored in the registry.
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 objects array.
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.
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.
subroutine expand(this)
subroutine relinquish_vector_single(this, index)
Relinquish the use of a vector in the registry.
subroutine request_matrix(this, m, index, nrows, ncols, clear)
Get a matrix from the registry by assigning it to a pointer.
subroutine request_vector(this, v, index, n, clear)
Get a vector from the registry by assigning it to a pointer.
subroutine scratch_registry_init(this, size, expansion_size, dof)
Constructor, optionally taking initial registry and expansion size as argument.
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.
pure integer function get_expansion_size(this)
Get the expansion size.
Utilities.
Definition utils.f90:35
subroutine, public vector_rzero(a, n)
Zero a real vector.
Defines a vector.
Definition vector.f90:34