Neko  0.8.99
A portable framework for high-order spectral element flow simulations
bc.f90
Go to the documentation of this file.
1 ! Copyright (c) 2020-2024, 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 !
34 module bc
35  use neko_config
36  use num_types
37  use device
38  use dofmap, only : dofmap_t
39  use coefs, only : coef_t
40  use space, only : space_t
42  use facet_zone, only : facet_zone_t
43  use stack, only : stack_i4t2_t
44  use tuple, only : tuple_i4_t
46  use, intrinsic :: iso_c_binding, only : c_ptr, c_null_ptr
47  implicit none
48  private
49 
51  type, public, abstract :: bc_t
53  integer, allocatable :: msk(:)
55  integer, allocatable :: facet(:)
57  type(dofmap_t), pointer :: dof
59  type(coef_t), pointer :: coef
61  type(mesh_t), pointer :: msh
63  type(space_t), pointer :: xh
65  type(stack_i4t2_t) :: marked_facet
67  type(c_ptr) :: msk_d = c_null_ptr
69  type(c_ptr) :: facet_d = c_null_ptr
70  contains
72  procedure, pass(this) :: init_base => bc_init_base
74  procedure, pass(this) :: free_base => bc_free_base
76  procedure, pass(this) :: mark_facet => bc_mark_facet
78  procedure, pass(this) :: mark_facets => bc_mark_facets
80  procedure, pass(this) :: mark_zones_from_list => bc_mark_zones_from_list
82  procedure, pass(this) :: mark_zone => bc_mark_zone
85  procedure, pass(this) :: finalize => bc_finalize
87  procedure(bc_apply_scalar), pass(this), deferred :: apply_scalar
89  procedure(bc_apply_vector), pass(this), deferred :: apply_vector
91  procedure(bc_apply_scalar_dev), pass(this), deferred :: apply_scalar_dev
93  procedure(bc_apply_vector_dev), pass(this), deferred :: apply_vector_dev
95  procedure(bc_destructor), pass(this), deferred :: free
96  end type bc_t
97 
99  type, private :: bcp_t
100  class(bc_t), pointer :: bcp
101  end type bcp_t
102 
104  type, public :: bc_list_t
105  type(bcp_t), allocatable :: bc(:)
107  integer :: n
109  integer :: size
110  end type bc_list_t
111 
112  abstract interface
113 
118  subroutine bc_apply_scalar(this, x, n, t, tstep)
119  import :: bc_t
120  import :: rp
121  class(bc_t), intent(inout) :: this
122  integer, intent(in) :: n
123  real(kind=rp), intent(inout), dimension(n) :: x
124  real(kind=rp), intent(in), optional :: t
125  integer, intent(in), optional :: tstep
126  end subroutine bc_apply_scalar
127  end interface
128 
129  abstract interface
130 
137  subroutine bc_apply_vector(this, x, y, z, n, t, tstep)
138  import :: bc_t
139  import :: rp
140  class(bc_t), intent(inout) :: this
141  integer, intent(in) :: n
142  real(kind=rp), intent(inout), dimension(n) :: x
143  real(kind=rp), intent(inout), dimension(n) :: y
144  real(kind=rp), intent(inout), dimension(n) :: z
145  real(kind=rp), intent(in), optional :: t
146  integer, intent(in), optional :: tstep
147  end subroutine bc_apply_vector
148  end interface
149 
150  abstract interface
151 
152  subroutine bc_destructor(this)
153  import :: bc_t
154  class(bc_t), intent(inout), target :: this
155  end subroutine bc_destructor
156  end interface
157 
158  abstract interface
159 
161  subroutine bc_apply_scalar_dev(this, x_d, t, tstep)
162  import :: c_ptr
163  import :: bc_t
164  import :: rp
165  class(bc_t), intent(inout), target :: this
166  type(c_ptr) :: x_d
167  real(kind=rp), intent(in), optional :: t
168  integer, intent(in), optional :: tstep
169  end subroutine bc_apply_scalar_dev
170  end interface
171 
172  abstract interface
173 
177  subroutine bc_apply_vector_dev(this, x_d, y_d, z_d, t, tstep)
178  import :: c_ptr
179  import :: bc_t
180  import :: rp
181  class(bc_t), intent(inout), target :: this
182  type(c_ptr) :: x_d
183  type(c_ptr) :: y_d
184  type(c_ptr) :: z_d
185  real(kind=rp), intent(in), optional :: t
186  integer, intent(in), optional :: tstep
187  end subroutine bc_apply_vector_dev
188  end interface
189 
190  interface bc_list_apply
192  end interface bc_list_apply
193 
194  public :: bc_list_init, bc_list_free, bc_list_add, &
196 
197 contains
198 
201  subroutine bc_init_base(this, coef)
202  class(bc_t), intent(inout) :: this
203  type(coef_t), target, intent(in) :: coef
204 
205  call this%free_base
206 
207  this%dof => coef%dof
208  this%coef => coef
209  this%Xh => this%dof%Xh
210  this%msh => this%dof%msh
211 
212  call this%marked_facet%init()
213 
214  end subroutine bc_init_base
215 
217  subroutine bc_free_base(this)
218  class(bc_t), intent(inout) :: this
219 
220  call this%marked_facet%free()
221 
222  nullify(this%Xh)
223  nullify(this%msh)
224  nullify(this%dof)
225  nullify(this%coef)
226 
227  if (allocated(this%msk)) then
228  deallocate(this%msk)
229  end if
230 
231  if (allocated(this%facet)) then
232  deallocate(this%facet)
233  end if
234 
235  if (c_associated(this%msk_d)) then
236  call device_free(this%msk_d)
237  this%msk_d = c_null_ptr
238  end if
239 
240  if (c_associated(this%facet_d)) then
241  call device_free(this%facet_d)
242  this%facet_d = c_null_ptr
243  end if
244 
245  end subroutine bc_free_base
246 
250  subroutine bc_mark_facet(this, facet, el)
251  class(bc_t), intent(inout) :: this
252  integer, intent(in) :: facet
253  integer, intent(in) :: el
254  type(tuple_i4_t) :: t
255 
256  t%x = (/facet, el/)
257  call this%marked_facet%push(t)
258 
259  end subroutine bc_mark_facet
260 
263  subroutine bc_mark_facets(this, facet_list)
264  class(bc_t), intent(inout) :: this
265  type(stack_i4t2_t), intent(inout) :: facet_list
266  type(tuple_i4_t), pointer :: fp(:)
267  integer :: i
268 
269  fp => facet_list%array()
270  do i = 1, facet_list%size()
271  call this%marked_facet%push(fp(i))
272  end do
273 
274  end subroutine bc_mark_facets
275 
278  subroutine bc_mark_zone(this, bc_zone)
279  class(bc_t), intent(inout) :: this
280  class(facet_zone_t), intent(inout) :: bc_zone
281  integer :: i
282  do i = 1, bc_zone%size
283  call this%marked_facet%push(bc_zone%facet_el(i))
284  end do
285  end subroutine bc_mark_zone
286 
293  subroutine bc_mark_zones_from_list(this, bc_zones, bc_key, bc_labels)
294  class(bc_t), intent(inout) :: this
295  class(facet_zone_t), intent(inout) :: bc_zones(:)
296  character(len=*) :: bc_key
297  character(len=100), allocatable :: split_key(:)
298  character(len=NEKO_MSH_MAX_ZLBL_LEN) :: bc_labels(NEKO_MSH_MAX_ZLBLS)
299  integer :: i, j, k, l, msh_bc_type
300 
301  msh_bc_type = 0
302  if(trim(bc_key) .eq. 'o' .or. trim(bc_key) .eq. 'on' &
303  .or. trim(bc_key) .eq. 'o+dong' .or. trim(bc_key) .eq. 'on+dong') then
304  msh_bc_type = 1
305  else if(trim(bc_key) .eq. 'd_pres') then
306  msh_bc_type = 1
307  else if(trim(bc_key) .eq. 'w') then
308  msh_bc_type = 2
309  else if(trim(bc_key) .eq. 'v') then
310  msh_bc_type = 2
311  else if(trim(bc_key) .eq. 'd_vel_u') then
312  msh_bc_type = 2
313  else if(trim(bc_key) .eq. 'd_vel_v') then
314  msh_bc_type = 2
315  else if(trim(bc_key) .eq. 'd_vel_w') then
316  msh_bc_type = 2
317  else if(trim(bc_key) .eq. 'sym') then
318  msh_bc_type = 2
319  end if
320 
321  do i = 1, neko_msh_max_zlbls
322  !Check if several bcs are defined for this zone
323  !bcs are seperated by /, but we could use something else
324  if (index(trim(bc_labels(i)), '/') .eq. 0) then
325  if (trim(bc_key) .eq. trim(bc_labels(i))) then
326  call bc_mark_zone(this, bc_zones(i))
327  ! Loop across all faces in the mesh
328  do j = 1,this%msh%nelv
329  do k = 1, 2 * this%msh%gdim
330  if (this%msh%facet_type(k,j) .eq. -i) then
331  this%msh%facet_type(k,j) = msh_bc_type
332  end if
333  end do
334  end do
335  end if
336  else
337  split_key = split_string(trim(bc_labels(i)),'/')
338  do l = 1, size(split_key)
339  if (trim(split_key(l)) .eq. trim(bc_key)) then
340  call bc_mark_zone(this, bc_zones(i))
341  ! Loop across all faces in the mesh
342  do j = 1,this%msh%nelv
343  do k = 1, 2 * this%msh%gdim
344  if (this%msh%facet_type(k,j) .eq. -i) then
345  this%msh%facet_type(k,j) = msh_bc_type
346  end if
347  end do
348  end do
349  end if
350  end do
351  end if
352  end do
353  end subroutine bc_mark_zones_from_list
354 
355 
359  subroutine bc_finalize(this)
360  class(bc_t), target, intent(inout) :: this
361  type(tuple_i4_t), pointer :: bfp(:)
362  type(tuple_i4_t) :: bc_facet
363  integer :: facet_size, facet, el
364  integer :: i, j, k, l, msk_c
365  integer :: lx, ly, lz, n
366 
367  lx = this%Xh%lx
368  ly = this%Xh%ly
369  lz = this%Xh%lz
370 
372 
373  ! Note we assume that lx = ly = lz
374  facet_size = lx**2
375  allocate(this%msk(0:facet_size * this%marked_facet%size()))
376  allocate(this%facet(0:facet_size * this%marked_facet%size()))
377 
378  msk_c = 0
379  bfp => this%marked_facet%array()
380 
381  ! Loop through each (facet, element) id tuple
382  ! Then loop over all the nodes of the face and compute their linear index
383  ! This index goes into this%msk, whereas the corresponding face id goes into
384  ! this%facet
385  do i = 1, this%marked_facet%size()
386  bc_facet = bfp(i)
387  facet = bc_facet%x(1)
388  el = bc_facet%x(2)
389  select case (facet)
390  case (1)
391  do l = 1, lz
392  do k = 1, ly
393  msk_c = msk_c + 1
394  this%msk(msk_c) = linear_index(1,k,l,el,lx,ly,lz)
395  this%facet(msk_c) = 1
396  end do
397  end do
398  case (2)
399  do l = 1, lz
400  do k = 1, ly
401  msk_c = msk_c + 1
402  this%msk(msk_c) = linear_index(lx,k,l,el,lx,ly,lz)
403  this%facet(msk_c) = 2
404  end do
405  end do
406  case(3)
407  do l = 1, lz
408  do j = 1, lx
409  msk_c = msk_c + 1
410  this%msk(msk_c) = linear_index(j,1,l,el,lx,ly,lz)
411  this%facet(msk_c) = 3
412  end do
413  end do
414  case(4)
415  do l = 1, lz
416  do j = 1, lx
417  msk_c = msk_c + 1
418  this%msk(msk_c) = linear_index(j,ly,l,el,lx,ly,lz)
419  this%facet(msk_c) = 4
420  end do
421  end do
422  case(5)
423  do k = 1, ly
424  do j = 1, lx
425  msk_c = msk_c + 1
426  this%msk(msk_c) = linear_index(j,k,1,el,lx,ly,lz)
427  this%facet(msk_c) = 5
428  end do
429  end do
430  case(6)
431  do k = 1, ly
432  do j = 1, lx
433  msk_c = msk_c + 1
434  this%msk(msk_c) = linear_index(j,k,lz,el,lx,ly,lz)
435  this%facet(msk_c) = 6
436  end do
437  end do
438  end select
439  end do
440 
441  this%msk(0) = msk_c
442  this%facet(0) = msk_c
443 
444  if (neko_bcknd_device .eq. 1) then
445  n = facet_size * this%marked_facet%size() + 1
446  call device_map(this%msk, this%msk_d, n)
447  call device_map(this%facet, this%facet_d, n)
448 
449  call device_memcpy(this%msk, this%msk_d, n, &
450  host_to_device, sync=.false.)
451  call device_memcpy(this%facet, this%facet_d, n, &
452  host_to_device, sync=.false.)
453  end if
454 
455  end subroutine bc_finalize
456 
459  subroutine bc_list_init(bclst, size)
460  type(bc_list_t), intent(inout), target :: bclst
461  integer, optional :: size
462  integer :: n, i
463 
464  call bc_list_free(bclst)
465 
466  if (present(size)) then
467  n = size
468  else
469  n = 1
470  end if
471 
472  allocate(bclst%bc(n))
473 
474  do i = 1, n
475  bclst%bc(i)%bcp => null()
476  end do
477 
478  bclst%n = 0
479  bclst%size = n
480 
481  end subroutine bc_list_init
482 
486  subroutine bc_list_free(bclst)
487  type(bc_list_t), intent(inout) :: bclst
488 
489  if (allocated(bclst%bc)) then
490  deallocate(bclst%bc)
491  end if
492 
493  bclst%n = 0
494  bclst%size = 0
495 
496  end subroutine bc_list_free
497 
500  subroutine bc_list_add(bclst, bc)
501  type(bc_list_t), intent(inout) :: bclst
502  class(bc_t), intent(inout), target :: bc
503  type(bcp_t), allocatable :: tmp(:)
504 
506  if(bc%marked_facet%size() .eq. 0) return
507 
508  if (bclst%n .ge. bclst%size) then
509  bclst%size = bclst%size * 2
510  allocate(tmp(bclst%size))
511  tmp(1:bclst%n) = bclst%bc
512  call move_alloc(tmp, bclst%bc)
513  end if
514 
515  bclst%n = bclst%n + 1
516  bclst%bc(bclst%n)%bcp => bc
517 
518  end subroutine bc_list_add
519 
525  subroutine bc_list_apply_scalar(bclst, x, n, t, tstep)
526  type(bc_list_t), intent(inout) :: bclst
527  integer, intent(in) :: n
528  real(kind=rp), intent(inout), dimension(n) :: x
529  real(kind=rp), intent(in), optional :: t
530  integer, intent(in), optional :: tstep
531  type(c_ptr) :: x_d
532  integer :: i
533 
534  if (neko_bcknd_device .eq. 1) then
535  x_d = device_get_ptr(x)
536  if (present(t) .and. present(tstep)) then
537  do i = 1, bclst%n
538  call bclst%bc(i)%bcp%apply_scalar_dev(x_d, t=t, tstep=tstep)
539  end do
540  else if (present(t)) then
541  do i = 1, bclst%n
542  call bclst%bc(i)%bcp%apply_scalar_dev(x_d, t=t)
543  end do
544  else if (present(tstep)) then
545  do i = 1, bclst%n
546  call bclst%bc(i)%bcp%apply_scalar_dev(x_d, tstep=tstep)
547  end do
548  else
549  do i = 1, bclst%n
550  call bclst%bc(i)%bcp%apply_scalar_dev(x_d)
551  end do
552  end if
553  else
554  if (present(t) .and. present(tstep)) then
555  do i = 1, bclst%n
556  call bclst%bc(i)%bcp%apply_scalar(x, n, t, tstep)
557  end do
558  else if (present(t)) then
559  do i = 1, bclst%n
560  call bclst%bc(i)%bcp%apply_scalar(x, n, t=t)
561  end do
562  else if (present(tstep)) then
563  do i = 1, bclst%n
564  call bclst%bc(i)%bcp%apply_scalar(x, n, tstep=tstep)
565  end do
566  else
567  do i = 1, bclst%n
568  call bclst%bc(i)%bcp%apply_scalar(x, n)
569  end do
570  end if
571  end if
572 
573  end subroutine bc_list_apply_scalar
574 
582  subroutine bc_list_apply_vector(bclst, x, y, z, n, t, tstep)
583  type(bc_list_t), intent(inout) :: bclst
584  integer, intent(in) :: n
585  real(kind=rp), intent(inout), dimension(n) :: x
586  real(kind=rp), intent(inout), dimension(n) :: y
587  real(kind=rp), intent(inout), dimension(n) :: z
588  real(kind=rp), intent(in), optional :: t
589  integer, intent(in), optional :: tstep
590  type(c_ptr) :: x_d
591  type(c_ptr) :: y_d
592  type(c_ptr) :: z_d
593  integer :: i
594 
595  if (neko_bcknd_device .eq. 1) then
596  x_d = device_get_ptr(x)
597  y_d = device_get_ptr(y)
598  z_d = device_get_ptr(z)
599  if (present(t) .and. present(tstep)) then
600  do i = 1, bclst%n
601  call bclst%bc(i)%bcp%apply_vector_dev(x_d, y_d, z_d, t, tstep)
602  end do
603  else if (present(t)) then
604  do i = 1, bclst%n
605  call bclst%bc(i)%bcp%apply_vector_dev(x_d, y_d, z_d, t=t)
606  end do
607  else if (present(tstep)) then
608  do i = 1, bclst%n
609  call bclst%bc(i)%bcp%apply_vector_dev(x_d, y_d, z_d, tstep=tstep)
610  end do
611  else
612  do i = 1, bclst%n
613  call bclst%bc(i)%bcp%apply_vector_dev(x_d, y_d, z_d)
614  end do
615  end if
616  else
617  if (present(t) .and. present(tstep)) then
618  do i = 1, bclst%n
619  call bclst%bc(i)%bcp%apply_vector(x, y, z, n, t, tstep)
620  end do
621  else if (present(t)) then
622  do i = 1, bclst%n
623  call bclst%bc(i)%bcp%apply_vector(x, y, z, n, t=t)
624  end do
625  else if (present(tstep)) then
626  do i = 1, bclst%n
627  call bclst%bc(i)%bcp%apply_vector(x, y, z, n, tstep=tstep)
628  end do
629  else
630  do i = 1, bclst%n
631  call bclst%bc(i)%bcp%apply_vector(x, y, z, n)
632  end do
633  end if
634  end if
635 
636  end subroutine bc_list_apply_vector
637 
638 
639 end module bc
Apply the boundary condition to a scalar field on the device.
Definition: bc.f90:161
Apply the boundary condition to a scalar field.
Definition: bc.f90:118
Apply the boundary condition to a vector field on the device.
Definition: bc.f90:177
Apply the boundary condition to a vector field.
Definition: bc.f90:137
Destructor.
Definition: bc.f90:152
Return the device pointer for an associated Fortran array.
Definition: device.F90:81
Map a Fortran array to a device (allocate and associate)
Definition: device.F90:57
Copy data between host and device (or device and device)
Definition: device.F90:51
Defines a boundary condition.
Definition: bc.f90:34
subroutine bc_mark_zone(this, bc_zone)
Mark all facets from a zone.
Definition: bc.f90:279
subroutine, public bc_list_add(bclst, bc)
Add a condition to a list of boundary conditions.
Definition: bc.f90:501
subroutine, public bc_list_apply_vector(bclst, x, y, z, n, t, tstep)
Apply a list of boundary conditions to a vector field.
Definition: bc.f90:583
subroutine bc_finalize(this)
Finalize the construction of the bc by populting the msk and facet arrays.
Definition: bc.f90:360
subroutine bc_free_base(this)
Destructor for the base type, bc_t.
Definition: bc.f90:218
subroutine, public bc_list_init(bclst, size)
Constructor for a list of boundary conditions.
Definition: bc.f90:460
subroutine, public bc_list_free(bclst)
Destructor for a list of boundary conditions.
Definition: bc.f90:487
subroutine bc_init_base(this, coef)
Constructor.
Definition: bc.f90:202
subroutine bc_mark_zones_from_list(this, bc_zones, bc_key, bc_labels)
Mark all facets from a list of zones, also marks type of bc in the mesh. The facet_type in mesh is be...
Definition: bc.f90:294
subroutine bc_mark_facet(this, facet, el)
Mark facet on element el as part of the boundary condition.
Definition: bc.f90:251
subroutine bc_mark_facets(this, facet_list)
Mark all facets from a (facet, el) tuple list.
Definition: bc.f90:264
subroutine, public bc_list_apply_scalar(bclst, x, n, t, tstep)
Apply a list of boundary conditions to a scalar field.
Definition: bc.f90:526
Coefficients.
Definition: coef.f90:34
Device abstraction, common interface for various accelerators.
Definition: device.F90:34
integer, parameter, public host_to_device
Definition: device.F90:47
subroutine, public device_free(x_d)
Deallocate memory on the device.
Definition: device.F90:185
Defines a mapping of the degrees of freedom.
Definition: dofmap.f90:35
Defines a zone as a subset of facets in a mesh.
Definition: facet_zone.f90:34
Defines a mesh.
Definition: mesh.f90:34
integer, parameter, public neko_msh_max_zlbls
Max num. zone labels.
Definition: mesh.f90:56
integer, parameter, public neko_msh_max_zlbl_len
Max length of a zone label.
Definition: mesh.f90:58
Build configurations.
Definition: neko_config.f90:34
integer, parameter neko_bcknd_device
Definition: neko_config.f90:44
integer, parameter, public rp
Global precision used in computations.
Definition: num_types.f90:12
Defines a function space.
Definition: space.f90:34
Implements a dynamic stack ADT.
Definition: stack.f90:35
Implements a n-tuple.
Definition: tuple.f90:34
Utilities.
Definition: utils.f90:35
character(len=100) function, dimension(:), allocatable, public split_string(string, delimiter)
Split a string based on delimiter (tokenizer) OBS: very hacky, this should really be improved,...
Definition: utils.f90:89
pure integer function, public linear_index(i, j, k, l, lx, ly, lz)
Compute the address of a (i,j,k,l) array with sizes (1:lx, 1:ly, 1:lz, :)
Definition: utils.f90:130
A list of boundary conditions.
Definition: bc.f90:104
Base type for a boundary condition.
Definition: bc.f90:51
Pointer to boundary condtiion.
Definition: bc.f90:99
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition: coef.f90:55
The function space for the SEM solution fields.
Definition: space.f90:62
Integer 2-tuple based stack.
Definition: stack.f90:84
Integer based 2-tuple.
Definition: tuple.f90:51