38 use json_module,
only : json_file
54 use,
intrinsic :: iso_c_binding, only : c_ptr, c_null_ptr, c_associated
65 real(kind=
rp) :: kappa
71 real(kind=
rp) :: z0h_in
79 character(len=:),
allocatable :: bc_type
81 real(kind=
rp) :: bc_value
83 character(len=:),
allocatable :: scalar_name
85 type(
vector_t) :: ri_b, l_ob, utau, magu, ti, ts, q
86 integer,
allocatable :: h_x_idx(:), h_y_idx(:), h_z_idx(:)
87 type(c_ptr) :: h_x_idx_d = c_null_ptr
88 type(c_ptr) :: h_y_idx_d = c_null_ptr
89 type(c_ptr) :: h_z_idx_d = c_null_ptr
99 procedure, pass(this) :: init_from_components => &
106 procedure, pass(this) :: extract_properties => &
121 character(len=*),
intent(in) :: scheme_name
122 type(
coef_t),
intent(in) :: coef
123 integer,
intent(in) :: msk(:)
124 integer,
intent(in) :: facet(:)
125 integer,
intent(in) :: h_index
126 type(json_file),
intent(inout) :: json
127 real(kind=
rp) :: kappa, z0, z0h_in, pr
128 character(len=:),
allocatable :: bc_type
129 character(len=:),
allocatable :: scalar_name
130 real(kind=
rp) :: bc_value
131 real(kind=
rp),
allocatable :: g_tmp(:)
132 real(kind=
rp) :: g(3)
133 logical :: if_time_dependent
144 call json_get(json,
"type_of_temp_bc", bc_type)
145 call json_get(json,
"scalar_field", scalar_name)
148 if_time_dependent, .false.)
150 if (if_time_dependent)
then
155 if (
size(g_tmp) == 3)
then
158 call neko_error(
"Richardson WM: The gravity vector should " &
159 //
"have exactly 3 components")
163 call this%init_from_components(scheme_name, scalar_name, coef, &
164 msk, facet, h_index, kappa, g, pr, z0, z0h_in, bc_type, bc_value)
166 deallocate(scalar_name)
174 type(
coef_t),
intent(in) :: coef
175 type(json_file),
intent(inout) :: json
176 real(kind=
rp),
allocatable :: g_tmp(:)
177 character(len=LOG_SIZE) :: log_buf
178 logical :: if_time_dependent
180 call this%partial_init_base(coef, json)
185 call json_get(json,
"type_of_temp_bc", this%bc_type)
186 call json_get(json,
"scalar_field", this%scalar_name)
189 if_time_dependent, .false.)
191 if (if_time_dependent)
then
197 if (
size(g_tmp) == 3)
then
200 call neko_error(
"Richardson WM: The gravity vector should " &
201 //
"have exactly 3 components")
206 write(log_buf,
'(A, A)')
'Model : Richardson'
208 write(log_buf,
'(A, A)')
'scalar_name : ', trim(this%scalar_name)
210 write(log_buf,
'(A, A)')
'bc_type : ', trim(this%bc_type)
212 write(log_buf,
'(A, E15.7)')
'bc_value : ', this%bc_value
214 write(log_buf,
'(A, E15.7)')
'kappa : ', this%kappa
216 write(log_buf,
'(A, E15.7)')
'z0 : ', this%z0
218 write(log_buf,
'(A, E15.7)')
'z0h : ', this%z0h_in
220 write(log_buf,
'(A, E15.7)')
'Pr : ', this%Pr
222 write(log_buf,
'(A, 3(E15.7,1X))')
'g : ', this%g
233 integer,
intent(in) :: msk(:)
234 integer,
intent(in) :: facet(:)
238 call this%finalize_base(msk, facet)
240 call this%Ri_b%init(this%n_nodes)
241 call this%L_ob%init(this%n_nodes)
242 call this%utau%init(this%n_nodes)
243 call this%magu%init(this%n_nodes)
244 call this%ti%init(this%n_nodes)
245 call this%ts%init(this%n_nodes)
246 call this%q%init(this%n_nodes)
248 call this%mu_w%init(this%n_nodes)
249 call this%rho_w%init(this%n_nodes)
251 allocate(this%h_x_idx(this%n_nodes))
252 allocate(this%h_y_idx(this%n_nodes))
253 allocate(this%h_z_idx(this%n_nodes))
255 call device_map(this%h_x_idx, this%h_x_idx_d, this%n_nodes)
256 call device_map(this%h_y_idx, this%h_y_idx_d, this%n_nodes)
257 call device_map(this%h_z_idx, this%h_z_idx_d, this%n_nodes)
260 do i = 1, this%n_nodes
264 this%h_x_idx(i) = this%h_index
268 this%h_x_idx(i) = - this%h_index
273 this%h_y_idx(i) = this%h_index
277 this%h_y_idx(i) = - this%h_index
282 this%h_z_idx(i) = this%h_index
286 this%h_z_idx(i) = - this%h_index
288 call neko_error(
"The face index is not correct (richardson.f90)")
293 call device_memcpy(this%h_x_idx, this%h_x_idx_d, this%n_nodes, &
295 call device_memcpy(this%h_y_idx, this%h_y_idx_d, this%n_nodes, &
297 call device_memcpy(this%h_z_idx, this%h_z_idx_d, this%n_nodes, &
309 this%mu%size(), this%mu_w%size())
312 this%rho%size(), this%rho_w%size())
315 this%mu%size(), this%mu_w%size())
317 this%rho%size(), this%rho_w%size())
337 scalar_name, coef, msk, facet, h_index, kappa, g, Pr, z0, &
338 z0h_in, bc_type, bc_value)
340 character(len=*),
intent(in) :: scheme_name
341 character(len=*),
intent(in) :: bc_type
342 character(len=*),
intent(in) :: scalar_name
343 type(
coef_t),
intent(in) :: coef
344 integer,
intent(in) :: msk(:)
345 integer,
intent(in) :: facet(:)
346 integer,
intent(in) :: h_index
347 real(kind=
rp),
intent(in) :: g(3)
348 real(kind=
rp) :: g_mag, g_dot_n, cos_alpha, max_ang
350 real(kind=
rp),
intent(in) :: kappa
351 real(kind=
rp),
intent(in) :: z0, z0h_in, bc_value, pr
352 character(len=LOG_SIZE) :: log_buf
355 call this%init_base(scheme_name, coef, msk, facet, h_index)
362 this%bc_type = bc_type
363 this%bc_value = bc_value
364 this%scalar_name = scalar_name
366 call this%mu_w%init(this%n_nodes)
367 call this%rho_w%init(this%n_nodes)
370 g_mag = sqrt(sum(g**2))
371 if (g_mag < 1.0e-6_rp)
then
372 call neko_error(
"Richardson WM: Gravity magnitude is zero. " &
373 //
"Check your input configuration.")
378 do i = 1, this%n_nodes
379 g_dot_n = abs(g(1) * this%n_x%x(i) + g(2) * this%n_y%x(i) + &
380 g(3) * this%n_z%x(i))
381 cos_alpha = g_dot_n / g_mag
382 max_ang =
max(max_ang, acos(min(1.0_rp, cos_alpha)))
384 max_ang = max_ang * 180.0_rp / (4.0_rp * atan(1.0_rp))
385 if (max_ang > 8.0_rp)
then
386 write(log_buf,
'(A, F6.2, A)')
"Richardson WM: Significant " &
387 //
"gravity-normal misalignment (max ", &
388 max_ang,
" deg). Stability corrections will use projected gravity."
393 if (any(this%h%x(1:this%n_nodes) .le. this%z0))
then
394 call neko_error(
"Richardson WM: Sampling height h must be greater " &
395 //
"than roughness z0.")
396 else if ( (this%z0h_in .gt. 0.0_rp) .and. &
397 (any(this%h%x(1:this%n_nodes) .le. this%z0h_in)) )
then
398 call neko_error(
"Richardson WM: Sampling height h must be greater " &
399 //
"than thermal roughness z0h.")
400 else if (this%z0 .eq. 0.0_rp)
then
401 call neko_error(
"Richardson WM: Roughness z0 must be greater than 0.")
402 else if (this%z0h_in .eq. 0.0_rp)
then
403 call neko_error(
"Richardson WM: Thermal roughness z0h must " // &
404 "be greater than 0.")
413 if (
allocated(this%bc_type))
then
414 deallocate(this%bc_type)
417 if (
allocated(this%scalar_name))
then
418 deallocate(this%scalar_name)
421 call this%mu_w%free()
422 call this%rho_w%free()
423 call this%free_base()
425 call this%Ri_b%free()
426 call this%L_ob%free()
427 call this%utau%free()
428 call this%magu%free()
433 if (
allocated(this%h_x_idx))
then
434 if (c_associated(this%h_x_idx_d))
then
437 deallocate(this%h_x_idx)
440 if (
allocated(this%h_y_idx))
then
441 if (c_associated(this%h_y_idx_d))
then
444 deallocate(this%h_y_idx)
447 if (
allocated(this%h_z_idx))
then
448 if (c_associated(this%h_z_idx_d))
then
451 deallocate(this%h_z_idx)
461 real(kind=
rp),
intent(in) :: t
462 integer,
intent(in) :: tstep
467 real(kind=
rp),
pointer :: updated_bc_value
470 call this%extract_properties()
479 this%bc_value = updated_bc_value
484 this%ind_r_d, this%ind_s_d, this%ind_t_d, &
485 this%ind_e_d, this%n_x%x_d, this%n_y%x_d, this%n_z%x_d, &
486 this%h%x_d, this%tau_x%x_d, this%tau_y%x_d, &
487 this%tau_z%x_d, this%n_nodes, u%Xh%lx, this%kappa, &
488 this%mu_w%x_d, this%rho_w%x_d, this%g, this%Pr, this%z0, &
490 this%bc_type, this%bc_value, tstep, this%Ri_b%x_d, &
491 this%L_ob%x_d, this%utau%x_d, this%magu%x_d, this%ti%x_d, &
493 this%q%x_d, this%h_x_idx_d, this%h_y_idx_d, this%h_z_idx_d)
496 this%ind_s, this%ind_t, this%ind_e, this%n_x%x, &
497 this%n_y%x, this%n_z%x, this%h%x, this%tau_x%x, &
498 this%tau_y%x, this%tau_z%x, this%n_nodes, u%Xh%lx, &
499 u%msh%nelv, this%kappa, this%mu_w%x, this%rho_w%x, &
500 this%g, this%Pr, this%z0, this%z0h_in, this%bc_type, &
501 this%bc_value, tstep, this%Ri_b%x, this%L_ob%x, &
502 this%utau%x, this%magu%x, this%ti%x, this%ts%x, &
503 this%q%x, this%h_x_idx, this%h_y_idx, this%h_z_idx)
507 this%utau, this%magu, this%ti, this%ts, this%q, &
508 this%n_nodes, this%bc_value)
510 nullify(u, v, w, temp, updated_bc_value)
515 ti, ts, q, n_nodes, bc_value)
516 character(len=LOG_SIZE) :: log_buf
517 integer,
intent(in) :: n_nodes
518 real(kind=
rp),
intent(in) :: bc_value
519 type(
vector_t),
intent(in) :: ri_b, l_ob, utau
520 type(
vector_t),
intent(in) :: magu, ti, ts, q
522 call neko_log%section(
"Wall model diagnostics")
523 write(log_buf,
'(A)')
'--- sum --- '
524 call neko_log%message(trim(log_buf))
525 write(log_buf,
'(A, E15.7)')
"Ri_b: ", &
528 call neko_log%message(trim(log_buf))
530 write(log_buf,
'(A, E15.7)')
"L_ob: ", &
533 call neko_log%message(trim(log_buf))
535 write(log_buf,
'(A, E15.7)')
"utau: ", &
538 call neko_log%message(trim(log_buf))
540 write(log_buf,
'(A, E15.7)')
"magu: ", &
543 call neko_log%message(trim(log_buf))
545 write(log_buf,
'(A, E15.7)')
"ti: ", &
548 call neko_log%message(trim(log_buf))
550 write(log_buf,
'(A, E15.7)')
"ts: ", &
553 call neko_log%message(trim(log_buf))
555 write(log_buf,
'(A, E15.7)')
"q: ", &
558 call neko_log%message(trim(log_buf))
560 write(log_buf,
'(A, E15.7)')
"bc_value: ", bc_value
561 call neko_log%message(trim(log_buf))
__inline__ __device__ void nonlinear_index(const int idx, const int lx, int *index)
__global__ void richardson_compute(const T *__restrict__ u_d, const T *__restrict__ v_d, const T *__restrict__ w_d, const T *__restrict__ temp_d, const T *__restrict__ h_d, const T *__restrict__ n_x_d, const T *__restrict__ n_y_d, const T *__restrict__ n_z_d, const int *__restrict__ ind_r_d, const int *__restrict__ ind_s_d, const int *__restrict__ ind_t_d, const int *__restrict__ ind_e_d, T *__restrict__ tau_x_d, T *__restrict__ tau_y_d, T *__restrict__ tau_z_d, int n_nodes, int lx, T kappa, const T *__restrict__ mu_w_d, const T *__restrict__ rho_w_d, T g1, T g2, T g3, T Pr, T z0, T z0h_in, T bc_value, T *__restrict__ Ri_b_diagn, T *__restrict__ L_ob_diagn, T *__restrict__ utau_diagn, T *__restrict__ magu_diagn, T *__restrict__ ti_diagn, T *__restrict__ ts_diagn, T *__restrict__ q_diagn, const int *__restrict__ h_x_idx, const int *__restrict__ h_y_idx, const int *__restrict__ h_z_idx)
Map a Fortran array to a device (allocate and associate)
Copy data between host and device (or device and device)
Unmap a Fortran array from a device (deassociate and free)
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.
subroutine, public device_masked_gather_copy_0(a_d, b_d, mask_d, n, n_mask, strm)
Gather a masked vector .
Device abstraction, common interface for various accelerators.
integer, parameter, public host_to_device
Utilities for retrieving parameters from the case files.
type(log_t), public neko_log
Global log stream.
integer, parameter, public log_size
subroutine, public masked_gather_copy_0(a, b, mask, n, n_mask)
Gather a masked vector to reduced contigous vector .
integer, parameter neko_bcknd_device
integer, parameter, public rp
Global precision used in computations.
Defines a registry for storing solution fields.
type(registry_t), target, public neko_registry
Global field registry.
type(registry_t), target, public neko_const_registry
This registry is used to store user-defined scalars and vectors, provided under the constants section...
Implements the CPU kernel for the richardson_t type.
subroutine, public richardson_compute_cpu(u, v, w, temp, ind_r, ind_s, ind_t, ind_e, n_x, n_y, n_z, h, tau_x, tau_y, tau_z, n_nodes, lx, nelv, kappa, mu_w, rho_w, g_vec, pr, z0, z0h_in, bc_type, bc_value, tstep, ri_b_diagn, l_ob_diagn, utau_diagn, magu_diagn, ti_diagn, ts_diagn, q_diagn, h_x_idx, h_y_idx, h_z_idx)
Main routine to compute the surface stresses based on richardson.
Implements the device kernel for the richardson_t type.
subroutine, public richardson_compute_device(u_d, v_d, w_d, temp_d, ind_r_d, ind_s_d, ind_t_d, ind_e_d, n_x_d, n_y_d, n_z_d, h_d, tau_x_d, tau_y_d, tau_z_d, n_nodes, lx, kappa, mu_w_d, rho_w_d, g, pr, z0, z0h_in, bc_type, bc_value, tstep, ri_b_diagn, l_ob_diagn, utau_diagn, magu_diagn, ti_diagn, ts_diagn, q_diagn, h_x_idx, h_y_idx, h_z_idx)
Compute the wall shear stress on device using the rough log-law model.
subroutine richardson_init_from_components(this, scheme_name, scalar_name, coef, msk, facet, h_index, kappa, g, pr, z0, z0h_in, bc_type, bc_value)
Constructor from components.
subroutine richardson_extract_properties(this)
Extract the values of rho and mu at the boundary.
subroutine richardson_log_diagnostics(ri_b, l_ob, utau, magu, ti, ts, q, n_nodes, bc_value)
subroutine richardson_partial_init(this, coef, json)
Constructor from JSON.
subroutine richardson_finalize(this, msk, facet)
Finalize the construction using the mask and facet arrays of the bc.
subroutine richardson_init(this, scheme_name, coef, msk, facet, h_index, json)
Constructor from JSON.
subroutine richardson_free(this)
Destructor for the richardson_t (base) class.
Defines a registry for storing and requesting temporary objects This can be used when you have a func...
type(scratch_registry_t), target, public neko_scratch_registry
Global scratch registry.
subroutine, public neko_warning(warning_msg)
Reports a warning to standard output.
real(kind=rp) function, public vector_glmin(a, n)
Global minimum of all elements in a vector .
real(kind=rp) function, public vector_glsum(a, n)
real(kind=rp) function, public vector_glmax(a, n)
Global maximum of all elements in a vector .
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Wall model similar to the Monin-Obukhov Similarity Theory for atmospheric boundary layer flows,...
Base abstract type for wall-stress models for wall-modelled LES.