Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
dong_outflow.f90
Go to the documentation of this file.
1! Copyright (c) 2022-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!
36 use dirichlet, only : dirichlet_t
38 use num_types, only : rp, c_rp
39 use bc, only : bc_t, bc_dirichlet
40 use field, only : field_t
41 use dofmap, only : dofmap_t
42 use coefs, only : coef_t
43 use utils, only : nonlinear_index
45 use registry, only : neko_registry
46 use, intrinsic :: iso_c_binding, only : c_ptr, c_sizeof, c_null_ptr, &
47 c_associated
48 use json_module, only : json_file
50 use utils, only : neko_error
51 use time_state, only : time_state_t
52 implicit none
53 private
54
60 type, public, extends(bc_t) :: dong_outflow_t
61 type(field_t), pointer :: u
62 type(field_t), pointer :: v
63 type(field_t), pointer :: w
64 real(kind=rp) :: delta
65 real(kind=rp) :: uinf
66 type(c_ptr) :: normal_x_d = c_null_ptr
67 type(c_ptr) :: normal_y_d = c_null_ptr
68 type(c_ptr) :: normal_z_d = c_null_ptr
69 contains
70 procedure, pass(this) :: apply_scalar => dong_outflow_apply_scalar
71 procedure, pass(this) :: apply_vector => dong_outflow_apply_vector
72 procedure, pass(this) :: apply_scalar_dev => dong_outflow_apply_scalar_dev
73 procedure, pass(this) :: apply_vector_dev => dong_outflow_apply_vector_dev
75 procedure, pass(this) :: init => dong_outflow_init
77 procedure, pass(this) :: free => dong_outflow_free
79 procedure, pass(this) :: finalize => dong_outflow_finalize
80 end type dong_outflow_t
81
82contains
86 subroutine dong_outflow_init(this, coef, json)
87 class(dong_outflow_t), target, intent(inout) :: this
88 type(coef_t), target, intent(in) :: coef
89 type(json_file), intent(inout) :: json
90 call this%free()
91 call this%init_base(coef)
92 this%bc_type = bc_dirichlet
93
94 call json_get_or_default(json, 'delta', this%delta, 0.01_rp)
95 call json_get_or_default(json, 'velocity_scale', this%uinf, 1.0_rp)
96
97 end subroutine dong_outflow_init
98
101 subroutine dong_outflow_apply_scalar(this, x, n, time, strong)
102 class(dong_outflow_t), intent(inout) :: this
103 integer, intent(in) :: n
104 real(kind=rp), intent(inout), dimension(n) :: x
105 type(time_state_t), intent(in), optional :: time
106 logical, intent(in), optional :: strong
107 integer :: i, m, k, facet, idx(4)
108 real(kind=rp) :: vn, s0, ux, uy, uz, normal_xyz(3)
109 logical :: strong_
110
111 if (present(strong)) then
112 strong_ = strong
113 else
114 strong_ = .true.
115 end if
116
117 !Im actually not sure what to do if one has two dong that share a corner.
118 if (strong_) then
119 m = this%facet_node_msk(0)
120 !$omp do
121 do i = 1, m
122 k = this%facet_node_msk(i)
123 facet = this%facet(i)
124 ux = this%u%x(k,1,1,1)
125 uy = this%v%x(k,1,1,1)
126 uz = this%w%x(k,1,1,1)
127 idx = nonlinear_index(k, this%Xh%lx, this%Xh%lx, this%Xh%lx)
128 normal_xyz = this%coef%get_normal(idx(1), idx(2), idx(3), idx(4), &
129 facet)
130 vn = ux*normal_xyz(1) + uy*normal_xyz(2) + uz*normal_xyz(3)
131 s0 = 0.5_rp*(1.0_rp - tanh(vn / (this%uinf * this%delta)))
132
133 x(k) = -0.5_rp * (ux*ux+uy*uy+uz*uz) * s0
134 end do
135 !$omp end do
136 end if
137 end subroutine dong_outflow_apply_scalar
138
141 subroutine dong_outflow_apply_vector(this, x, y, z, n, time, strong)
142 class(dong_outflow_t), intent(inout) :: this
143 integer, intent(in) :: n
144 real(kind=rp), intent(inout), dimension(n) :: x
145 real(kind=rp), intent(inout), dimension(n) :: y
146 real(kind=rp), intent(inout), dimension(n) :: z
147 type(time_state_t), intent(in), optional :: time
148 logical, intent(in), optional :: strong
149
150 end subroutine dong_outflow_apply_vector
151
154 subroutine dong_outflow_apply_scalar_dev(this, x_d, time, strong, strm)
155 class(dong_outflow_t), intent(inout), target :: this
156 type(c_ptr), intent(inout) :: x_d
157 type(time_state_t), intent(in), optional :: time
158 logical, intent(in), optional :: strong
159 type(c_ptr), intent(inout) :: strm
160 logical :: strong_
161
162 if (present(strong)) then
163 strong_ = strong
164 else
165 strong_ = .true.
166 end if
167
168 if (strong_ .and. this%msk(0) .gt. 0) then
169 call device_dong_outflow_apply_scalar(this%msk_d, x_d, &
170 this%normal_x_d, this%normal_y_d, this%normal_z_d, &
171 this%u%x_d, this%v%x_d, this%w%x_d, &
172 this%uinf, this%delta, &
173 this%msk(0), strm)
174 end if
175
176 end subroutine dong_outflow_apply_scalar_dev
177
180 subroutine dong_outflow_apply_vector_dev(this, x_d, y_d, z_d, time, &
181 strong, strm)
182 class(dong_outflow_t), intent(inout), target :: this
183 type(c_ptr), intent(inout) :: x_d
184 type(c_ptr), intent(inout) :: y_d
185 type(c_ptr), intent(inout) :: z_d
186 type(time_state_t), intent(in), optional :: time
187 logical, intent(in), optional :: strong
188 type(c_ptr), intent(inout) :: strm
189
190 !call device_dong_outflow_apply_vector(this%msk_d, x_d, y_d, z_d, &
191 ! this%g, size(this%msk))
192
193 end subroutine dong_outflow_apply_vector_dev
194
196 subroutine dong_outflow_free(this)
197 class(dong_outflow_t), target, intent(inout) :: this
198
199 call this%free_base
200 nullify(this%u)
201 nullify(this%v)
202 nullify(this%w)
203
204 if (c_associated(this%normal_x_d)) then
205 call device_free(this%normal_x_d)
206 this%normal_x_d = c_null_ptr
207 end if
208
209 if (c_associated(this%normal_y_d)) then
210 call device_free(this%normal_y_d)
211 this%normal_y_d = c_null_ptr
212 end if
213
214 if (c_associated(this%normal_z_d)) then
215 call device_free(this%normal_z_d)
216 this%normal_z_d = c_null_ptr
217 end if
218
219 end subroutine dong_outflow_free
220
222 subroutine dong_outflow_finalize(this)
223 class(dong_outflow_t), target, intent(inout) :: this
224 real(kind=rp), allocatable :: temp_x(:)
225 real(kind=rp), allocatable :: temp_y(:)
226 real(kind=rp), allocatable :: temp_z(:)
227 real(c_rp) :: dummy
228 integer :: i, m, k, facet, idx(4)
229 real(kind=rp) :: normal_xyz(3)
230
231 ! Here and in apply_scalar(), which runs every step
232 call this%coef%require_facets('dong_outflow')
233
234 call this%finalize_base()
235
236 this%u => neko_registry%get_field("u")
237 this%v => neko_registry%get_field("v")
238 this%w => neko_registry%get_field("w")
239 if ((neko_bcknd_device .eq. 1) .and. (this%facet_node_msk(0) .gt. 0)) then
240 call device_alloc(this%normal_x_d, &
241 c_sizeof(dummy)*this%facet_node_msk(0))
242 call device_alloc(this%normal_y_d, &
243 c_sizeof(dummy)*this%facet_node_msk(0))
244 call device_alloc(this%normal_z_d, &
245 c_sizeof(dummy)*this%facet_node_msk(0))
246 m = this%facet_node_msk(0)
247 allocate(temp_x(m))
248 allocate(temp_y(m))
249 allocate(temp_z(m))
250 !$omp parallel do private(k, facet, idx, normal_xyz)
251 do i = 1, m
252 k = this%facet_node_msk(i)
253 facet = this%facet(i)
254 idx = nonlinear_index(k, this%Xh%lx, this%Xh%lx, this%Xh%lx)
255 normal_xyz = &
256 this%coef%get_normal(idx(1), idx(2), idx(3), idx(4), facet)
257 temp_x(i) = normal_xyz(1)
258 temp_y(i) = normal_xyz(2)
259 temp_z(i) = normal_xyz(3)
260 end do
261 !$omp end parallel do
262 call device_memcpy(temp_x, this%normal_x_d, m, host_to_device, &
263 sync = .false.)
264 call device_memcpy(temp_y, this%normal_y_d, m, host_to_device, &
265 sync = .false.)
266 call device_memcpy(temp_z, this%normal_z_d, m, host_to_device, &
267 sync = .true.)
268 deallocate( temp_x, temp_y, temp_z)
269 end if
270 end subroutine dong_outflow_finalize
271
272end module dong_outflow
__inline__ __device__ void nonlinear_index(const int idx, const int lx, int *index)
Definition bc_utils.h:44
Copy data between host and device (or device and device)
Definition device.F90:72
Retrieves a parameter by name or assigns a provided default value. In the latter case also adds the m...
Retrieves a parameter by name or throws an error.
Defines a boundary condition.
Definition bc.f90:34
integer, parameter, public bc_dirichlet
Supported boundary condition types. The values are set in order of precedence for global resolution....
Definition bc.f90:66
Coefficients.
Definition coef.f90:34
subroutine, public device_dong_outflow_apply_scalar(msk, x, normal_x, normal_y, normal_z, u, v, w, uinf, delta, m, strm)
Device abstraction, common interface for various accelerators.
Definition device.F90:34
integer, parameter, public host_to_device
Definition device.F90:48
subroutine, public device_free(x_d)
Deallocate memory on the device.
Definition device.F90:243
subroutine, public device_alloc(x_d, s)
Allocate memory on the device.
Definition device.F90:212
Defines a dirichlet boundary condition.
Definition dirichlet.f90:34
Defines a mapping of the degrees of freedom.
Definition dofmap.f90:35
Defines a dong outflow condition.
subroutine dong_outflow_finalize(this)
Finalize.
subroutine dong_outflow_apply_vector_dev(this, x_d, y_d, z_d, time, strong, strm)
Boundary condition apply for a generic Dirichlet condition to vectors x, y and z (device version)
subroutine dong_outflow_apply_vector(this, x, y, z, n, time, strong)
Boundary condition apply for a generic Dirichlet condition to vectors x, y and z.
subroutine dong_outflow_apply_scalar_dev(this, x_d, time, strong, strm)
Boundary condition apply for a generic Dirichlet condition to a vector x (device version)
subroutine dong_outflow_free(this)
Destructor.
subroutine dong_outflow_apply_scalar(this, x, n, time, strong)
Boundary condition apply for a generic Dirichlet condition to a vector x.
subroutine dong_outflow_init(this, coef, json)
Constructor.
Defines a field.
Definition field.f90:34
Utilities for retrieving parameters from the case files.
Build configurations.
integer, parameter neko_bcknd_device
integer, parameter, public c_rp
Definition num_types.f90:15
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:14
Defines a registry for storing solution fields.
Definition registry.f90:34
type(registry_t), target, public neko_registry
Global field registry.
Definition registry.f90:144
Module with things related to the simulation time.
Utilities.
Definition utils.f90:35
Base type for a boundary condition.
Definition bc.f90:72
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:93
Generic Dirichlet boundary condition on .
Definition dirichlet.f90:49
Dong outflow condition Follows "A Convective-like Energy-Stable Open Boundary Condition for Simulati...
A struct that contains all info about the time, expand as needed.