Neko 1.99.3
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
bc_list.f90
Go to the documentation of this file.
1! Copyright (c) 2024-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!
34module bc_list
36 use num_types, only : rp
37 use field, only : field_t
39 use utils, only : neko_error
40 use, intrinsic :: iso_c_binding, only : c_ptr
41 use bc, only : bc_t, bc_ptr_t
42 use time_state, only : time_state_t
43 !$ use omp_lib
44 implicit none
45 private
46
49 type, public :: bc_list_t
50 ! The items of the list.
51 class(bc_ptr_t), allocatable, private :: items(:)
53 integer, private :: size_ = 0
56 integer, private :: capacity
57 contains
59 procedure, pass(this) :: init => bc_list_init
61 procedure, pass(this) :: free => bc_list_free
62
64 procedure, pass(this) :: append => bc_list_append
66 procedure, pass(this) :: get => bc_list_get
68 procedure, pass(this) :: get_by_name => bc_list_get_by_name
70 procedure, pass(this) :: get_by_zone_index => bc_list_get_by_zone_index
71
73 procedure, pass(this) :: is_empty => bc_list_is_empty
75 procedure, pass(this) :: strong => bc_list_strong
77 procedure :: size => bc_list_size
78
80 generic :: apply => apply_scalar, apply_vector, &
81 apply_scalar_device, apply_vector_device, &
82 apply_scalar_field, apply_vector_field
84 procedure, pass(this) :: apply_scalar => bc_list_apply_scalar_array
86 procedure, pass(this) :: apply_vector => bc_list_apply_vector_array
88 procedure, pass(this) :: apply_scalar_device => bc_list_apply_scalar_device
90 procedure, pass(this) :: apply_vector_device => bc_list_apply_vector_device
92 procedure, pass(this) :: apply_scalar_field => bc_list_apply_scalar_field
94 procedure, pass(this) :: apply_vector_field => bc_list_apply_vector_field
95 end type bc_list_t
96
97contains
98
101 subroutine bc_list_init(this, capacity)
102 class(bc_list_t), intent(inout), target :: this
103 integer, optional :: capacity
104 integer :: n
105
106 call this%free()
107
108 n = 1
109 if (present(capacity)) n = capacity
110
111 allocate(this%items(n))
112
113 this%size_ = 0
114 this%capacity = n
115
116 end subroutine bc_list_init
117
121 subroutine bc_list_free(this)
122 class(bc_list_t), intent(inout) :: this
123 integer :: i
124
125 if (allocated(this%items)) then
126 do i = 1, this%size_
127 this%items(i)%ptr => null()
128 end do
129
130 deallocate(this%items)
131 end if
132
133 this%size_ = 0
134 this%capacity = 0
135 end subroutine bc_list_free
136
140 subroutine bc_list_append(this, bc)
141 class(bc_list_t), intent(inout) :: this
142 class(bc_t), intent(inout), target :: bc
143 type(bc_ptr_t), allocatable :: tmp(:)
144
145 if (this%size_ .ge. this%capacity) then
146 this%capacity = this%capacity * 2
147 allocate(tmp(this%capacity))
148 tmp(1:this%size_) = this%items
149 call move_alloc(tmp, this%items)
150 end if
151
152 this%size_ = this%size_ + 1
153 this%items(this%size_)%ptr => bc
154
155 end subroutine bc_list_append
156
160 function bc_list_get(this, i) result(bc)
161 class(bc_list_t), intent(in) :: this
162 class(bc_t), pointer :: bc
163 integer, intent(in) :: i
164
165 if (i .lt. 1 .or. i .gt. this%size_) then
166 call neko_error("Index out of bounds in bc_list_get")
167 end if
168
169 bc => this%items(i)%ptr
170
171 end function bc_list_get
172
176 function bc_list_get_by_name(this, name) result(bc)
177 class(bc_list_t), intent(in) :: this
178 class(bc_t), pointer :: bc
179 character(len=*), intent(in) :: name
180 integer :: i
181
182 do i = 1, this%size_
183 if (this%items(i)%ptr%name .eq. trim(name)) then
184 bc => this%items(i)%ptr
185 return
186 end if
187 end do
188
189 ! If the function reaches this point, no item was found
190 call neko_error("Name not found in bc_list")
191
192 end function bc_list_get_by_name
193
197 function bc_list_get_by_zone_index(this, zone_index) result(bc)
198 class(bc_list_t), intent(in) :: this
199 class(bc_t), pointer :: bc
200 integer, intent(in) :: zone_index
201 integer :: i, j
202
203 do i = 1, this%size_
204 do j = 1, size(this%items(i)%ptr%zone_indices)
205 if (this%items(i)%ptr%zone_indices(j) == zone_index) then
206 bc => this%items(i)%ptr
207 return
208 end if
209 end do
210 end do
211
212 ! If the function reaches this point, no item was found
213 call neko_error("Zone index not found in bc_list")
214
215 end function bc_list_get_by_zone_index
216
224 subroutine bc_list_apply_scalar_array(this, x, n, time, strong, strm)
225 class(bc_list_t), intent(inout) :: this
226 integer, intent(in) :: n
227 real(kind=rp), intent(inout), dimension(n) :: x
228 type(time_state_t), intent(in), optional :: time
229 logical, intent(in), optional :: strong
230 type(c_ptr), intent(inout), optional :: strm
231 type(c_ptr) :: x_d
232 integer :: i
233
234 if (neko_bcknd_device .eq. 1) then
235
236 x_d = device_get_ptr(x)
237
238 call this%apply_scalar_device(x_d, time = time, &
239 strong = strong, strm = strm)
240 else
241 !$omp parallel
242 do i = 1, this%size_
243 call this%items(i)%ptr%apply_scalar(x, n, time = time, &
244 strong = strong)
245 end do
246 !$omp end parallel
247 end if
248 end subroutine bc_list_apply_scalar_array
249
259 subroutine bc_list_apply_vector_array(this, x, y, z, n, time, strong, strm)
260 class(bc_list_t), intent(inout) :: this
261 integer, intent(in) :: n
262 real(kind=rp), intent(inout), dimension(n) :: x
263 real(kind=rp), intent(inout), dimension(n) :: y
264 real(kind=rp), intent(inout), dimension(n) :: z
265 type(time_state_t), intent(in), optional :: time
266 logical, intent(in), optional :: strong
267 type(c_ptr), intent(inout), optional :: strm
268 type(c_ptr) :: x_d
269 type(c_ptr) :: y_d
270 type(c_ptr) :: z_d
271 integer :: i
272
273 if (neko_bcknd_device .eq. 1) then
274
275 x_d = device_get_ptr(x)
276 y_d = device_get_ptr(y)
277 z_d = device_get_ptr(z)
278
279 call this%apply_vector_device(x_d, y_d, z_d, time = time, &
280 strong = strong, strm = strm)
281 else
282 !$omp parallel
283 do i = 1, this%size_
284 call this%items(i)%ptr%apply_vector(x, y, z, n, time = time, &
285 strong = strong)
286 end do
287 !$omp end parallel
288 end if
289
290 end subroutine bc_list_apply_vector_array
291
298 subroutine bc_list_apply_scalar_device(this, x_d, time, strong, strm)
299 class(bc_list_t), intent(inout) :: this
300 type(c_ptr), intent(inout) :: x_d
301 type(time_state_t), intent(in), optional :: time
302 logical, intent(in), optional :: strong
303 type(c_ptr), intent(inout), optional :: strm
304 type(c_ptr) :: strm_
305 integer :: i
306
307 if (present(strm)) then
308 strm_ = strm
309 else
310 strm_ = glb_cmd_queue
311 end if
312
313 do i = 1, this%size_
314 call this%items(i)%ptr%apply_scalar_dev(x_d, time = time, &
315 strong = strong, strm = strm_)
316 end do
317
318 end subroutine bc_list_apply_scalar_device
319
328 subroutine bc_list_apply_vector_device(this, x_d, y_d, z_d, time, strong, &
329 strm)
330 class(bc_list_t), intent(inout) :: this
331 type(c_ptr), intent(inout) :: x_d
332 type(c_ptr), intent(inout) :: y_d
333 type(c_ptr), intent(inout) :: z_d
334 type(time_state_t), intent(in), optional :: time
335 logical, intent(in), optional :: strong
336 type(c_ptr), intent(inout), optional :: strm
337 type(c_ptr) :: strm_
338 integer :: i
339
340 if (present(strm)) then
341 strm_ = strm
342 else
343 strm_ = glb_cmd_queue
344 end if
345
346 do i = 1, this%size_
347 call this%items(i)%ptr%apply_vector_dev(x_d, y_d, z_d, time = time, &
348 strong = strong, strm = strm_)
349 end do
350
351 end subroutine bc_list_apply_vector_device
352
359 subroutine bc_list_apply_scalar_field(this, x, time, strong, strm)
360 class(bc_list_t), intent(inout) :: this
361 type(field_t), intent(inout) :: x
362 type(time_state_t), intent(in), optional :: time
363 logical, intent(in), optional :: strong
364 type(c_ptr), intent(inout), optional :: strm
365 integer :: i
366
367 !$omp parallel if (.not. omp_in_parallel())
368 do i = 1, this%size_
369 call this%items(i)%ptr%apply_scalar_generic(x, time = time, &
370 strong = strong, strm = strm)
371 end do
372 !$omp end parallel
373
374 end subroutine bc_list_apply_scalar_field
375
384 subroutine bc_list_apply_vector_field(this, x, y, z, time, strong, strm)
385 class(bc_list_t), intent(inout) :: this
386 type(field_t), intent(inout) :: x
387 type(field_t), intent(inout) :: y
388 type(field_t), intent(inout) :: z
389 type(time_state_t), intent(in), optional :: time
390 logical, intent(in), optional :: strong
391 type(c_ptr), intent(inout), optional :: strm
392 integer :: i
393
394 !$omp parallel if (.not. omp_in_parallel())
395 do i = 1, this%size_
396 call this%items(i)%ptr%apply_vector_generic(x, y, z, time = time, &
397 strong = strong, strm = strm)
398 end do
399 !$omp end parallel
400
401 end subroutine bc_list_apply_vector_field
402
404 pure function bc_list_strong(this, i) result(strong)
405 class(bc_list_t), intent(in), target :: this
406 integer, intent(in) :: i
407 logical :: strong
408
409 strong = this%items(i)%ptr%strong
410 end function bc_list_strong
411
413 function bc_list_is_empty(this) result(is_empty)
414 class(bc_list_t), intent(in), target :: this
415 logical :: is_empty
416 integer :: i
417
418 is_empty = .true.
419 do i = 1, this%size_
420
421 if (.not. allocated(this%items(i)%ptr%msk)) then
422 call neko_error("bc not finalized, error in bc_list%is_empty")
423 end if
424
425 if (this%items(i)%ptr%msk(0) > 0) is_empty = .false.
426
427 end do
428 end function bc_list_is_empty
429
431 pure function bc_list_size(this) result(size)
432 class(bc_list_t), intent(in), target :: this
433 integer :: size
434
435 size = this%size_
436 end function bc_list_size
437
438end module bc_list
Return the device pointer for an associated Fortran array.
Definition device.F90:107
Defines a list of bc_t.
Definition bc_list.f90:34
pure logical function bc_list_strong(this, i)
Return whether the bc is strong or not.
Definition bc_list.f90:405
subroutine bc_list_apply_vector_array(this, x, y, z, n, time, strong, strm)
Apply a list of boundary conditions to a vector field.
Definition bc_list.f90:260
subroutine bc_list_apply_vector_device(this, x_d, y_d, z_d, time, strong, strm)
Apply a list of boundary conditions to a vector field on the device.
Definition bc_list.f90:330
class(bc_t) function, pointer bc_list_get(this, i)
Get the item at the given index.
Definition bc_list.f90:161
subroutine bc_list_apply_scalar_array(this, x, n, time, strong, strm)
Apply a list of boundary conditions to a scalar field.
Definition bc_list.f90:225
subroutine bc_list_apply_scalar_device(this, x_d, time, strong, strm)
Apply a list of boundary conditions to a scalar field on the device.
Definition bc_list.f90:299
pure integer function bc_list_size(this)
Return the number of items in the list.
Definition bc_list.f90:432
subroutine bc_list_append(this, bc)
Append a condition to the end of the list.
Definition bc_list.f90:141
subroutine bc_list_init(this, capacity)
Constructor.
Definition bc_list.f90:102
class(bc_t) function, pointer bc_list_get_by_name(this, name)
Get the item from a given name.
Definition bc_list.f90:177
subroutine bc_list_apply_vector_field(this, x, y, z, time, strong, strm)
Apply a list of boundary conditions to a vector field.
Definition bc_list.f90:385
subroutine bc_list_free(this)
Destructor.
Definition bc_list.f90:122
class(bc_t) function, pointer bc_list_get_by_zone_index(this, zone_index)
Get the item from zone_index.
Definition bc_list.f90:198
subroutine bc_list_apply_scalar_field(this, x, time, strong, strm)
Apply a list of boundary conditions to a scalar field.
Definition bc_list.f90:360
logical function bc_list_is_empty(this)
Return whether the list is empty.
Definition bc_list.f90:414
Defines a boundary condition.
Definition bc.f90:34
Device abstraction, common interface for various accelerators.
Definition device.F90:34
type(c_ptr), bind(C), public glb_cmd_queue
Global command queue.
Definition device.F90:51
Defines a field.
Definition field.f90:34
Build configurations.
integer, parameter neko_bcknd_device
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12
Module with things related to the simulation time.
Utilities.
Definition utils.f90:35
Pointer to a `bc_t`.
Definition bc.f90:133
Base type for a boundary condition.
Definition bc.f90:62
A list of allocatable `bc_t`. Follows the standard interface of lists.
Definition bc_list.f90:49
A struct that contains all info about the time, expand as needed.