Neko 1.99.3
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 integer :: i, n
248
249 n = this%get_size()
250
251 if (n .gt. 0) then
252 call move_alloc(this%entries, temp)
253 call move_alloc(this%inuse, temp2)
254 end if
255
256 allocate(this%entries(n + this%expansion_size))
257 allocate(this%inuse(n + this%expansion_size), source = .false.)
258
259 if (n .gt. 0) then
260 do i = 1, n
261 call this%entries(i)%move_from(temp(i))
262 this%inuse(i) = temp2(i)
263 call temp(i)%free()
264 end do
265 end if
266
267 if (allocated(temp)) deallocate(temp)
268 if (allocated(temp2)) deallocate(temp2)
269
270 end subroutine expand
271
276 subroutine request_field(this, f, index, clear)
277 class(scratch_registry_t), target, intent(inout) :: this
278 type(field_t), pointer, intent(inout) :: f
279 integer, intent(inout) :: index
280 logical, intent(in) :: clear
281 character(len=10) :: name
282
283 if (.not. associated(this%dof)) then
284 call neko_error("scratch_registry::request_field: "&
285 // "No dofmap assigned to scratch registry.")
286 end if
287
288 associate(n_entries => this%n_entries, n_inuse => this%n_inuse)
289
290 do index = 1, this%get_size()
291 if (.not. this%inuse(index)) then
292
293 if (.not. this%entries(index)%is_allocated()) then
294 write(name, "(A3,I0.3)") "wrk", index
295 call this%entries(index)%init_field(this%dof, trim(name))
296 n_entries = n_entries + 1
297 else if (this%entries(index)%get_type() .ne. 'field') then
298 cycle
299 end if
300
301 f => this%entries(index)%get_field()
302 if (clear) call field_rzero(f)
303 this%inuse(index) = .true.
304 this%n_inuse = this%n_inuse + 1
305 return
306 end if
307 end do
308
309 ! all existing fields in use, we need to expand to add a new one
310 index = n_entries + 1
311 call this%expand()
312 n_entries = n_entries + 1
313 n_inuse = n_inuse + 1
314 this%inuse(n_entries) = .true.
315 write (name, "(A3,I0.3)") "wrk", index
316 call this%entries(n_entries)%init_field(this%dof, trim(name))
317 f => this%entries(n_entries)%get_field()
318
319 end associate
320 end subroutine request_field
321
327 subroutine request_vector(this, v, index, n, clear)
328 class(scratch_registry_t), target, intent(inout) :: this
329 type(vector_t), pointer, intent(inout) :: v
330 integer, intent(inout) :: index
331 integer, intent(in) :: n
332 logical, intent(in) :: clear
333
334 associate(n_entries => this%n_entries, n_inuse => this%n_inuse)
335
336 do index = 1, this%get_size()
337 if (.not. this%inuse(index)) then
338
339 if (.not. this%entries(index)%is_allocated()) then
340 call this%entries(index)%init_vector(n)
341 n_entries = n_entries + 1
342 else if (trim(this%entries(index)%get_type()) .ne. 'vector') then
343 cycle
344 end if
345
346 v => this%entries(index)%get_vector()
347 if (v%size() .ne. n) then
348 nullify(v)
349 cycle
350 end if
351
352 if (clear) call vector_rzero(v)
353 this%inuse(index) = .true.
354 this%n_inuse = this%n_inuse + 1
355 return
356 end if
357 end do
358
359 ! all existing vectors in use, we need to expand to add a new one
360 index = n_entries + 1
361 call this%expand()
362 n_entries = n_entries + 1
363 n_inuse = n_inuse + 1
364 this%inuse(n_entries) = .true.
365 call this%entries(n_entries)%init_vector(n)
366 v => this%entries(n_entries)%get_vector()
367
368 end associate
369 end subroutine request_vector
370
377 subroutine request_matrix(this, m, index, nrows, ncols, clear)
378 class(scratch_registry_t), target, intent(inout) :: this
379 type(matrix_t), pointer, intent(inout) :: m
380 integer, intent(inout) :: index
381 integer, intent(in) :: nrows, ncols
382 logical, intent(in) :: clear
383
384 associate(n_entries => this%n_entries, n_inuse => this%n_inuse)
385
386 do index = 1, this%get_size()
387 if (.not. this%inuse(index)) then
388
389 if (.not. this%entries(index)%is_allocated()) then
390 call this%entries(index)%init_matrix(nrows, ncols)
391 n_entries = n_entries + 1
392 else if (trim(this%entries(index)%get_type()) .ne. 'matrix') then
393 cycle
394 end if
395
396 m => this%entries(index)%get_matrix()
397 if (m%get_nrows() .ne. nrows .or. &
398 m%get_ncols() .ne. ncols) then
399 nullify(m)
400 cycle
401 end if
402
403 if (clear) call matrix_rzero(m)
404 this%inuse(index) = .true.
405 this%n_inuse = this%n_inuse + 1
406 return
407 end if
408 end do
409
410 ! all existing matrices in use, we need to expand to add a new one
411 index = n_entries + 1
412 call this%expand()
413 n_entries = n_entries + 1
414 n_inuse = n_inuse + 1
415 this%inuse(n_entries) = .true.
416 call this%entries(n_entries)%init_matrix(nrows, ncols)
417 m => this%entries(n_entries)%get_matrix()
418
419 end associate
420 end subroutine request_matrix
421
424 subroutine relinquish_field_single(this, index)
425 class(scratch_registry_t), target, intent(inout) :: this
426 integer, intent(inout) :: index
427
428 if (trim(this%entries(index)%get_type()) .ne. 'field') then
429 call neko_error("scratch_registry::relinquish_field_single: " &
430 // "Register entry is not a field.")
431 end if
432
433 this%inuse(index) = .false.
434 this%n_inuse = this%n_inuse - 1
435 end subroutine relinquish_field_single
436
439 subroutine relinquish_field_multiple(this, indices)
440 class(scratch_registry_t), target, intent(inout) :: this
441 integer, intent(inout) :: indices(:)
442 integer :: i
443
444 do i = 1, size(indices)
445 if (trim(this%entries(indices(i))%get_type()) .ne. 'field') then
446 call neko_error("scratch_registry::relinquish_field_single: " &
447 // "Register entry is not a field.")
448 end if
449
450 this%inuse(indices(i)) = .false.
451 end do
452 this%n_inuse = this%n_inuse - size(indices)
453 end subroutine relinquish_field_multiple
454
457 subroutine relinquish_vector_single(this, index)
458 class(scratch_registry_t), target, intent(inout) :: this
459 integer, intent(inout) :: index
460
461 if (trim(this%entries(index)%get_type()) .ne. 'vector') then
462 call neko_error("scratch_registry::relinquish_vector_single: " &
463 // "Register entry is not a vector.")
464 end if
465
466 this%inuse(index) = .false.
467 this%n_inuse = this%n_inuse - 1
468 end subroutine relinquish_vector_single
469
472 subroutine relinquish_vector_multiple(this, indices)
473 class(scratch_registry_t), target, intent(inout) :: this
474 integer, intent(inout) :: indices(:)
475 integer :: i
476
477 do i = 1, size(indices)
478 if (trim(this%entries(indices(i))%get_type()) .ne. 'vector') then
479 call neko_error("scratch_registry::relinquish_vector_single: " &
480 // "Register entry is not a vector.")
481 end if
482
483 this%inuse(indices(i)) = .false.
484 end do
485 this%n_inuse = this%n_inuse - size(indices)
486 end subroutine relinquish_vector_multiple
487
490 subroutine relinquish_matrix_single(this, index)
491 class(scratch_registry_t), target, intent(inout) :: this
492 integer, intent(inout) :: index
493
494 if (trim(this%entries(index)%get_type()) .ne. 'matrix') then
495 call neko_error("scratch_registry::relinquish_matrix_single: " &
496 // "Register entry is not a matrix.")
497 end if
498
499 this%inuse(index) = .false.
500 this%n_inuse = this%n_inuse - 1
501 end subroutine relinquish_matrix_single
502
505 subroutine relinquish_matrix_multiple(this, indices)
506 class(scratch_registry_t), target, intent(inout) :: this
507 integer, intent(inout) :: indices(:)
508 integer :: i
509
510 do i = 1, size(indices)
511 if (trim(this%entries(indices(i))%get_type()) .ne. 'matrix') then
512 call neko_error("scratch_registry::relinquish_matrix_single: " &
513 // "Register entry is not a matrix.")
514 end if
515
516 this%inuse(indices(i)) = .false.
517 end do
518 this%n_inuse = this%n_inuse - size(indices)
519 end subroutine relinquish_matrix_multiple
520
523 subroutine relinquish_single(this, index)
524 class(scratch_registry_t), target, intent(inout) :: this
525 integer, intent(inout) :: index
526
527 this%inuse(index) = .false.
528 this%n_inuse = this%n_inuse - 1
529 end subroutine relinquish_single
530
533 subroutine relinquish_multiple(this, indices)
534 class(scratch_registry_t), target, intent(inout) :: this
535 integer, intent(inout) :: indices(:)
536 integer :: i
537
538 do i = 1, size(indices)
539 this%inuse(indices(i)) = .false.
540 end do
541 this%n_inuse = this%n_inuse - size(indices)
542 end subroutine relinquish_multiple
543
544end 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 registries ...
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