Neko 1.99.6
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
compressible_res_cpu.f90
Go to the documentation of this file.
1! Copyright (c) 2025-2026, 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!
39 use field, only : field_t
40 use ax_product, only : ax_t
41 use coefs, only : coef_t
42 use gather_scatter, only : gs_t
43 use num_types, only : rp
44 use operators, only : div, grad, opgrad, rotate_cyc
45 use gs_ops, only : gs_op_add
48 use field_list, only : field_list_t
51 use bc_list, only : bc_list_t
52 use time_state, only : time_state_t
53 implicit none
54 private
55
57 contains
58 procedure, nopass :: step => advance_primitive_variables_cpu
59 procedure, nopass :: evaluate_rhs => evaluate_rhs_cpu
61
67 real(kind=rp), public :: compressible_res_cpu_gamma = 1.4_rp
68
69
70contains
89 subroutine advance_primitive_variables_cpu(rho_field, m_x, m_y, m_z, &
90 E, p, u, v, w, Ax, &
91 Ax_stress, coef, gs, h, artificial_visc, mu, kappa, bcs_vel, time, &
92 rk_scheme, dt)
93 type(field_t), intent(inout) :: rho_field, m_x, m_y, m_z, e
94 type(field_t), intent(in) :: p, u, v, w, h, artificial_visc, mu, kappa
95 class(ax_t), intent(inout) :: Ax, Ax_stress
96 type(coef_t), intent(inout) :: coef
97 type(gs_t), intent(inout) :: gs
98 type(bc_list_t), intent(inout) :: bcs_vel
99 type(time_state_t), intent(in) :: time
100 class(runge_kutta_time_scheme_t), intent(in) :: rk_scheme
101 real(kind=rp), intent(in) :: dt
102 integer :: n, s, i, j, l
103 type(field_t), pointer :: k_rho_1, k_rho_2, k_rho_3, k_rho_4, &
104 k_m_x_1, k_m_x_2, k_m_x_3, k_m_x_4, &
105 k_m_y_1, k_m_y_2, k_m_y_3, k_m_y_4, &
106 k_m_z_1, k_m_z_2, k_m_z_3, k_m_z_4, &
107 k_E_1, k_E_2, k_E_3, k_E_4, &
108 temp_rho, temp_m_x, temp_m_y, temp_m_z, temp_E, &
109 temp_p, temp_u, temp_v, temp_w, temp_ruvw
110 integer :: tmp_indices(30)
111 type(field_list_t) :: k_rho, k_m_x, k_m_y, k_m_z, k_E
112 ! These contiguous pointers are necessary to ensure that
113 ! the Fujitsu compiler properly vectorizes the loop nests
114 real(kind=rp), contiguous, pointer :: k_rho_ptr(:,:,:,:)
115 real(kind=rp), contiguous, pointer :: k_m_x_ptr(:,:,:,:)
116 real(kind=rp), contiguous, pointer :: k_m_y_ptr(:,:,:,:)
117 real(kind=rp), contiguous, pointer :: k_m_z_ptr(:,:,:,:)
118 real(kind=rp), contiguous, pointer :: k_e_ptr(:,:,:,:)
119
120 n = p%dof%size()
121 s = rk_scheme%order
122 call neko_scratch_registry%request_field(k_rho_1, tmp_indices(1), .true.)
123 call neko_scratch_registry%request_field(k_rho_2, tmp_indices(2), .true.)
124 call neko_scratch_registry%request_field(k_rho_3, tmp_indices(3), .true.)
125 call neko_scratch_registry%request_field(k_rho_4, tmp_indices(4), .true.)
126 call neko_scratch_registry%request_field(k_m_x_1, tmp_indices(5), .true.)
127 call neko_scratch_registry%request_field(k_m_x_2, tmp_indices(6), .true.)
128 call neko_scratch_registry%request_field(k_m_x_3, tmp_indices(7), .true.)
129 call neko_scratch_registry%request_field(k_m_x_4, tmp_indices(8), .true.)
130 call neko_scratch_registry%request_field(k_m_y_1, tmp_indices(9), .true.)
131 call neko_scratch_registry%request_field(k_m_y_2, tmp_indices(10), .true.)
132 call neko_scratch_registry%request_field(k_m_y_3, tmp_indices(11), .true.)
133 call neko_scratch_registry%request_field(k_m_y_4, tmp_indices(12), .true.)
134 call neko_scratch_registry%request_field(k_m_z_1, tmp_indices(13), .true.)
135 call neko_scratch_registry%request_field(k_m_z_2, tmp_indices(14), .true.)
136 call neko_scratch_registry%request_field(k_m_z_3, tmp_indices(15), .true.)
137 call neko_scratch_registry%request_field(k_m_z_4, tmp_indices(16), .true.)
138 call neko_scratch_registry%request_field(k_e_1, tmp_indices(17), .true.)
139 call neko_scratch_registry%request_field(k_e_2, tmp_indices(18), .true.)
140 call neko_scratch_registry%request_field(k_e_3, tmp_indices(19), .true.)
141 call neko_scratch_registry%request_field(k_e_4, tmp_indices(20), .true.)
142 call neko_scratch_registry%request_field(temp_rho, tmp_indices(21), .false.)
143 call neko_scratch_registry%request_field(temp_m_x, tmp_indices(22), .false.)
144 call neko_scratch_registry%request_field(temp_m_y, tmp_indices(23), .false.)
145 call neko_scratch_registry%request_field(temp_m_z, tmp_indices(24), .false.)
146 call neko_scratch_registry%request_field(temp_e, tmp_indices(25), .false.)
147 call neko_scratch_registry%request_field(temp_p, tmp_indices(26), .false.)
148 call neko_scratch_registry%request_field(temp_u, tmp_indices(27), .false.)
149 call neko_scratch_registry%request_field(temp_v, tmp_indices(28), .false.)
150 call neko_scratch_registry%request_field(temp_w, tmp_indices(29), .false.)
151 call neko_scratch_registry%request_field(temp_ruvw, tmp_indices(30), &
152 .false.)
153
154 ! Initialize Runge-Kutta stage variables for each conserved quantity
155 call k_rho%init(4)
156 call k_rho%assign(1, k_rho_1)
157 call k_rho%assign(2, k_rho_2)
158 call k_rho%assign(3, k_rho_3)
159 call k_rho%assign(4, k_rho_4)
160 call k_m_x%init(4)
161 call k_m_x%assign(1, k_m_x_1)
162 call k_m_x%assign(2, k_m_x_2)
163 call k_m_x%assign(3, k_m_x_3)
164 call k_m_x%assign(4, k_m_x_4)
165 call k_m_y%init(4)
166 call k_m_y%assign(1, k_m_y_1)
167 call k_m_y%assign(2, k_m_y_2)
168 call k_m_y%assign(3, k_m_y_3)
169 call k_m_y%assign(4, k_m_y_4)
170 call k_m_z%init(4)
171 call k_m_z%assign(1, k_m_z_1)
172 call k_m_z%assign(2, k_m_z_2)
173 call k_m_z%assign(3, k_m_z_3)
174 call k_m_z%assign(4, k_m_z_4)
175 call k_e%init(4)
176 call k_e%assign(1, k_e_1)
177 call k_e%assign(2, k_e_2)
178 call k_e%assign(3, k_e_3)
179 call k_e%assign(4, k_e_4)
180
182 any(mu%x .ne. 0.0_rp) .or. any(kappa%x .ne. 0.0_rp)
183 compressible_res_cpu_add_physical_stress = any(mu%x .ne. 0.0_rp)
184
185 ! Loop over Runge-Kutta stages. One parallel region per stage covers
186 ! both the initial copy and all (i-1) accumulation sweeps.
187 do i = 1, s
188 !$omp parallel private(j, l, k_rho_ptr) &
189 !$omp& private(k_m_x_ptr, k_m_y_ptr, k_m_z_ptr, k_E_ptr)
190
191 ! Copy current solution state to temporary arrays for this RK stage
192 !OCL NORECURRENCE, NOVREC, NOALIAS
193 !DIR$ CONCURRENT
194 !DIR$ IVDEP
195 !GCC$ ivdep
196 !$omp do simd
197 do l = 1, n
198 temp_rho%x(l,1,1,1) = rho_field%x(l,1,1,1)
199 temp_m_x%x(l,1,1,1) = m_x%x(l,1,1,1)
200 temp_m_y%x(l,1,1,1) = m_y%x(l,1,1,1)
201 temp_m_z%x(l,1,1,1) = m_z%x(l,1,1,1)
202 temp_e%x(l,1,1,1) = e%x(l,1,1,1)
203 end do
204 !$omp end do simd
205
206 ! Accumulate previous stage contributions using RK coefficients.
207 ! Each thread independently sets its private k_*_ptr aliases before
208 ! the worksharing loop; the implicit barrier at end of !$omp do simd
209 ! synchronises threads between j iterations.
210 do j = 1, i-1
211 k_rho_ptr => k_rho%items(j)%ptr%x
212 k_m_x_ptr => k_m_x%items(j)%ptr%x
213 k_m_y_ptr => k_m_y%items(j)%ptr%x
214 k_m_z_ptr => k_m_z%items(j)%ptr%x
215 k_e_ptr => k_e%items(j)%ptr%x
216
217 !OCL NORECURRENCE, NOVREC, NOALIAS
218 !DIR$ CONCURRENT
219 !DIR$ IVDEP
220 !GCC$ ivdep
221 !$omp do simd
222 do l = 1, n
223 temp_rho%x(l,1,1,1) = temp_rho%x(l,1,1,1) + &
224 dt * rk_scheme%coeffs_A(i, j) * k_rho_ptr(l,1,1,1)
225 temp_m_x%x(l,1,1,1) = temp_m_x%x(l,1,1,1) + &
226 dt * rk_scheme%coeffs_A(i, j) * k_m_x_ptr(l,1,1,1)
227 temp_m_y%x(l,1,1,1) = temp_m_y%x(l,1,1,1) + &
228 dt * rk_scheme%coeffs_A(i, j) * k_m_y_ptr(l,1,1,1)
229 temp_m_z%x(l,1,1,1) = temp_m_z%x(l,1,1,1) + &
230 dt * rk_scheme%coeffs_A(i, j) * k_m_z_ptr(l,1,1,1)
231 temp_e%x(l,1,1,1) = temp_e%x(l,1,1,1) + &
232 dt * rk_scheme%coeffs_A(i, j) * k_e_ptr(l,1,1,1)
233 end do
234 !$omp end do simd
235 end do
236 !$omp end parallel
237
238 ! Evaluate RHS terms using primitive variables from the RK stage state.
239 call compressible_ops_cpu_update_uvw(temp_u%x, temp_v%x, temp_w%x, &
240 temp_m_x%x, temp_m_y%x, temp_m_z%x, temp_rho%x, n)
242 call bcs_vel%apply_vector(temp_u%x, temp_v%x, temp_w%x, n, time, &
243 strong = .true.)
244 end if
245 call compressible_ops_cpu_update_mxyz_p_ruvw(temp_m_x%x, temp_m_y%x, &
246 temp_m_z%x, temp_p%x, temp_ruvw%x, temp_u%x, temp_v%x, temp_w%x, &
247 temp_e%x, temp_rho%x, compressible_res_cpu_gamma, n)
248
249 call evaluate_rhs_cpu(k_rho%items(i)%ptr, k_m_x%items(i)%ptr, &
250 k_m_y%items(i)%ptr, k_m_z%items(i)%ptr, &
251 k_e%items(i)%ptr, &
252 temp_rho, temp_m_x, temp_m_y, temp_m_z, temp_e, &
253 temp_p, temp_u, temp_v, temp_w, ax, &
254 ax_stress, coef, gs, h, artificial_visc, mu, kappa)
255 end do
256
257 ! Update the solution. Single parallel region covers all s stages.
258 !$omp parallel default(shared) private(i, l, k_rho_ptr) &
259 !$omp& private(k_m_x_ptr, k_m_y_ptr, k_m_z_ptr, k_E_ptr)
260 do i = 1, s
261 k_rho_ptr => k_rho%items(i)%ptr%x
262 k_m_x_ptr => k_m_x%items(i)%ptr%x
263 k_m_y_ptr => k_m_y%items(i)%ptr%x
264 k_m_z_ptr => k_m_z%items(i)%ptr%x
265 k_e_ptr => k_e%items(i)%ptr%x
266
267 !OCL NORECURRENCE, NOVREC, NOALIAS
268 !DIR$ CONCURRENT
269 !DIR$ IVDEP
270 !GCC$ ivdep
271 !$omp do simd
272 do l = 1, n
273 rho_field%x(l,1,1,1) = rho_field%x(l,1,1,1) + &
274 dt * rk_scheme%coeffs_b(i) * k_rho_ptr(l,1,1,1)
275 m_x%x(l,1,1,1) = m_x%x(l,1,1,1) + &
276 dt * rk_scheme%coeffs_b(i) * k_m_x_ptr(l,1,1,1)
277 m_y%x(l,1,1,1) = m_y%x(l,1,1,1) + &
278 dt * rk_scheme%coeffs_b(i) * k_m_y_ptr(l,1,1,1)
279 m_z%x(l,1,1,1) = m_z%x(l,1,1,1) + &
280 dt * rk_scheme%coeffs_b(i) * k_m_z_ptr(l,1,1,1)
281 e%x(l,1,1,1) = e%x(l,1,1,1) + &
282 dt * rk_scheme%coeffs_b(i) * k_e_ptr(l,1,1,1)
283 end do
284 !$omp end do simd
285 end do
286 !$omp end parallel
287
288 call neko_scratch_registry%relinquish_field(tmp_indices)
289
291
317 subroutine evaluate_rhs_cpu(rhs_rho_field, rhs_m_x, rhs_m_y, rhs_m_z, rhs_E, &
318 rho_field, m_x, m_y, m_z, E, p, u, v, w, Ax, &
319 Ax_stress, coef, gs, h, artificial_visc, mu, kappa)
320 type(field_t), intent(inout) :: rhs_rho_field, &
321 rhs_m_x, rhs_m_y, rhs_m_z, rhs_e
322 type(field_t), intent(inout) :: rho_field, m_x, m_y, m_z, E
323 type(field_t), intent(in) :: p, u, v, w, h, artificial_visc, mu, kappa
324 class(ax_t), intent(inout) :: Ax, Ax_stress
325 type(coef_t), intent(inout) :: coef
326 type(gs_t), intent(inout) :: gs
327 integer :: i, n
328 type(field_t), pointer :: f_x, f_y, f_z
329 type(field_t), pointer :: visc_rho, visc_m_x, visc_m_y, visc_m_z, visc_E
330 integer :: tmp_indices(8)
331
332 n = coef%dof%size()
333
334 call neko_scratch_registry%request_field(f_x, tmp_indices(1), .false.)
335 call neko_scratch_registry%request_field(f_y, tmp_indices(2), .false.)
336 call neko_scratch_registry%request_field(f_z, tmp_indices(3), .false.)
337
338 ! Hoisted from below so the registry calls are kept outside the
339 ! following !$omp parallel do simd regions.
340 ! fused into one !$omp parallel do simd (registry calls are not
341 ! thread-safe so they cannot sit between two !$omp do constructs).
342 call neko_scratch_registry%request_field(visc_rho, tmp_indices(4), .false.)
343 call neko_scratch_registry%request_field(visc_m_x, tmp_indices(5), .false.)
344 call neko_scratch_registry%request_field(visc_m_y, tmp_indices(6), .false.)
345 call neko_scratch_registry%request_field(visc_m_z, tmp_indices(7), .false.)
346 call neko_scratch_registry%request_field(visc_e, tmp_indices(8), .false.)
347
349 ! Compute density flux divergence
350 call div(rhs_rho_field%x, m_x%x, m_y%x, m_z%x, coef)
351
353 ! Compute momentum flux divergences
354 ! m_x
355 !OCL NORECURRENCE, NOVREC, NOALIAS
356 !DIR$ CONCURRENT
357 !DIR$ IVDEP
358 !GCC$ ivdep
359 !$omp parallel do simd
360 do i = 1, n
361 f_x%x(i,1,1,1) = m_x%x(i,1,1,1) * m_x%x(i,1,1,1) / &
362 rho_field%x(i,1,1,1) + p%x(i,1,1,1)
363 f_y%x(i,1,1,1) = m_x%x(i,1,1,1) * m_y%x(i,1,1,1) / &
364 rho_field%x(i,1,1,1)
365 f_z%x(i,1,1,1) = m_x%x(i,1,1,1) * m_z%x(i,1,1,1) / &
366 rho_field%x(i,1,1,1)
367 end do
368 !$omp end parallel do simd
369 call div(rhs_m_x%x, f_x%x, f_y%x, f_z%x, coef)
370 ! m_y
371 !OCL NORECURRENCE, NOVREC, NOALIAS
372 !DIR$ CONCURRENT
373 !DIR$ IVDEP
374 !GCC$ ivdep
375 !$omp parallel do simd
376 do i = 1, n
377 f_x%x(i,1,1,1) = m_y%x(i,1,1,1) * m_x%x(i,1,1,1) / &
378 rho_field%x(i,1,1,1)
379 f_y%x(i,1,1,1) = m_y%x(i,1,1,1) * m_y%x(i,1,1,1) / &
380 rho_field%x(i,1,1,1) + p%x(i,1,1,1)
381 f_z%x(i,1,1,1) = m_y%x(i,1,1,1) * m_z%x(i,1,1,1) / &
382 rho_field%x(i,1,1,1)
383 end do
384 !$omp end parallel do simd
385 call div(rhs_m_y%x, f_x%x, f_y%x, f_z%x, coef)
386 ! m_z
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 f_x%x(i,1,1,1) = m_z%x(i,1,1,1) * m_x%x(i,1,1,1) / &
394 rho_field%x(i,1,1,1)
395 f_y%x(i,1,1,1) = m_z%x(i,1,1,1) * m_y%x(i,1,1,1) / &
396 rho_field%x(i,1,1,1)
397 f_z%x(i,1,1,1) = m_z%x(i,1,1,1) * m_z%x(i,1,1,1) / &
398 rho_field%x(i,1,1,1) + p%x(i,1,1,1)
399 end do
400 !$omp end parallel do simd
401 call div(rhs_m_z%x, f_x%x, f_y%x, f_z%x, coef)
402
404 ! Compute energy flux divergence
405 !OCL NORECURRENCE, NOVREC, NOALIAS
406 !DIR$ CONCURRENT
407 !DIR$ IVDEP
408 !GCC$ ivdep
409 !$omp parallel do simd
410 do i = 1, n
411 f_x%x(i,1,1,1) = (e%x(i,1,1,1) + p%x(i,1,1,1)) * &
412 u%x(i,1,1,1)
413 f_y%x(i,1,1,1) = (e%x(i,1,1,1) + p%x(i,1,1,1)) * &
414 v%x(i,1,1,1)
415 f_z%x(i,1,1,1) = (e%x(i,1,1,1) + p%x(i,1,1,1)) * &
416 w%x(i,1,1,1)
417 end do
418 !$omp end parallel do simd
419 call div(rhs_e%x, f_x%x, f_y%x, f_z%x, coef)
420
421 call gs%op(rhs_rho_field, gs_op_add)
422 call rotate_cyc(rhs_m_x%x, rhs_m_y%x, rhs_m_z%x, 1, coef)
423 call gs%op(rhs_m_x%x, rhs_m_y%x, rhs_m_z%x, n, gs_op_add)
424 call rotate_cyc(rhs_m_x%x, rhs_m_y%x, rhs_m_z%x, 0, coef)
425 call gs%op(rhs_e, gs_op_add)
426
427 ! Apply multiplicity to the inviscid RHS and set h1 to the artificial
428 ! viscosity for the Laplacian (density, momentum and energy are all
429 ! stabilized by the same artificial viscosity). Fused: one fork-join
430 ! instead of two, and coef%mult / artificial_visc share L1.
431 !OCL NORECURRENCE, NOVREC, NOALIAS
432 !DIR$ CONCURRENT
433 !DIR$ IVDEP
434 !GCC$ ivdep
435 !$omp parallel do simd
436 do i = 1, n
437 rhs_rho_field%x(i,1,1,1) = rhs_rho_field%x(i,1,1,1) * &
438 coef%mult(i,1,1,1)
439 rhs_m_x%x(i,1,1,1) = rhs_m_x%x(i,1,1,1) * coef%mult(i,1,1,1)
440 rhs_m_y%x(i,1,1,1) = rhs_m_y%x(i,1,1,1) * coef%mult(i,1,1,1)
441 rhs_m_z%x(i,1,1,1) = rhs_m_z%x(i,1,1,1) * coef%mult(i,1,1,1)
442 rhs_e%x(i,1,1,1) = rhs_e%x(i,1,1,1) * coef%mult(i,1,1,1)
443 coef%h1(i,1,1,1) = artificial_visc%x(i,1,1,1)
444 end do
445 !$omp end parallel do simd
446
447 coef%ifh2 = .false.
448
449 ! Calculate artificial diffusion with variable viscosity. The momentum
450 ! components share the operator, so they use the fused vector apply
451 ! (geometric factors and h1 are loaded once for all three components).
452 call ax%compute(visc_rho%x, rho_field%x, coef, p%msh, p%Xh)
453 call ax%compute_vector(visc_m_x%x, visc_m_y%x, visc_m_z%x, &
454 m_x%x, m_y%x, m_z%x, coef, p%msh, p%Xh)
455 call ax%compute(visc_e%x, e%x, coef, p%msh, p%Xh)
456
458 call add_navier_stokes_flux_cpu(visc_m_x, visc_m_y, visc_m_z, visc_e, &
459 rho_field, p, u, v, w, mu, kappa, ax, ax_stress, coef)
460 end if
461
462 ! gs. h1=1.0 reset is deferred into the final accumulation below; safe
463 ! because nothing here (gs%op, rotate_cyc) reads coef%h1.
464 call gs%op(visc_rho, gs_op_add)
465 call rotate_cyc(visc_m_x%x, visc_m_y%x, visc_m_z%x, 1, coef)
466 call gs%op(visc_m_x%x, visc_m_y%x, visc_m_z%x, n, gs_op_add)
467 call rotate_cyc(visc_m_x%x, visc_m_y%x, visc_m_z%x, 0, coef)
468 call gs%op(visc_e, gs_op_add)
469
470 ! Move div to the rhs, apply artificial viscosity, and reset h1 to 1.
471 ! The viscosity coefficient is already included in the Laplacian operator.
472 ! Fused: one fork-join instead of two, and coef%Binv stays in L1.
473 !OCL NORECURRENCE, NOVREC, NOALIAS
474 !DIR$ CONCURRENT
475 !DIR$ IVDEP
476 !GCC$ ivdep
477 !$omp parallel do simd
478 do i = 1, n
479 rhs_rho_field%x(i,1,1,1) = -rhs_rho_field%x(i,1,1,1) - &
480 coef%Binv(i,1,1,1) * visc_rho%x(i,1,1,1)
481 rhs_m_x%x(i,1,1,1) = -rhs_m_x%x(i,1,1,1) - &
482 coef%Binv(i,1,1,1) * visc_m_x%x(i,1,1,1)
483 rhs_m_y%x(i,1,1,1) = -rhs_m_y%x(i,1,1,1) - &
484 coef%Binv(i,1,1,1) * visc_m_y%x(i,1,1,1)
485 rhs_m_z%x(i,1,1,1) = -rhs_m_z%x(i,1,1,1) - &
486 coef%Binv(i,1,1,1) * visc_m_z%x(i,1,1,1)
487 rhs_e%x(i,1,1,1) = -rhs_e%x(i,1,1,1) - &
488 coef%Binv(i,1,1,1) * visc_e%x(i,1,1,1)
489 coef%h1(i,1,1,1) = 1.0_rp
490 end do
491 !$omp end parallel do simd
492
493 call neko_scratch_registry%relinquish_field(tmp_indices)
494 end subroutine evaluate_rhs_cpu
495
511 subroutine add_navier_stokes_flux_cpu(visc_m_x, visc_m_y, visc_m_z, visc_E, &
512 rho_field, p, u, v, w, mu, kappa, Ax, Ax_stress, coef)
513 type(field_t), intent(inout) :: visc_m_x, visc_m_y, visc_m_z, visc_E
514 type(field_t), intent(in) :: rho_field
515 type(field_t), intent(in) :: p, u, v, w, mu, kappa
516 class(ax_t), intent(inout) :: Ax, Ax_stress
517 type(coef_t), intent(inout) :: coef
518 type(field_t), pointer :: dudx, dudy, dudz, dvdx, dvdy, dvdz, &
519 dwdx, dwdy, dwdz, tau_xx, tau_xy, tau_xz, tau_yy, tau_yz, &
520 tau_zz, f_x, f_y, f_z, div_flux, dissipation
521 integer :: tmp_indices(20)
522 integer :: i, n
523 real(kind=rp) :: div_u, two_thirds
524
525 n = coef%dof%size()
526 two_thirds = 2.0_rp / 3.0_rp
527
528 call neko_scratch_registry%request_field(dudx, tmp_indices(1), .false.)
529 call neko_scratch_registry%request_field(dudy, tmp_indices(2), .false.)
530 call neko_scratch_registry%request_field(dudz, tmp_indices(3), .false.)
531 call neko_scratch_registry%request_field(dvdx, tmp_indices(4), .false.)
532 call neko_scratch_registry%request_field(dvdy, tmp_indices(5), .false.)
533 call neko_scratch_registry%request_field(dvdz, tmp_indices(6), .false.)
534 call neko_scratch_registry%request_field(dwdx, tmp_indices(7), .false.)
535 call neko_scratch_registry%request_field(dwdy, tmp_indices(8), .false.)
536 call neko_scratch_registry%request_field(dwdz, tmp_indices(9), .false.)
537 call neko_scratch_registry%request_field(tau_xx, tmp_indices(10), .false.)
538 call neko_scratch_registry%request_field(tau_xy, tmp_indices(11), .false.)
539 call neko_scratch_registry%request_field(tau_xz, tmp_indices(12), .false.)
540 call neko_scratch_registry%request_field(tau_yy, tmp_indices(13), .false.)
541 call neko_scratch_registry%request_field(tau_yz, tmp_indices(14), .false.)
542 call neko_scratch_registry%request_field(tau_zz, tmp_indices(15), .false.)
543 call neko_scratch_registry%request_field(f_x, tmp_indices(16), .false.)
544 call neko_scratch_registry%request_field(f_y, tmp_indices(17), .false.)
545 call neko_scratch_registry%request_field(f_z, tmp_indices(18), .false.)
546 call neko_scratch_registry%request_field(div_flux, tmp_indices(19), .false.)
547 call neko_scratch_registry%request_field(dissipation, tmp_indices(20), &
548 .false.)
549
550 call grad(dudx%x, dudy%x, dudz%x, u%x, coef)
551 call grad(dvdx%x, dvdy%x, dvdz%x, v%x, coef)
552 call grad(dwdx%x, dwdy%x, dwdz%x, w%x, coef)
553
554 ! Viscous stress tensor, dilatational flux, viscous dissipation and
555 ! h1 = mu for the stress Laplacian, fused into a single sweep.
556 !OCL NORECURRENCE, NOVREC, NOALIAS
557 !DIR$ CONCURRENT
558 !DIR$ IVDEP
559 !GCC$ ivdep
560 !$omp parallel do simd private(div_u)
561 do i = 1, n
562 div_u = dudx%x(i,1,1,1) + dvdy%x(i,1,1,1) + dwdz%x(i,1,1,1)
563 div_flux%x(i,1,1,1) = mu%x(i,1,1,1) * div_u
564 coef%h1(i,1,1,1) = mu%x(i,1,1,1)
565 tau_xx%x(i,1,1,1) = mu%x(i,1,1,1) * &
566 (2.0_rp * dudx%x(i,1,1,1) - two_thirds * div_u)
567 tau_yy%x(i,1,1,1) = mu%x(i,1,1,1) * &
568 (2.0_rp * dvdy%x(i,1,1,1) - two_thirds * div_u)
569 tau_zz%x(i,1,1,1) = mu%x(i,1,1,1) * &
570 (2.0_rp * dwdz%x(i,1,1,1) - two_thirds * div_u)
571 tau_xy%x(i,1,1,1) = mu%x(i,1,1,1) * &
572 (dudy%x(i,1,1,1) + dvdx%x(i,1,1,1))
573 tau_xz%x(i,1,1,1) = mu%x(i,1,1,1) * &
574 (dudz%x(i,1,1,1) + dwdx%x(i,1,1,1))
575 tau_yz%x(i,1,1,1) = mu%x(i,1,1,1) * &
576 (dvdz%x(i,1,1,1) + dwdy%x(i,1,1,1))
577 dissipation%x(i,1,1,1) = &
578 tau_xx%x(i,1,1,1) * dudx%x(i,1,1,1) &
579 + tau_xy%x(i,1,1,1) * (dudy%x(i,1,1,1) + dvdx%x(i,1,1,1)) &
580 + tau_xz%x(i,1,1,1) * (dudz%x(i,1,1,1) + dwdx%x(i,1,1,1)) &
581 + tau_yy%x(i,1,1,1) * dvdy%x(i,1,1,1) &
582 + tau_yz%x(i,1,1,1) * (dvdz%x(i,1,1,1) + dwdy%x(i,1,1,1)) &
583 + tau_zz%x(i,1,1,1) * dwdz%x(i,1,1,1)
584 end do
585 !$omp end parallel do simd
586
587 call ax_stress%compute_vector(f_x%x, f_y%x, f_z%x, u%x, v%x, w%x, coef, &
588 p%msh, p%Xh)
589 call opgrad(dudx%x, dudy%x, dudz%x, div_flux%x, coef)
590
591 ! Accumulate the stress contribution into the viscous residual, add
592 ! the dissipation to the energy residual, compute the internal energy
593 ! (temperature) for the heat flux and set h1 = kappa for its Laplacian.
594 ! Fused: one fork-join instead of four.
595 !OCL NORECURRENCE, NOVREC, NOALIAS
596 !DIR$ CONCURRENT
597 !DIR$ IVDEP
598 !GCC$ ivdep
599 !$omp parallel do simd
600 do i = 1, n
601 f_x%x(i,1,1,1) = f_x%x(i,1,1,1) &
602 - two_thirds * dudx%x(i,1,1,1)
603 f_y%x(i,1,1,1) = f_y%x(i,1,1,1) &
604 - two_thirds * dudy%x(i,1,1,1)
605 f_z%x(i,1,1,1) = f_z%x(i,1,1,1) &
606 - two_thirds * dudz%x(i,1,1,1)
607 visc_m_x%x(i,1,1,1) = visc_m_x%x(i,1,1,1) + f_x%x(i,1,1,1)
608 visc_m_y%x(i,1,1,1) = visc_m_y%x(i,1,1,1) + f_y%x(i,1,1,1)
609 visc_m_z%x(i,1,1,1) = visc_m_z%x(i,1,1,1) + f_z%x(i,1,1,1)
610 visc_e%x(i,1,1,1) = visc_e%x(i,1,1,1) &
611 + u%x(i,1,1,1) * f_x%x(i,1,1,1) &
612 + v%x(i,1,1,1) * f_y%x(i,1,1,1) &
613 + w%x(i,1,1,1) * f_z%x(i,1,1,1) &
614 - coef%B(i,1,1,1) * dissipation%x(i,1,1,1)
615 div_flux%x(i,1,1,1) = p%x(i,1,1,1) / &
616 (rho_field%x(i,1,1,1) * (compressible_res_cpu_gamma - 1.0_rp))
617 coef%h1(i,1,1,1) = kappa%x(i,1,1,1)
618 end do
619 !$omp end parallel do simd
620
621 call ax%compute(dudx%x, div_flux%x, coef, p%msh, p%Xh)
622
623 !OCL NORECURRENCE, NOVREC, NOALIAS
624 !DIR$ CONCURRENT
625 !DIR$ IVDEP
626 !GCC$ ivdep
627 !$omp parallel do simd
628 do i = 1, n
629 visc_e%x(i,1,1,1) = visc_e%x(i,1,1,1) + dudx%x(i,1,1,1)
630 end do
631 !$omp end parallel do simd
632
633 call neko_scratch_registry%relinquish_field(tmp_indices)
634
635 end subroutine add_navier_stokes_flux_cpu
636
637end module compressible_res_cpu
Compute the divergence of a vector field.
Definition operators.f90:85
Compute the gradient of a scalar field, multiplied by the mass matrix.
Definition operators.f90:91
Apply cyclic boundary condition to a vector field.
Defines a Matrix-vector product.
Definition ax.f90:34
Defines a list of bc_t.
Definition bc_list.f90:34
Coefficients.
Definition coef.f90:34
CPU implementation of compressible flow operations.
subroutine, public compressible_ops_cpu_update_uvw(u, v, w, m_x, m_y, m_z, rho, n)
Update u,v,w fields.
subroutine, public compressible_ops_cpu_update_mxyz_p_ruvw(m_x, m_y, m_z, p, ruvw, u, v, w, e, rho, gamma, n)
Update m_x, m_y, m_z, p, ruvw, fields.
This implements CPU-based residual calculations for the compressible equations. It handles the time a...
subroutine add_navier_stokes_flux_cpu(visc_m_x, visc_m_y, visc_m_z, visc_e, rho_field, p, u, v, w, mu, kappa, ax, ax_stress, coef)
Add the physical Navier-Stokes flux contribution to the viscous residual.
subroutine evaluate_rhs_cpu(rhs_rho_field, rhs_m_x, rhs_m_y, rhs_m_z, rhs_e, rho_field, m_x, m_y, m_z, e, p, u, v, w, ax, ax_stress, coef, gs, h, artificial_visc, mu, kappa)
Evaluates the right-hand side of the compressible equations. Inviscid terms are evaluated through div...
logical compressible_res_cpu_add_physical_flux
Whether physical Navier-Stokes fluxes are active for the current step.
subroutine advance_primitive_variables_cpu(rho_field, m_x, m_y, m_z, e, p, u, v, w, ax, ax_stress, coef, gs, h, artificial_visc, mu, kappa, bcs_vel, time, rk_scheme, dt)
Advances the primitive variables (density, momentum, energy) in time using a Runge-Kutta scheme.
logical compressible_res_cpu_add_physical_stress
Whether physical viscous stress is active for the current step.
real(kind=rp), public compressible_res_cpu_gamma
Module variable to store thermodynamic parameter set by factory.
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
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:12
Operators.
Definition operators.f90:34
subroutine, public opgrad(ux, uy, uz, u, coef, es, ee)
Compute the weak gradient of a scalar field, i.e. the gradient multiplied by the mass matrix.
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.
Module with things related to the simulation time.
Base type for a matrix-vector product providing .
Definition ax.f90:43
A list of allocatable `bc_t`. Follows the standard interface of lists.
Definition bc_list.f90:49
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:63
field_list_t, To be able to group fields together
Gather-scatter kernel.
A struct that contains all info about the time, expand as needed.