Neko 1.99.9
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)
151 class(entropy_viscosity_t), intent(inout) :: this
152 type(time_state_t), intent(in) :: time
153
154 call this%compute_residual(time%tstep, &
155 real(time%dt, kind=rp), &
156 real(time%dtlag, kind=rp))
157
158 call this%compute_viscosity(time%tstep)
159
160 end subroutine entropy_viscosity_compute
161
162 subroutine entropy_viscosity_compute_residual(this, tstep, dt, dt_lag)
163 class(entropy_viscosity_t), intent(inout) :: this
164 integer, intent(in) :: tstep
165 real(kind=rp), intent(in) :: dt
166 real(kind=rp), intent(in) :: dt_lag(10)
167 integer :: n
168 type(field_t), pointer :: us_field, vs_field, ws_field, div_field
169 integer :: temp_indices(4)
170 real(kind=rp) :: bdf_coeffs(4)
171 type(bdf_time_scheme_t) :: bdf_scheme
172 real(kind=rp) :: dt_local(10)
173
174 if (tstep .le. 3) then
175 return
176 end if
177
178 n = this%dof%size()
179 call field_cfill(this%entropy_residual, 0.0_rp, n)
180
181 bdf_coeffs = 0.0_rp
182 dt_local = dt_lag
183
184 call bdf_scheme%compute_coeffs(bdf_coeffs, dt_local, 3)
185
186 if (neko_bcknd_device .eq. 1) then
188 this%entropy_residual%x_d, &
189 this%S%x_d, this%S_lag%lf(1)%x_d, &
190 this%S_lag%lf(2)%x_d, this%S_lag%lf(3)%x_d, &
191 bdf_coeffs, dt, n)
192 else
194 this%entropy_residual%x, &
195 this%S%x, this%S_lag%lf(1)%x, &
196 this%S_lag%lf(2)%x, this%S_lag%lf(3)%x, &
197 bdf_coeffs, dt, n)
198 end if
199
200 call neko_scratch_registry%request_field(us_field, temp_indices(1), .false.)
201 call neko_scratch_registry%request_field(vs_field, temp_indices(2), .false.)
202 call neko_scratch_registry%request_field(ws_field, temp_indices(3), .false.)
203 call neko_scratch_registry%request_field(div_field, temp_indices(4), &
204 .false.)
205
206 if (neko_bcknd_device .eq. 1) then
207 call device_col3(us_field%x_d, this%u%x_d, this%S%x_d, n)
208 call device_col3(vs_field%x_d, this%v%x_d, this%S%x_d, n)
209 call device_col3(ws_field%x_d, this%w%x_d, this%S%x_d, n)
210 else
211 call entropy_viscosity_col3_vector_cpu(us_field%x, vs_field%x, &
212 ws_field%x, this%u%x, this%v%x, this%w%x, this%S%x, n)
213 end if
214
215 call div(div_field%x, us_field%x, vs_field%x, ws_field%x, this%coef)
216
217 if (neko_bcknd_device .eq. 1) then
218 call device_memcpy(this%entropy_residual%x, this%entropy_residual%x_d, &
219 n, device_to_host, sync = .false.)
220 call device_memcpy(div_field%x, div_field%x_d, n, device_to_host, &
221 sync = .true.)
222 end if
223
224 call entropy_viscosity_abs_add_cpu(this%entropy_residual%x, div_field%x, n)
225
226 if (neko_bcknd_device .eq. 1) then
227 call device_memcpy(this%entropy_residual%x, this%entropy_residual%x_d, &
228 n, host_to_device, sync = .false.)
229 end if
230
231 call neko_scratch_registry%relinquish_field(temp_indices)
232
234
236 class(entropy_viscosity_t), intent(inout) :: this
237 integer, intent(in) :: tstep
238 integer :: n, temp_indices(1)
239 real(kind=rp) :: s_mean, n_s
240 type(field_t), pointer :: temp_field
241
242 n = this%dof%size()
243
244 if (tstep .le. 3) then
245 call field_cfill(this%reg_coeff, 0.0_rp, n)
246 return
247 end if
248
249 call neko_scratch_registry%request_field(temp_field, temp_indices(1), &
250 .false.)
251
252 call field_cfill(temp_field, 1.0_rp, n)
253 s_mean = field_glsum(this%S, n) / field_glsum(temp_field, n)
254
255 call field_copy(temp_field, this%S, n)
256 call field_cadd(temp_field, -s_mean, n)
257
258 if (neko_bcknd_device .eq. 1) then
259 call device_absval(temp_field%x_d, n)
260 call device_memcpy(temp_field%x, temp_field%x_d, n, device_to_host, &
261 sync = .true.)
262 else
263 call absval(temp_field%x, n)
264 end if
265
266 ! Normalization factor n_S = |S-S_mean|_inf
267 n_s = glmax(temp_field%x, n)
268
269 call neko_scratch_registry%relinquish_field(temp_indices)
270
271 if (n_s < 1.0e-12_rp) then
272 n_s = 1.0e-12_rp
273 end if
274
275 ! entropy viscosity = c_avisc_entropy * h^2 * entropy_residual / n_S
276 if (neko_bcknd_device .eq. 1) then
278 this%reg_coeff%x_d, this%entropy_residual%x_d, &
279 this%h%x_d, this%c_avisc_entropy, n_s, n)
280 else
282 this%reg_coeff%x, this%entropy_residual%x, &
283 this%h%x, this%c_avisc_entropy, n_s, n)
284 end if
285
286 ! artificial viscosity = min(entropy viscosity, low-order viscosity)
287 if (neko_bcknd_device .eq. 1) then
289 this%reg_coeff%x_d, this%h%x_d, this%max_wave_speed%x_d, &
290 this%c_avisc_low, n)
291 else
293 this%reg_coeff%x, this%h%x, this%max_wave_speed%x, &
294 this%c_avisc_low, n)
295 end if
296
297 call this%apply_element_max()
298
299 call this%smooth_viscosity()
300
302
306 class(entropy_viscosity_t), intent(inout) :: this
307 integer :: n
308 type(field_t), pointer :: temp_field, mult_field
309 integer :: temp_indices(2)
310
311 n = this%dof%size()
312
313 call neko_scratch_registry%request_field(temp_field, temp_indices(1), &
314 .false.)
315 call neko_scratch_registry%request_field(mult_field, temp_indices(2), &
316 .false.)
317
318 call field_copy(temp_field, this%reg_coeff, n)
319 call this%gs%op(temp_field, gs_op_add)
320
321 call field_cfill(mult_field, 1.0_rp, n)
322 call this%gs%op(mult_field, gs_op_add)
323
324 if (neko_bcknd_device .eq. 1) then
326 this%reg_coeff%x_d, temp_field%x_d, mult_field%x_d, n)
327 else
329 this%reg_coeff%x, temp_field%x, mult_field%x, n)
330 end if
331
332 call neko_scratch_registry%relinquish_field(temp_indices)
333
335
337 class(entropy_viscosity_t), intent(inout) :: this
338 integer :: lx
339
340 lx = this%Xh%lx
341
342 if (neko_bcknd_device .eq. 1) then
344 this%reg_coeff%x_d, lx, this%msh%nelv)
345 else
347 this%reg_coeff%x, lx, this%msh%nelv)
348 end if
349
351
352 subroutine entropy_viscosity_set_fields(this, S, u, v, w, h, max_wave_speed, &
353 msh, Xh, gs)
354 class(entropy_viscosity_t), intent(inout) :: this
355 type(field_t), target, intent(inout) :: s
356 type(field_t), target, intent(in) :: u, v, w, h, max_wave_speed
357 type(mesh_t), target, intent(in) :: msh
358 type(space_t), target, intent(in) :: xh
359 type(gs_t), target, intent(in) :: gs
360
361 this%S => s
362 this%u => u
363 this%v => v
364 this%w => w
365 this%h => h
366 this%max_wave_speed => max_wave_speed
367 this%msh => msh
368 this%Xh => xh
369 this%gs => gs
370
371 call this%S_lag%init(s, 3)
372
373 end subroutine entropy_viscosity_set_fields
374
376 class(entropy_viscosity_t), intent(inout) :: this
377
378 call this%S_lag%update()
379
380 end subroutine entropy_viscosity_update_lag
381
382 subroutine entropy_viscosity_col3_vector_cpu(us, vs, ws, u, v, w, S, n)
383 integer, intent(in) :: n
384 real(kind=rp), intent(out) :: us(n), vs(n), ws(n)
385 real(kind=rp), intent(in) :: u(n), v(n), w(n), s(n)
386 integer :: i
387
388 !OCL NORECURRENCE, NOVREC, NOALIAS
389 !DIR$ CONCURRENT
390 !DIR$ IVDEP
391 !GCC$ ivdep
392 !$omp parallel do simd
393 do i = 1, n
394 us(i) = u(i) * s(i)
395 vs(i) = v(i) * s(i)
396 ws(i) = w(i) * s(i)
397 end do
398 !$omp end parallel do simd
400
401 subroutine entropy_viscosity_abs_add_cpu(entropy_residual, div_field, n)
402 integer, intent(in) :: n
403 real(kind=rp), intent(inout) :: entropy_residual(n)
404 real(kind=rp), intent(in) :: div_field(n)
405 integer :: i
406
407 !OCL NORECURRENCE, NOVREC, NOALIAS
408 !DIR$ CONCURRENT
409 !DIR$ IVDEP
410 !GCC$ ivdep
411 !$omp parallel do simd
412 do i = 1, n
413 entropy_residual(i) = abs(entropy_residual(i) + div_field(i))
414 end do
415 !$omp end parallel do simd
416 end subroutine entropy_viscosity_abs_add_cpu
417
419 pure function entropy_viscosity_low_order(this, i) result(visc)
420 class(entropy_viscosity_t), intent(in) :: this
421 integer, intent(in) :: i
422 real(kind=rp) :: visc
423
424 visc = this%c_avisc_low * this%h%x(i,1,1,1) * this%max_wave_speed%x(i,1,1,1)
425
426 end function entropy_viscosity_low_order
427
428end 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:86
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)
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:1643
real(kind=rp) function, public glmax(a, n)
Max of a vector of length n.
Definition math.f90:653
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:14
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:93
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.