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 call move_alloc(temp2, this%inuse)
257
258 end subroutine expand
259
264 subroutine request_field(this, f, index, clear)
265 class(scratch_registry_t), target, intent(inout) :: this
266 type(field_t), pointer, intent(inout) :: f
267 integer, intent(inout) :: index
268 logical, intent(in) :: clear
269 character(len=10) :: name
270
271 if (.not. associated(this%dof)) then
272 call neko_error("scratch_registry::request_field: "&
273 // "No dofmap assigned to scratch registry.")
274 end if
275
276 associate(n_entries => this%n_entries, n_inuse => this%n_inuse)
277
278 do index = 1, this%get_size()
279 if (.not. this%inuse(index)) then
280
281 if (.not. this%entries(index)%is_allocated()) then
282 write(name, "(A3,I0.3)") "wrk", index
283 call this%entries(index)%init_field(this%dof, trim(name))
284 n_entries = n_entries + 1
285 else if (this%entries(index)%get_type() .ne. 'field') then
286 cycle
287 end if
288
289 f => this%entries(index)%get_field()
290 if (clear) call field_rzero(f)
291 this%inuse(index) = .true.
292 this%n_inuse = this%n_inuse + 1
293 return
294 end if
295 end do
296
297 ! all existing fields in use, we need to expand to add a new one
298 index = n_entries + 1
299 call this%expand()
300 n_entries = n_entries + 1
301 n_inuse = n_inuse + 1
302 this%inuse(n_entries) = .true.
303 write (name, "(A3,I0.3)") "wrk", index
304 call this%entries(n_entries)%init_field(this%dof, trim(name))
305 f => this%entries(n_entries)%get_field()
306
307 end associate
308 end subroutine request_field
309
315 subroutine request_vector(this, v, index, n, clear)
316 class(scratch_registry_t), target, intent(inout) :: this
317 type(vector_t), pointer, intent(inout) :: v
318 integer, intent(inout) :: index
319 integer, intent(in) :: n
320 logical, intent(in) :: clear
321
322 associate(n_entries => this%n_entries, n_inuse => this%n_inuse)
323
324 do index = 1, this%get_size()
325 if (.not. this%inuse(index)) then
326
327 if (.not. this%entries(index)%is_allocated()) then
328 call this%entries(index)%init_vector(n)
329 n_entries = n_entries + 1
330 else if (trim(this%entries(index)%get_type()) .ne. 'vector') then
331 cycle
332 end if
333
334 v => this%entries(index)%get_vector()
335 if (v%size() .ne. n) then
336 nullify(v)
337 cycle
338 end if
339
340 if (clear) call vector_rzero(v)
341 this%inuse(index) = .true.
342 this%n_inuse = this%n_inuse + 1
343 return
344 end if
345 end do
346
347 ! all existing vectors in use, we need to expand to add a new one
348 index = n_entries + 1
349 call this%expand()
350 n_entries = n_entries + 1
351 n_inuse = n_inuse + 1
352 this%inuse(n_entries) = .true.
353 call this%entries(n_entries)%init_vector(n)
354 v => this%entries(n_entries)%get_vector()
355
356 end associate
357 end subroutine request_vector
358
365 subroutine request_matrix(this, m, index, nrows, ncols, clear)
366 class(scratch_registry_t), target, intent(inout) :: this
367 type(matrix_t), pointer, intent(inout) :: m
368 integer, intent(inout) :: index
369 integer, intent(in) :: nrows, ncols
370 logical, intent(in) :: clear
371
372 associate(n_entries => this%n_entries, n_inuse => this%n_inuse)
373
374 do index = 1, this%get_size()
375 if (.not. this%inuse(index)) then
376
377 if (.not. this%entries(index)%is_allocated()) then
378 call this%entries(index)%init_matrix(nrows, ncols)
379 n_entries = n_entries + 1
380 else if (trim(this%entries(index)%get_type()) .ne. 'matrix') then
381 cycle
382 end if
383
384 m => this%entries(index)%get_matrix()
385 if (m%get_nrows() .ne. nrows .or. &
386 m%get_ncols() .ne. ncols) then
387 nullify(m)
388 cycle
389 end if
390
391 if (clear) call matrix_rzero(m)
392 this%inuse(index) = .true.
393 this%n_inuse = this%n_inuse + 1
394 return
395 end if
396 end do
397
398 ! all existing matrices in use, we need to expand to add a new one
399 index = n_entries + 1
400 call this%expand()
401 n_entries = n_entries + 1
402 n_inuse = n_inuse + 1
403 this%inuse(n_entries) = .true.
404 call this%entries(n_entries)%init_matrix(nrows, ncols)
405 m => this%entries(n_entries)%get_matrix()
406
407 end associate
408 end subroutine request_matrix
409
412 subroutine relinquish_field_single(this, index)
413 class(scratch_registry_t), target, intent(inout) :: this
414 integer, intent(inout) :: index
415
416 if (trim(this%entries(index)%get_type()) .ne. 'field') then
417 call neko_error("scratch_registry::relinquish_field_single: " &
418 // "Register entry is not a field.")
419 end if
420
421 this%inuse(index) = .false.
422 this%n_inuse = this%n_inuse - 1
423 end subroutine relinquish_field_single
424
427 subroutine relinquish_field_multiple(this, indices)
428 class(scratch_registry_t), target, intent(inout) :: this
429 integer, intent(inout) :: indices(:)
430 integer :: i
431
432 do i = 1, size(indices)
433 if (trim(this%entries(indices(i))%get_type()) .ne. 'field') then
434 call neko_error("scratch_registry::relinquish_field_single: " &
435 // "Register entry is not a field.")
436 end if
437
438 this%inuse(indices(i)) = .false.
439 end do
440 this%n_inuse = this%n_inuse - size(indices)
441 end subroutine relinquish_field_multiple
442
445 subroutine relinquish_vector_single(this, index)
446 class(scratch_registry_t), target, intent(inout) :: this
447 integer, intent(inout) :: index
448
449 if (trim(this%entries(index)%get_type()) .ne. 'vector') then
450 call neko_error("scratch_registry::relinquish_vector_single: " &
451 // "Register entry is not a vector.")
452 end if
453
454 this%inuse(index) = .false.
455 this%n_inuse = this%n_inuse - 1
456 end subroutine relinquish_vector_single
457
460 subroutine relinquish_vector_multiple(this, indices)
461 class(scratch_registry_t), target, intent(inout) :: this
462 integer, intent(inout) :: indices(:)
463 integer :: i
464
465 do i = 1, size(indices)
466 if (trim(this%entries(indices(i))%get_type()) .ne. 'vector') then
467 call neko_error("scratch_registry::relinquish_vector_single: " &
468 // "Register entry is not a vector.")
469 end if
470
471 this%inuse(indices(i)) = .false.
472 end do
473 this%n_inuse = this%n_inuse - size(indices)
474 end subroutine relinquish_vector_multiple
475
478 subroutine relinquish_matrix_single(this, index)
479 class(scratch_registry_t), target, intent(inout) :: this
480 integer, intent(inout) :: index
481
482 if (trim(this%entries(index)%get_type()) .ne. 'matrix') then
483 call neko_error("scratch_registry::relinquish_matrix_single: " &
484 // "Register entry is not a matrix.")
485 end if
486
487 this%inuse(index) = .false.
488 this%n_inuse = this%n_inuse - 1
489 end subroutine relinquish_matrix_single
490
493 subroutine relinquish_matrix_multiple(this, indices)
494 class(scratch_registry_t), target, intent(inout) :: this
495 integer, intent(inout) :: indices(:)
496 integer :: i
497
498 do i = 1, size(indices)
499 if (trim(this%entries(indices(i))%get_type()) .ne. 'matrix') then
500 call neko_error("scratch_registry::relinquish_matrix_single: " &
501 // "Register entry is not a matrix.")
502 end if
503
504 this%inuse(indices(i)) = .false.
505 end do
506 this%n_inuse = this%n_inuse - size(indices)
507 end subroutine relinquish_matrix_multiple
508
511 subroutine relinquish_single(this, index)
512 class(scratch_registry_t), target, intent(inout) :: this
513 integer, intent(inout) :: index
514
515 this%inuse(index) = .false.
516 this%n_inuse = this%n_inuse - 1
517 end subroutine relinquish_single
518
521 subroutine relinquish_multiple(this, indices)
522 class(scratch_registry_t), target, intent(inout) :: this
523 integer, intent(inout) :: indices(:)
524 integer :: i
525
526 do i = 1, size(indices)
527 this%inuse(indices(i)) = .false.
528 end do
529 this%n_inuse = this%n_inuse - size(indices)
530 end subroutine relinquish_multiple
531
532end 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