Neko 1.99.6
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
entropy_viscosity.f90
Go to the documentation of this file.
1! Copyright (c) 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!
34 use num_types, only : rp
36 use json_module, only : json_file
38 use field, only : field_t
41 use coefs, only : coef_t
42 use dofmap, only : dofmap_t
43 use time_state, only : time_state_t
45 use operators, only : div
46 use math, only : glmax, absval
48 use mesh, only : mesh_t
49 use space, only : space_t
50 use gather_scatter, only : gs_t
51 use gs_ops, only : gs_op_add
60 use entropy_viscosity_device, only : &
66 implicit none
67 private
68
69 type, public, extends(regularization_t) :: entropy_viscosity_t
70 real(kind=rp) :: c_avisc_entropy
71 real(kind=rp) :: c_avisc_low
72 type(field_t) :: entropy_residual
73 type(field_series_t) :: s_lag
74 type(field_t), pointer :: s => null()
75 type(field_t), pointer :: u => null()
76 type(field_t), pointer :: v => null()
77 type(field_t), pointer :: w => null()
78 type(field_t), pointer :: h => null()
79 type(field_t), pointer :: max_wave_speed => null()
80 type(mesh_t), pointer :: msh => null()
81 type(space_t), pointer :: xh => null()
82 type(gs_t), pointer :: gs => null()
83 contains
84 procedure, pass(this) :: init => entropy_viscosity_init
85 procedure, pass(this) :: free => entropy_viscosity_free
86 procedure, pass(this) :: compute => entropy_viscosity_compute
87 procedure, pass(this) :: update_lag => entropy_viscosity_update_lag
88 procedure, pass(this), private :: compute_residual => &
90 procedure, pass(this), private :: compute_viscosity => &
92 procedure, pass(this), private :: smooth_viscosity => &
94 procedure, pass(this), private :: apply_element_max => &
96 procedure, pass(this), private :: low_order_viscosity => &
98 end type entropy_viscosity_t
99
101
102contains
103
104 subroutine entropy_viscosity_init(this, json, coef, dof, reg_coeff)
105 class(entropy_viscosity_t), intent(inout) :: this
106 type(json_file), intent(inout) :: json
107 type(coef_t), intent(in), target :: coef
108 type(dofmap_t), intent(in), target :: dof
109 type(field_t), intent(in), target :: reg_coeff
110
111 call this%init_base(json, coef, dof, reg_coeff)
112
113 call json_get_or_default(json, 'c_avisc_low', this%c_avisc_low, 1.0_rp)
114 call json_get_or_default(json, 'c_avisc_entropy', &
115 this%c_avisc_entropy, 1.0_rp)
116
117 call this%entropy_residual%init(dof, 'entropy_residual')
118
119 nullify(this%S)
120 nullify(this%u)
121 nullify(this%v)
122 nullify(this%w)
123 nullify(this%h)
124 nullify(this%max_wave_speed)
125 nullify(this%msh)
126 nullify(this%Xh)
127 nullify(this%gs)
128
129 end subroutine entropy_viscosity_init
130
131 subroutine entropy_viscosity_free(this)
132 class(entropy_viscosity_t), intent(inout) :: this
133
134 call this%free_base()
135 call this%entropy_residual%free()
136 call this%S_lag%free()
137
138 nullify(this%S)
139 nullify(this%u)
140 nullify(this%v)
141 nullify(this%w)
142 nullify(this%h)
143 nullify(this%max_wave_speed)
144 nullify(this%msh)
145 nullify(this%Xh)
146 nullify(this%gs)
147
148 end subroutine entropy_viscosity_free
149
150 subroutine entropy_viscosity_compute(this, time, tstep, dt)
151 class(entropy_viscosity_t), intent(inout) :: this
152 type(time_state_t), intent(in) :: time
153 integer, intent(in) :: tstep
154 real(kind=rp), intent(in) :: dt
155
156 call this%compute_residual(tstep, dt, time%dtlag)
157 call this%compute_viscosity(tstep)
158
159 end subroutine entropy_viscosity_compute
160
161 subroutine entropy_viscosity_compute_residual(this, tstep, dt, dt_lag)
162 class(entropy_viscosity_t), intent(inout) :: this
163 integer, intent(in) :: tstep
164 real(kind=rp), intent(in) :: dt
165 real(kind=rp), intent(in) :: dt_lag(10)
166 integer :: n
167 type(field_t), pointer :: us_field, vs_field, ws_field, div_field
168 integer :: temp_indices(4)
169 real(kind=rp) :: bdf_coeffs(4)
170 type(bdf_time_scheme_t) :: bdf_scheme
171 real(kind=rp) :: dt_local(10)
172
173 if (tstep .le. 3) then
174 return
175 end if
176
177 n = this%dof%size()
178 call field_cfill(this%entropy_residual, 0.0_rp, n)
179
180 bdf_coeffs = 0.0_rp
181 dt_local = dt_lag
182
183 call bdf_scheme%compute_coeffs(bdf_coeffs, dt_local, 3)
184
185 if (neko_bcknd_device .eq. 1) then
187 this%entropy_residual%x_d, &
188 this%S%x_d, this%S_lag%lf(1)%x_d, &
189 this%S_lag%lf(2)%x_d, this%S_lag%lf(3)%x_d, &
190 bdf_coeffs, dt, n)
191 else
193 this%entropy_residual%x, &
194 this%S%x, this%S_lag%lf(1)%x, &
195 this%S_lag%lf(2)%x, this%S_lag%lf(3)%x, &
196 bdf_coeffs, dt, n)
197 end if
198
199 call neko_scratch_registry%request_field(us_field, temp_indices(1), .false.)
200 call neko_scratch_registry%request_field(vs_field, temp_indices(2), .false.)
201 call neko_scratch_registry%request_field(ws_field, temp_indices(3), .false.)
202 call neko_scratch_registry%request_field(div_field, temp_indices(4), &
203 .false.)
204
205 if (neko_bcknd_device .eq. 1) then
206 call device_col3(us_field%x_d, this%u%x_d, this%S%x_d, n)
207 call device_col3(vs_field%x_d, this%v%x_d, this%S%x_d, n)
208 call device_col3(ws_field%x_d, this%w%x_d, this%S%x_d, n)
209 else
210 call entropy_viscosity_col3_vector_cpu(us_field%x, vs_field%x, &
211 ws_field%x, this%u%x, this%v%x, this%w%x, this%S%x, n)
212 end if
213
214 call div(div_field%x, us_field%x, vs_field%x, ws_field%x, this%coef)
215
216 if (neko_bcknd_device .eq. 1) then
217 call device_memcpy(this%entropy_residual%x, this%entropy_residual%x_d, &
218 n, device_to_host, sync = .false.)
219 call device_memcpy(div_field%x, div_field%x_d, n, device_to_host, &
220 sync = .true.)
221 end if
222
223 call entropy_viscosity_abs_add_cpu(this%entropy_residual%x, div_field%x, n)
224
225 if (neko_bcknd_device .eq. 1) then
226 call device_memcpy(this%entropy_residual%x, this%entropy_residual%x_d, &
227 n, host_to_device, sync = .false.)
228 end if
229
230 call neko_scratch_registry%relinquish_field(temp_indices)
231
233
235 class(entropy_viscosity_t), intent(inout) :: this
236 integer, intent(in) :: tstep
237 integer :: n, temp_indices(1)
238 real(kind=rp) :: s_mean, n_s
239 type(field_t), pointer :: temp_field
240
241 n = this%dof%size()
242
243 if (tstep .le. 3) then
244 call field_cfill(this%reg_coeff, 0.0_rp, n)
245 return
246 end if
247
248 call neko_scratch_registry%request_field(temp_field, temp_indices(1), &
249 .false.)
250
251 call field_cfill(temp_field, 1.0_rp, n)
252 s_mean = field_glsum(this%S, n) / field_glsum(temp_field, n)
253
254 call field_copy(temp_field, this%S, n)
255 call field_cadd(temp_field, -s_mean, n)
256
257 if (neko_bcknd_device .eq. 1) then
258 call device_absval(temp_field%x_d, n)
259 call device_memcpy(temp_field%x, temp_field%x_d, n, device_to_host, &
260 sync = .true.)
261 else
262 call absval(temp_field%x, n)
263 end if
264
265 ! Normalization factor n_S = |S-S_mean|_inf
266 n_s = glmax(temp_field%x, n)
267
268 call neko_scratch_registry%relinquish_field(temp_indices)
269
270 if (n_s < 1.0e-12_rp) then
271 n_s = 1.0e-12_rp
272 end if
273
274 ! entropy viscosity = c_avisc_entropy * h^2 * entropy_residual / n_S
275 if (neko_bcknd_device .eq. 1) then
277 this%reg_coeff%x_d, this%entropy_residual%x_d, &
278 this%h%x_d, this%c_avisc_entropy, n_s, n)
279 else
281 this%reg_coeff%x, this%entropy_residual%x, &
282 this%h%x, this%c_avisc_entropy, n_s, n)
283 end if
284
285 ! artificial viscosity = min(entropy viscosity, low-order viscosity)
286 if (neko_bcknd_device .eq. 1) then
288 this%reg_coeff%x_d, this%h%x_d, this%max_wave_speed%x_d, &
289 this%c_avisc_low, n)
290 else
292 this%reg_coeff%x, this%h%x, this%max_wave_speed%x, &
293 this%c_avisc_low, n)
294 end if
295
296 call this%apply_element_max()
297
298 call this%smooth_viscosity()
299
301
305 class(entropy_viscosity_t), intent(inout) :: this
306 integer :: n
307 type(field_t), pointer :: temp_field, mult_field
308 integer :: temp_indices(2)
309
310 n = this%dof%size()
311
312 call neko_scratch_registry%request_field(temp_field, temp_indices(1), &
313 .false.)
314 call neko_scratch_registry%request_field(mult_field, temp_indices(2), &
315 .false.)
316
317 call field_copy(temp_field, this%reg_coeff, n)
318 call this%gs%op(temp_field, gs_op_add)
319
320 call field_cfill(mult_field, 1.0_rp, n)
321 call this%gs%op(mult_field, gs_op_add)
322
323 if (neko_bcknd_device .eq. 1) then
325 this%reg_coeff%x_d, temp_field%x_d, mult_field%x_d, n)
326 else
328 this%reg_coeff%x, temp_field%x, mult_field%x, n)
329 end if
330
331 call neko_scratch_registry%relinquish_field(temp_indices)
332
334
336 class(entropy_viscosity_t), intent(inout) :: this
337 integer :: lx
338
339 lx = this%Xh%lx
340
341 if (neko_bcknd_device .eq. 1) then
343 this%reg_coeff%x_d, lx, this%msh%nelv)
344 else
346 this%reg_coeff%x, lx, this%msh%nelv)
347 end if
348
350
351 subroutine entropy_viscosity_set_fields(this, S, u, v, w, h, max_wave_speed, &
352 msh, Xh, gs)
353 class(entropy_viscosity_t), intent(inout) :: this
354 type(field_t), target, intent(inout) :: s
355 type(field_t), target, intent(in) :: u, v, w, h, max_wave_speed
356 type(mesh_t), target, intent(in) :: msh
357 type(space_t), target, intent(in) :: xh
358 type(gs_t), target, intent(in) :: gs
359
360 this%S => s
361 this%u => u
362 this%v => v
363 this%w => w
364 this%h => h
365 this%max_wave_speed => max_wave_speed
366 this%msh => msh
367 this%Xh => xh
368 this%gs => gs
369
370 call this%S_lag%init(s, 3)
371
372 end subroutine entropy_viscosity_set_fields
373
375 class(entropy_viscosity_t), intent(inout) :: this
376
377 call this%S_lag%update()
378
379 end subroutine entropy_viscosity_update_lag
380
381 subroutine entropy_viscosity_col3_vector_cpu(us, vs, ws, u, v, w, S, n)
382 integer, intent(in) :: n
383 real(kind=rp), intent(out) :: us(n), vs(n), ws(n)
384 real(kind=rp), intent(in) :: u(n), v(n), w(n), s(n)
385 integer :: i
386
387 !OCL NORECURRENCE, NOVREC, NOALIAS
388 !DIR$ CONCURRENT
389 !DIR$ IVDEP
390 !GCC$ ivdep
391 !$omp parallel do simd
392 do i = 1, n
393 us(i) = u(i) * s(i)
394 vs(i) = v(i) * s(i)
395 ws(i) = w(i) * s(i)
396 end do
397 !$omp end parallel do simd
399
400 subroutine entropy_viscosity_abs_add_cpu(entropy_residual, div_field, n)
401 integer, intent(in) :: n
402 real(kind=rp), intent(inout) :: entropy_residual(n)
403 real(kind=rp), intent(in) :: div_field(n)
404 integer :: i
405
406 !OCL NORECURRENCE, NOVREC, NOALIAS
407 !DIR$ CONCURRENT
408 !DIR$ IVDEP
409 !GCC$ ivdep
410 !$omp parallel do simd
411 do i = 1, n
412 entropy_residual(i) = abs(entropy_residual(i) + div_field(i))
413 end do
414 !$omp end parallel do simd
415 end subroutine entropy_viscosity_abs_add_cpu
416
418 pure function entropy_viscosity_low_order(this, i) result(visc)
419 class(entropy_viscosity_t), intent(in) :: this
420 integer, intent(in) :: i
421 real(kind=rp) :: visc
422
423 visc = this%c_avisc_low * this%h%x(i,1,1,1) * this%max_wave_speed%x(i,1,1,1)
424
425 end function entropy_viscosity_low_order
426
427end module entropy_viscosity
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...
Compute the divergence of a vector field.
Definition operators.f90:85
Backward-differencing scheme for time integration.
Coefficients.
Definition coef.f90:34
real(kind=rp) function, public device_glsum(a_d, n, strm)
Sum a vector of length n.
subroutine, public device_absval(a_d, n, strm)
subroutine, public device_col3(a_d, b_d, c_d, n, strm)
Vector multiplication with 3 vectors .
Device abstraction, common interface for various accelerators.
Definition device.F90:34
integer, parameter, public host_to_device
Definition device.F90:48
integer, parameter, public device_to_host
Definition device.F90:48
Defines a mapping of the degrees of freedom.
Definition dofmap.f90:35
CPU backend for entropy viscosity regularization.
subroutine, public entropy_viscosity_compute_viscosity_cpu(reg_coeff, entropy_residual, h, c_avisc_entropy, n_s, n)
Compute viscosity from entropy residual on CPU.
subroutine, public entropy_viscosity_compute_residual_cpu(entropy_residual, s, s_lag1, s_lag2, s_lag3, bdf_coeffs, dt, n)
Compute entropy residual on CPU.
subroutine, public entropy_viscosity_smooth_divide_cpu(reg_coeff, temp_field, mult_field, n)
Divide by multiplicity for smoothing on CPU.
subroutine, public entropy_viscosity_clamp_to_low_order_cpu(reg_coeff, h, max_wave_speed, c_avisc_low, n)
Clamp regularization coefficient to low-order viscosity on CPU.
subroutine, public entropy_viscosity_apply_element_max_cpu(reg_coeff, lx, nelv)
Apply element-wise maximum on CPU.
Device backend for entropy viscosity regularization.
subroutine, public entropy_viscosity_smooth_divide_device(reg_coeff_d, temp_field_d, mult_field_d, n)
Divide by multiplicity for smoothing on device.
subroutine, public entropy_viscosity_clamp_to_low_order_device(reg_coeff_d, h_d, max_wave_speed_d, c_avisc_low, n)
Clamp regularization coefficient to low-order viscosity on device.
subroutine, public entropy_viscosity_apply_element_max_device(reg_coeff_d, lx, nelv)
Apply element-wise maximum on device.
subroutine, public entropy_viscosity_compute_residual_device(entropy_residual_d, s_d, s_lag1_d, s_lag2_d, s_lag3_d, bdf_coeffs, dt, n)
Compute entropy residual on device.
subroutine, public entropy_viscosity_compute_viscosity_device(reg_coeff_d, entropy_residual_d, h_d, c_avisc_entropy, n_s, n)
Compute viscosity from entropy residual on device.
subroutine entropy_viscosity_apply_element_max(this)
subroutine entropy_viscosity_abs_add_cpu(entropy_residual, div_field, n)
subroutine entropy_viscosity_col3_vector_cpu(us, vs, ws, u, v, w, s, n)
subroutine entropy_viscosity_update_lag(this)
subroutine entropy_viscosity_smooth_viscosity(this)
Cross-element smoothing via gather-scatter averaging. Averages viscosity values at shared nodes betwe...
subroutine entropy_viscosity_compute_viscosity(this, tstep)
subroutine entropy_viscosity_compute_residual(this, tstep, dt, dt_lag)
subroutine entropy_viscosity_compute(this, time, tstep, dt)
subroutine entropy_viscosity_init(this, json, coef, dof, reg_coeff)
subroutine entropy_viscosity_free(this)
pure real(kind=rp) function entropy_viscosity_low_order(this, i)
Compute low-order viscosity at point i: c_avisc_low * h * max_wave_speed.
subroutine, public entropy_viscosity_set_fields(this, s, u, v, w, h, max_wave_speed, msh, xh, gs)
subroutine, public field_cadd(a, s, n)
Add a scalar to vector .
subroutine, public field_cfill(a, c, n)
Set all elements to a constant c .
real(kind=rp) function, public field_glsum(a, n)
subroutine, public field_copy(a, b, n)
Copy a vector .
Contains the field_serties_t type.
Defines a field.
Definition field.f90:34
Gather-scatter.
Defines Gather-scatter operations.
Definition gs_ops.f90:34
integer, parameter, public gs_op_add
Definition gs_ops.f90:36
Utilities for retrieving parameters from the case files.
Definition math.f90:60
subroutine, public absval(a, n)
Take the absolute value of an array.
Definition math.f90:1640
real(kind=rp) function, public glmax(a, n)
Max of a vector of length n.
Definition math.f90:650
Defines a mesh.
Definition mesh.f90:34
Build configurations.
integer, parameter neko_bcknd_device
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12
Operators.
Definition operators.f90:34
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.
Defines a function space.
Definition space.f90:34
Module with things related to the simulation time.
Implicit backward-differencing scheme for time integration.
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:63
Stores a series (sequence) of fields, logically connected to a base field, and arranged according to ...
Gather-scatter kernel.
The function space for the SEM solution fields.
Definition space.f90:64
A struct that contains all info about the time, expand as needed.