Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
blasius.f90
Go to the documentation of this file.
1! Copyright (c) 2021-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 blasius
35 use num_types, only : rp
36 use coefs, only : coef_t
37 use utils, only : nonlinear_index
42 use utils, only : neko_error
43 use, intrinsic :: iso_fortran_env
44 use, intrinsic :: iso_c_binding
45 use bc, only : bc_t, bc_dirichlet
46 use json_module, only : json_file
48 use time_state, only : time_state_t
49 implicit none
50 private
51
55 type, public, extends(bc_t) :: blasius_t
56 real(kind=rp), dimension(3) :: uinf = [0d0, 0d0, 0d0]
57 real(kind=rp) :: delta
58 procedure(blasius_profile), nopass, pointer :: bla => null()
59 type(c_ptr), private :: blax_d = c_null_ptr
60 type(c_ptr), private :: blay_d = c_null_ptr
61 type(c_ptr), private :: blaz_d = c_null_ptr
62 contains
63 procedure, pass(this) :: apply_scalar => blasius_apply_scalar
64 procedure, pass(this) :: apply_vector => blasius_apply_vector
65 procedure, pass(this) :: apply_scalar_dev => blasius_apply_scalar_dev
66 procedure, pass(this) :: apply_vector_dev => blasius_apply_vector_dev
67 procedure, pass(this) :: set_params => blasius_set_params
69 procedure, pass(this) :: init => blasius_init
71 procedure, pass(this) :: init_from_components => &
74 procedure, pass(this) :: free => blasius_free
76 procedure, pass(this) :: finalize => blasius_finalize
77 end type blasius_t
78
79contains
80
84 subroutine blasius_init(this, coef, json)
85 class(blasius_t), intent(inout), target :: this
86 type(coef_t), target, intent(in) :: coef
87 type(json_file), intent(inout) :: json
88 real(kind=rp) :: delta
89 real(kind=rp), allocatable :: uinf(:)
90 character(len=:), allocatable :: approximation
91
92 call this%init_base(coef)
93
94 call json_get_or_lookup(json, 'delta', delta)
95 call json_get(json, 'approximation', approximation)
96 call json_get_or_lookup(json, 'freestream_velocity', uinf)
97
98 if (size(uinf) .ne. 3) then
99 call neko_error("The uinf keyword for the blasius profile should be an &
100 & array of 3 reals")
101 end if
102
103 call this%init_from_components(coef, delta, uinf, approximation)
104
105 end subroutine blasius_init
106
112 subroutine blasius_init_from_components(this, coef, delta, uinf, &
113 approximation)
114 class(blasius_t), intent(inout), target :: this
115 type(coef_t), target, intent(in) :: coef
116 real(kind=rp) :: delta
117 real(kind=rp) :: uinf(3)
118 character(len=*) :: approximation
119
120 call this%init_base(coef)
121 this%bc_type = bc_dirichlet
122
123 this%delta = delta
124 this%uinf = uinf
125
126 select case (trim(approximation))
127 case ('linear')
128 this%bla => blasius_linear
129 case ('quadratic')
130 this%bla => blasius_quadratic
131 case ('cubic')
132 this%bla => blasius_cubic
133 case ('quartic')
134 this%bla => blasius_quartic
135 case ('sin')
136 this%bla => blasius_sin
137 case ('tanh')
138 this%bla => blasius_tanh
139 case default
140 call neko_error('Invalid Blasius approximation')
141 end select
142 end subroutine blasius_init_from_components
143
144 subroutine blasius_free(this)
145 class(blasius_t), target, intent(inout) :: this
146
147 call this%free_base()
148 nullify(this%bla)
149
150 if (c_associated(this%blax_d)) then
151 call device_free(this%blax_d)
152 end if
153
154 if (c_associated(this%blay_d)) then
155 call device_free(this%blay_d)
156 end if
157
158 if (c_associated(this%blaz_d)) then
159 call device_free(this%blaz_d)
160 end if
161
162 end subroutine blasius_free
163
165 subroutine blasius_apply_scalar(this, x, n, time, strong)
166 class(blasius_t), intent(inout) :: this
167 integer, intent(in) :: n
168 real(kind=rp), intent(inout), dimension(n) :: x
169 type(time_state_t), intent(in), optional :: time
170 logical, intent(in), optional :: strong
171 end subroutine blasius_apply_scalar
172
174 subroutine blasius_apply_scalar_dev(this, x_d, time, strong, strm)
175 class(blasius_t), intent(inout), target :: this
176 type(c_ptr), intent(inout) :: x_d
177 type(time_state_t), intent(in), optional :: time
178 logical, intent(in), optional :: strong
179 type(c_ptr), intent(inout) :: strm
180 end subroutine blasius_apply_scalar_dev
181
183 subroutine blasius_apply_vector(this, x, y, z, n, time, strong)
184 class(blasius_t), intent(inout) :: this
185 integer, intent(in) :: n
186 real(kind=rp), intent(inout), dimension(n) :: x
187 real(kind=rp), intent(inout), dimension(n) :: y
188 real(kind=rp), intent(inout), dimension(n) :: z
189 type(time_state_t), intent(in), optional :: time
190 logical, intent(in), optional :: strong
191 integer :: i, m, k, idx(4), facet
192 logical :: strong_
193
194 if (present(strong)) then
195 strong_ = strong
196 else
197 strong_ = .true.
198 end if
199
200 associate(xc => this%coef%dof%x, yc => this%coef%dof%y, &
201 zc => this%coef%dof%z, nx => this%coef%nx, ny => this%coef%ny, &
202 nz => this%coef%nz, lx => this%coef%Xh%lx)
203 m = this%facet_node_msk(0)
204 if (strong_) then
205 !$omp do
206 do i = 1, m
207 k = this%facet_node_msk(i)
208 facet = this%facet(i)
209 idx = nonlinear_index(k, lx, lx, lx)
210 select case (facet)
211 case (1, 2)
212 x(k) = this%bla(zc(idx(1), idx(2), idx(3), idx(4)), &
213 this%delta, this%uinf(1))
214 y(k) = 0.0_rp
215 z(k) = 0.0_rp
216 case (3, 4)
217 x(k) = 0.0_rp
218 y(k) = this%bla(xc(idx(1), idx(2), idx(3), idx(4)), &
219 this%delta, this%uinf(2))
220 z(k) = 0.0_rp
221 case (5, 6)
222 x(k) = 0.0_rp
223 y(k) = 0.0_rp
224 z(k) = this%bla(yc(idx(1), idx(2), idx(3), idx(4)), &
225 this%delta, this%uinf(3))
226 end select
227 end do
228 !$omp end do
229 end if
230 end associate
231 end subroutine blasius_apply_vector
232
234 subroutine blasius_apply_vector_dev(this, x_d, y_d, z_d, time, strong, strm)
235 class(blasius_t), intent(inout), target :: this
236 type(c_ptr), intent(inout) :: x_d
237 type(c_ptr), intent(inout) :: y_d
238 type(c_ptr), intent(inout) :: z_d
239 type(time_state_t), intent(in), optional :: time
240 logical, intent(in), optional :: strong
241 integer :: i, m, k, idx(4), facet
242 integer(c_size_t) :: s
243 real(kind=rp), allocatable :: bla_x(:), bla_y(:), bla_z(:)
244 logical :: strong_
245 type(c_ptr), intent(inout) :: strm
246
247 if (present(strong)) then
248 strong_ = strong
249 else
250 strong_ = .true.
251 end if
252
253 associate(xc => this%coef%dof%x, yc => this%coef%dof%y, &
254 zc => this%coef%dof%z, nx => this%coef%nx, ny => this%coef%ny, &
255 nz => this%coef%nz, lx => this%coef%Xh%lx , &
256 blax_d => this%blax_d, blay_d => this%blay_d, &
257 blaz_d => this%blaz_d)
258
259 m = this%facet_node_msk(0)
260
261
262 ! Pretabulate values during first call to apply
263 if (.not. c_associated(blax_d) .and. strong_ .and. m .gt. 0) then
264 allocate(bla_x(m), bla_y(m), bla_z(m)) ! Temp arrays
265
266 if (rp .eq. real32) then
267 s = m * 4
268 else if (rp .eq. real64) then
269 s = m * 8
270 end if
271
272 call device_alloc(blax_d, s)
273 call device_alloc(blay_d, s)
274 call device_alloc(blaz_d, s)
275 !$omp parallel do private(k, facet, idx)
276 do i = 1, m
277 k = this%facet_node_msk(i)
278 facet = this%facet(i)
279 idx = nonlinear_index(k, lx, lx, lx)
280 select case (facet)
281 case (1,2)
282 bla_x(i) = this%bla(zc(idx(1), idx(2), idx(3), idx(4)), &
283 this%delta, this%uinf(1))
284 bla_y(i) = 0.0_rp
285 bla_z(i) = 0.0_rp
286 case (3,4)
287 bla_x(i) = 0.0_rp
288 bla_y(i) = this%bla(xc(idx(1), idx(2), idx(3), idx(4)), &
289 this%delta, this%uinf(2))
290 bla_z(i) = 0.0_rp
291 case (5,6)
292 bla_x(i) = 0.0_rp
293 bla_y(i) = 0.0_rp
294 bla_z(i) = this%bla(yc(idx(1), idx(2), idx(3), idx(4)), &
295 this%delta, this%uinf(3))
296 end select
297 end do
298 !$omp end parallel do
299
300 call device_memcpy(bla_x, blax_d, m, host_to_device, sync = .false.)
301 call device_memcpy(bla_y, blay_d, m, host_to_device, sync = .false.)
302 call device_memcpy(bla_z, blaz_d, m, host_to_device, sync = .true.)
303
304 deallocate(bla_x, bla_y, bla_z)
305 end if
306
307 if (strong_ .and. this%msk(0) .gt. 0) then
308 call device_inhom_dirichlet_apply_vector(this%msk_d, x_d, y_d, z_d, &
309 blax_d, blay_d, blaz_d, m, strm)
310 end if
311
312 end associate
313
314 end subroutine blasius_apply_vector_dev
315
317 subroutine blasius_set_params(this, uinf, delta, type)
318 class(blasius_t), intent(inout) :: this
319 real(kind=rp), intent(in) :: uinf(3)
320 real(kind=rp), intent(in) :: delta
321 character(len=*) :: type
322 this%delta = delta
323 this%uinf = uinf
324
325 select case (trim(type))
326 case ('linear')
327 this%bla => blasius_linear
328 case ('quadratic')
329 this%bla => blasius_quadratic
330 case ('cubic')
331 this%bla => blasius_cubic
332 case ('quartic')
333 this%bla => blasius_quartic
334 case ('sin')
335 this%bla => blasius_sin
336 case ('tanh')
337 this%bla => blasius_tanh
338 case default
339 call neko_error('Invalid Blasius approximation')
340 end select
341 end subroutine blasius_set_params
342
344 subroutine blasius_finalize(this)
345 class(blasius_t), target, intent(inout) :: this
346 call this%finalize_base()
347 end subroutine blasius_finalize
348end module blasius
__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
Abstract interface for computing a Blasius flow profile.
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
Defines a Blasius profile dirichlet condition.
Definition blasius.f90:34
subroutine blasius_apply_scalar_dev(this, x_d, time, strong, strm)
No-op scalar apply (device version)
Definition blasius.f90:175
subroutine blasius_init(this, coef, json)
Constructor.
Definition blasius.f90:85
subroutine blasius_init_from_components(this, coef, delta, uinf, approximation)
Constructor from components.
Definition blasius.f90:114
subroutine blasius_apply_vector(this, x, y, z, n, time, strong)
Apply blasius conditions (vector valued)
Definition blasius.f90:184
subroutine blasius_apply_scalar(this, x, n, time, strong)
No-op scalar apply.
Definition blasius.f90:166
subroutine blasius_apply_vector_dev(this, x_d, y_d, z_d, time, strong, strm)
Apply blasius conditions (vector valued) (device version)
Definition blasius.f90:235
subroutine blasius_free(this)
Definition blasius.f90:145
subroutine blasius_finalize(this)
Finalize.
Definition blasius.f90:345
subroutine blasius_set_params(this, uinf, delta, type)
Set Blasius parameters.
Definition blasius.f90:318
Coefficients.
Definition coef.f90:34
Device backend wrappers for inhomogeneous Dirichlet boundary conditions.
subroutine device_inhom_dirichlet_apply_vector(msk, x, y, z, bla_x, bla_y, bla_z, m, strm)
Apply an inhomogeneous Dirichlet condition to a vector field on the device.
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 flow profile.
real(kind=rp) function, public blasius_quadratic(y, delta, u)
Quadratic approximate Blasius Profile .
real(kind=rp) function, public blasius_quartic(y, delta, u)
Quartic approximate Blasius Profile .
real(kind=rp) function, public blasius_sin(y, delta, u)
Sinusoidal approximate Blasius Profile .
real(kind=rp) function, public blasius_cubic(y, delta, u)
Cubic approximate Blasius Profile .
real(kind=rp) function, public blasius_tanh(y, delta, u)
Hyperbolic tangent approximate Blasius Profile from O. Savas (2012) where is the 99 percent thickne...
real(kind=rp) function, public blasius_linear(y, delta, u)
Linear approximate Blasius profile .
Utilities for retrieving parameters from the case files.
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:14
Module with things related to the simulation time.
Utilities.
Definition utils.f90:35
Base type for a boundary condition.
Definition bc.f90:72
Blasius profile for inlet (vector valued).
Definition blasius.f90:55
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:93
A struct that contains all info about the time, expand as needed.