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 => &
117 subroutine most_init(this, scheme_name, coef, msk, facet, &
119 class(
most_t),
intent(inout) :: this
120 character(len=*),
intent(in) :: scheme_name
121 type(
coef_t),
intent(in) :: coef
122 integer,
intent(in) :: msk(:)
123 integer,
intent(in) :: facet(:)
124 integer,
intent(in) :: h_index
125 type(json_file),
intent(inout) :: json
126 real(kind=
rp) :: kappa, z0, z0h_in, pr
127 character(len=:),
allocatable :: bc_type
128 character(len=:),
allocatable :: scalar_name
129 real(kind=
rp) :: bc_value
130 real(kind=
rp),
allocatable :: g_tmp(:)
131 real(kind=
rp) :: g(3)
132 logical :: if_time_dependent
143 call json_get(json,
"type_of_temp_bc", bc_type)
144 call json_get(json,
"scalar_field", scalar_name)
147 if_time_dependent, .false.)
149 if (if_time_dependent)
then
154 if (
size(g_tmp) == 3)
then
157 call neko_error(
"MOST WM: The gravity vector should have exactly 3 components")
161 call this%init_from_components(scheme_name, scalar_name, coef, msk, facet, h_index, &
162 kappa, g, pr, z0, z0h_in, bc_type, bc_value)
164 deallocate(scalar_name)
171 class(
most_t),
intent(inout) :: this
172 type(
coef_t),
intent(in) :: coef
173 type(json_file),
intent(inout) :: json
174 real(kind=
rp),
allocatable :: g_tmp(:)
175 character(len=LOG_SIZE) :: log_buf
176 logical :: if_time_dependent
178 call this%partial_init_base(coef, json)
183 call json_get(json,
"type_of_temp_bc", this%bc_type)
184 call json_get(json,
"scalar_field", this%scalar_name)
187 if_time_dependent, .false.)
189 if (if_time_dependent)
then
195 if (
size(g_tmp) == 3)
then
198 call neko_error(
"MOST WM: The gravity vector should have exactly 3 components")
203 write(log_buf,
'(A, A)')
'Model : MOST'
205 write(log_buf,
'(A, A)')
'scalar_name : ', trim(this%scalar_name)
207 write(log_buf,
'(A, A)')
'bc_type : ', trim(this%bc_type)
209 write(log_buf,
'(A, E15.7)')
'bc_value : ', this%bc_value
211 write(log_buf,
'(A, E15.7)')
'kappa : ', this%kappa
213 write(log_buf,
'(A, E15.7)')
'z0 : ', this%z0
215 write(log_buf,
'(A, E15.7)')
'z0h : ', this%z0h_in
217 write(log_buf,
'(A, E15.7)')
'Pr : ', this%Pr
219 write(log_buf,
'(A, 3(E15.7,1X))')
'g : ', this%g
229 class(
most_t),
intent(inout) :: this
230 integer,
intent(in) :: msk(:)
231 integer,
intent(in) :: facet(:)
235 call this%finalize_base(msk, facet)
237 call this%Ri_b%init(this%n_nodes)
238 call this%L_ob%init(this%n_nodes)
239 call this%utau%init(this%n_nodes)
240 call this%magu%init(this%n_nodes)
241 call this%ti%init(this%n_nodes)
242 call this%ts%init(this%n_nodes)
243 call this%q%init(this%n_nodes)
245 call this%mu_w%init(this%n_nodes)
246 call this%rho_w%init(this%n_nodes)
248 allocate(this%h_x_idx(this%n_nodes))
249 allocate(this%h_y_idx(this%n_nodes))
250 allocate(this%h_z_idx(this%n_nodes))
252 call device_map(this%h_x_idx, this%h_x_idx_d, this%n_nodes)
253 call device_map(this%h_y_idx, this%h_y_idx_d, this%n_nodes)
254 call device_map(this%h_z_idx, this%h_z_idx_d, this%n_nodes)
257 do i = 1, this%n_nodes
261 this%h_x_idx(i) = this%h_index
265 this%h_x_idx(i) = - this%h_index
270 this%h_y_idx(i) = this%h_index
274 this%h_y_idx(i) = - this%h_index
279 this%h_z_idx(i) = this%h_index
283 this%h_z_idx(i) = - this%h_index
285 call neko_error(
"The face index is not correct (most.f90)")
290 call device_memcpy(this%h_x_idx, this%h_x_idx_d, this%n_nodes, &
292 call device_memcpy(this%h_y_idx, this%h_y_idx_d, this%n_nodes, &
294 call device_memcpy(this%h_z_idx, this%h_z_idx_d, this%n_nodes, &
301 class(
most_t),
intent(inout) :: this
305 this%mu%size(), this%mu_w%size())
307 this%rho%size(), this%rho_w%size())
310 this%mu%size(), this%mu_w%size())
312 this%rho%size(), this%rho_w%size())
330 coef, msk, facet, h_index, kappa, g, Pr, z0, &
331 z0h_in, bc_type, bc_value)
332 class(
most_t),
intent(inout) :: this
333 character(len=*),
intent(in) :: scheme_name
334 character(len=*),
intent(in) :: bc_type
335 character(len=*),
intent(in) :: scalar_name
336 type(
coef_t),
intent(in) :: coef
337 integer,
intent(in) :: msk(:)
338 integer,
intent(in) :: facet(:)
339 integer,
intent(in) :: h_index
340 real(kind=
rp),
intent(in) :: g(3)
341 real(kind=
rp) :: g_mag, g_dot_n, cos_alpha, max_ang
343 real(kind=
rp),
intent(in) :: kappa
344 real(kind=
rp),
intent(in) :: z0, z0h_in, bc_value, pr
345 character(len=LOG_SIZE) :: log_buf
348 call this%init_base(scheme_name, coef, msk, facet, h_index)
355 this%bc_type = bc_type
356 this%bc_value = bc_value
357 this%scalar_name = scalar_name
359 call this%mu_w%init(this%n_nodes)
360 call this%rho_w%init(this%n_nodes)
363 g_mag = sqrt(sum(g**2))
364 if (g_mag < 1.0e-6_rp)
then
365 call neko_error(
"MOST WM: Gravity magnitude is zero. Check your input configuration.")
370 do i = 1, this%n_nodes
371 g_dot_n = abs(g(1)*this%n_x%x(i) + g(2)*this%n_y%x(i) + g(3)*this%n_z%x(i))
372 cos_alpha = g_dot_n / g_mag
373 max_ang =
max(max_ang, acos(min(1.0_rp, cos_alpha)))
375 max_ang = max_ang * 180.0_rp / (4.0_rp * atan(1.0_rp))
376 if (max_ang > 8.0_rp)
then
377 write(log_buf,
'(A, F6.2, A)')
"MOST WM: Significant gravity-normal misalignment (max ", &
378 max_ang,
" deg). Stability corrections will use projected gravity."
383 if (any(this%h%x(1:this%n_nodes) .le. this%z0))
then
384 call neko_error(
"MOST WM: Sampling height h must be greater than roughness z0.")
385 else if ( (this%z0h_in .gt. 0.0_rp) .and. (any(this%h%x(1:this%n_nodes) .le. this%z0h_in)) )
then
386 call neko_error(
"MOST WM: Sampling height h must be greater than thermal roughness z0h.")
387 else if (this%z0 .eq. 0.0_rp)
then
388 call neko_error(
"MOST WM: Roughness z0 must be greater than 0.")
389 else if (this%z0h_in .eq. 0.0_rp)
then
390 call neko_error(
"MOST WM: Thermal roughness z0h must be greater than 0.")
397 class(
most_t),
intent(inout) :: this
399 if (
allocated(this%bc_type))
then
400 deallocate(this%bc_type)
403 if (
allocated(this%scalar_name))
then
404 deallocate(this%scalar_name)
407 call this%mu_w%free()
408 call this%rho_w%free()
409 call this%free_base()
411 call this%Ri_b%free()
412 call this%L_ob%free()
413 call this%utau%free()
414 call this%magu%free()
419 if (
allocated(this%h_x_idx))
then
420 deallocate(this%h_x_idx)
422 if (c_associated(this%h_x_idx_d))
then
426 if (
allocated(this%h_y_idx))
then
427 deallocate(this%h_y_idx)
429 if (c_associated(this%h_y_idx_d))
then
433 if (
allocated(this%h_z_idx))
then
434 deallocate(this%h_z_idx)
436 if (c_associated(this%h_z_idx_d))
then
446 class(
most_t),
intent(inout) :: this
447 real(kind=
rp),
intent(in) :: t
448 integer,
intent(in) :: tstep
453 real(kind=
rp),
pointer :: updated_bc_value
456 call this%extract_properties()
465 this%bc_value = updated_bc_value
470 this%ind_r_d, this%ind_s_d, this%ind_t_d, &
471 this%ind_e_d, this%n_x%x_d, this%n_y%x_d, this%n_z%x_d, &
472 this%h%x_d, this%tau_x%x_d, this%tau_y%x_d, &
473 this%tau_z%x_d, this%n_nodes, u%Xh%lx, this%kappa, &
474 this%mu_w%x_d, this%rho_w%x_d, this%g, this%Pr, this%z0, this%z0h_in, &
475 this%bc_type, this%bc_value, tstep, this%Ri_b%x_d, &
476 this%L_ob%x_d, this%utau%x_d, this%magu%x_d, this%ti%x_d, this%ts%x_d,&
477 this%q%x_d, this%h_x_idx_d, this%h_y_idx_d, this%h_z_idx_d)
480 this%ind_s, this%ind_t, this%ind_e, this%n_x%x, &
481 this%n_y%x, this%n_z%x, this%h%x, this%tau_x%x, &
482 this%tau_y%x, this%tau_z%x, this%n_nodes, u%Xh%lx, &
483 u%msh%nelv, this%kappa, this%mu_w%x, this%rho_w%x, &
484 this%g, this%Pr, this%z0, this%z0h_in, this%bc_type, &
485 this%bc_value, tstep, this%Ri_b%x, this%L_ob%x, &
486 this%utau%x, this%magu%x, this%ti%x, this%ts%x, &
487 this%q%x, this%h_x_idx, this%h_y_idx, this%h_z_idx)
491 this%utau, this%magu, this%ti, this%ts, this%q, &
492 this%n_nodes, this%bc_value)
497 character(len=LOG_SIZE) :: log_buf
498 integer,
intent(in) :: n_nodes
499 real(kind=
rp),
intent(in) :: bc_value
500 type(
vector_t),
intent(in) :: ri_b, l_ob, utau
501 type(
vector_t),
intent(in) :: magu, ti, ts, q
503 call neko_log%section(
"Wall model diagnostics")
504 write(log_buf,
'(A)')
'--- sum --- '
505 call neko_log%message(trim(log_buf))
506 write(log_buf,
'(A,3E15.7)')
"Ri_b: ",&
509 call neko_log%message(trim(log_buf))
511 write(log_buf,
'(A,3E15.7)')
"L_ob: ", &
514 call neko_log%message(trim(log_buf))
516 write(log_buf,
'(A,3E15.7)')
"utau: ", &
519 call neko_log%message(trim(log_buf))
521 write(log_buf,
'(A,3E15.7)')
"magu: ", &
524 call neko_log%message(trim(log_buf))
526 write(log_buf,
'(A,3E15.7)')
"ti: ", &
529 call neko_log%message(trim(log_buf))
531 write(log_buf,
'(A,3E15.7)')
"ts: ", &
534 call neko_log%message(trim(log_buf))
536 write(log_buf,
'(A,3E15.7)')
"q: ", &
539 call neko_log%message(trim(log_buf))
541 write(log_buf,
'(A,E15.7)')
"bc_value: ", bc_value
542 call neko_log%message(trim(log_buf))
__inline__ __device__ void nonlinear_index(const int idx, const int lx, int *index)
__global__ void most_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)
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
subroutine, public device_free(x_d)
Deallocate memory on the 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 .
Implements the CPU kernel for the most_t type.
subroutine, public most_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 MOST.
Implements the device kernel for the most_t type.
subroutine, public most_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 most_init(this, scheme_name, coef, msk, facet, h_index, json)
Constructor from JSON.
subroutine most_finalize(this, msk, facet)
Finalize the construction using the mask and facet arrays of the bc.
subroutine most_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 most_free(this)
Destructor for the most_t (base) class.
subroutine most_log_diagnostics(ri_b, l_ob, utau, magu, ti, ts, q, n_nodes, bc_value)
subroutine most_extract_properties(this)
Extract the values of rho and mu at the boundary.
subroutine most_partial_init(this, coef, json)
Constructor from JSON.
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...
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 based on the Monin-Obukhov Similarity Theory for atmospheric boundary layer flows....
Base abstract type for wall-stress models for wall-modelled LES.