Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
fluid_scheme_compressible.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!
34 use field, only : field_t
35 use field_math, only : field_col2, field_col3, &
38
39 use registry, only : neko_registry
40 use bc, only : bc_t
42 use json_module, only : json_file
43 use num_types, only : rp, dp
44 use mesh, only : mesh_t
46 use space, only : gll
50 use mpi_f08
51 use operators, only : cfl_compressible
53 use compressible_ops_cpu, only : &
55 use compressible_ops_device, only : &
58 use time_state, only : time_state_t
59 use logger, only : neko_log, log_size
60 use math, only : glsum, glamax
61 use device_math, only : device_glamax
62 use compressible_residual, only : compressible_rhs_set_physical_flux
63 use num_types, only : i8
64 implicit none
65 private
66
68 type, public, abstract, extends(fluid_scheme_base_t) :: &
71 type(field_t), pointer :: m_x => null()
72 type(field_t), pointer :: m_y => null()
73 type(field_t), pointer :: m_z => null()
74 type(field_t), pointer :: e => null()
75 type(field_t), pointer :: temperature => null()
76 type(field_t), pointer :: max_wave_speed => null()
77 type(field_t), pointer :: artificial_visc => null()
78 type(field_t), pointer :: kappa => null()
79
80 real(kind=rp) :: gamma
81
83 real(kind=rp) :: mu_amax = 0.0_rp
85 real(kind=rp) :: kappa_amax = 0.0_rp
86
88 logical :: add_physical_flux = .false.
90 logical :: add_physical_stress = .false.
93 logical :: variable_material_properties = .false.
94
96 integer(kind=i8) :: glb_n_points
98 integer(kind=i8) :: glb_unique_points
99
100 contains
102 procedure, pass(this) :: scheme_init => fluid_scheme_compressible_init
104 procedure, pass(this) :: scheme_free => fluid_scheme_compressible_free
105
107 procedure, pass(this) :: validate => fluid_scheme_compressible_validate
109 procedure, pass(this) :: compute_cfl &
112 procedure, pass(this) :: set_material_properties => &
115 procedure, pass(this) :: update_material_properties => &
118 procedure, pass(this) :: update_physical_flux => &
121 procedure, pass(this) :: compute_max_wave_speed => &
124 procedure, pass(this) :: log_solver_info => &
126
128
129contains
137 subroutine fluid_scheme_compressible_init(this, msh, lx, params, scheme, user)
138 class(fluid_scheme_compressible_t), target, intent(inout) :: this
139 type(mesh_t), target, intent(inout) :: msh
140 integer, intent(in) :: lx
141 character(len=*), intent(in) :: scheme
142 type(json_file), target, intent(inout) :: params
143 type(user_t), target, intent(in) :: user
144
145 !
146 ! SEM simulation fundamentals
147 !
148
149 this%msh => msh
150
151 if (msh%gdim .eq. 2) then
152 call this%Xh%init(gll, lx, lx)
153 else
154 call this%Xh%init(gll, lx, lx, lx)
155 end if
156
157 call this%dm_Xh%init(msh, this%Xh)
158
159 call this%gs_Xh%init(this%dm_Xh)
160
161 call this%c_Xh%init(this%gs_Xh)
162
163 ! Assign Dofmap to scratch registry
164 call neko_scratch_registry%set_dofmap(this%dm_Xh)
165
166 ! Case parameters
167 this%params => params
168
169 ! Assign a name
170 call json_get_or_default(params, 'case.fluid.name', this%name, "fluid")
171
172 ! Material properties will be set up via set_material_properties
173 call neko_registry%add_field(this%dm_Xh, this%name // "_rho")
174 this%rho => neko_registry%get_field(this%name // "_rho")
175
176 ! Assign momentum fields
177 call neko_registry%add_field(this%dm_Xh, "m_x")
178 call neko_registry%add_field(this%dm_Xh, "m_y")
179 call neko_registry%add_field(this%dm_Xh, "m_z")
180 this%m_x => neko_registry%get_field("m_x")
181 this%m_y => neko_registry%get_field("m_y")
182 this%m_z => neko_registry%get_field("m_z")
183 call this%m_x%init(this%dm_Xh, "m_x")
184 call this%m_y%init(this%dm_Xh, "m_y")
185 call this%m_z%init(this%dm_Xh, "m_z")
186
187 ! Assign energy field
188 call neko_registry%add_field(this%dm_Xh, "E")
189 this%E => neko_registry%get_field("E")
190 call this%E%init(this%dm_Xh, "E")
191
192 ! Assign temperature field
193 call neko_registry%add_field(this%dm_Xh, "temperature")
194 this%temperature => neko_registry%get_field("temperature")
195 call this%temperature%init(this%dm_Xh, "temperature")
196
197 ! Assign maximum wave speed field
198 call neko_registry%add_field(this%dm_Xh, "max_wave_speed")
199 this%max_wave_speed => neko_registry%get_field("max_wave_speed")
200 call this%max_wave_speed%init(this%dm_Xh, "max_wave_speed")
201
202 ! Assign artificial viscosity field (without physical viscosity)
203 call neko_registry%add_field(this%dm_Xh, "artificial_visc")
204 this%artificial_visc => neko_registry%get_field("artificial_visc")
205 call this%artificial_visc%init(this%dm_Xh, "artificial_visc")
206
207 ! ! Assign velocity fields
208 call neko_registry%add_field(this%dm_Xh, "u")
209 call neko_registry%add_field(this%dm_Xh, "v")
210 call neko_registry%add_field(this%dm_Xh, "w")
211 this%u => neko_registry%get_field("u")
212 this%v => neko_registry%get_field("v")
213 this%w => neko_registry%get_field("w")
214 call this%u%init(this%dm_Xh, "u")
215 call this%v%init(this%dm_Xh, "v")
216 call this%w%init(this%dm_Xh, "w")
217 call neko_registry%add_field(this%dm_Xh, 'p')
218 this%p => neko_registry%get_field('p')
219 call this%p%init(this%dm_Xh, "p")
220
221 !
222 ! Setup right-hand side fields.
223 !
224 allocate(this%f_x)
225 allocate(this%f_y)
226 allocate(this%f_z)
227 call this%f_x%init(this%dm_Xh, fld_name = "fluid_rhs_x")
228 call this%f_y%init(this%dm_Xh, fld_name = "fluid_rhs_y")
229 call this%f_z%init(this%dm_Xh, fld_name = "fluid_rhs_z")
230
231 ! Material properties
232 call this%set_material_properties(params, user)
233
234 ! Compressible parameters
235 call json_get_or_default(params, 'case.fluid.gamma', this%gamma, 1.4_rp)
236
237 ! Calculate global points for logging
238 this%glb_n_points = int(this%msh%glb_nelv, i8)*int(this%Xh%lxyz, i8)
239 this%glb_unique_points = int(glsum(this%c_Xh%mult, this%dm_Xh%size()), i8)
240
241 !
242 ! Log solver information
243 !
244 call this%log_solver_info(params, scheme, lx)
245 end subroutine fluid_scheme_compressible_init
246
250 class(fluid_scheme_compressible_t), intent(inout) :: this
251 class(bc_t), pointer :: bc
252 integer :: i
253
254 do i = 1, this%bcs_vel%size()
255 bc => this%bcs_vel%get(i)
256 if (associated(bc)) then
257 call bc%free()
258 deallocate(bc)
259 end if
260 end do
261 call this%bcs_vel%free()
262
263 do i = 1, this%bcs_prs%size()
264 bc => this%bcs_prs%get(i)
265 if (associated(bc)) then
266 call bc%free()
267 deallocate(bc)
268 end if
269 end do
270 call this%bcs_prs%free()
271
272 call this%dm_Xh%free()
273 call this%gs_Xh%free()
274 call this%c_Xh%free()
275 call this%Xh%free()
276
277 if (associated(this%m_x)) then
278 call this%m_x%free()
279 end if
280
281 if (associated(this%m_y)) then
282 call this%m_y%free()
283 end if
284
285 if (associated(this%m_z)) then
286 call this%m_z%free()
287 end if
288
289 if (associated(this%E)) then
290 call this%E%free()
291 end if
292
293 if (associated(this%temperature)) then
294 call this%temperature%free()
295 end if
296
297 if (associated(this%max_wave_speed)) then
298 call this%max_wave_speed%free()
299 end if
300
301 if (associated(this%f_x)) then
302 call this%f_x%free()
303 deallocate(this%f_x)
304 end if
305
306 if (associated(this%f_y)) then
307 call this%f_y%free()
308 deallocate(this%f_y)
309 end if
310
311 if (associated(this%f_z)) then
312 call this%f_z%free()
313 deallocate(this%f_z)
314 end if
315
316 nullify(this%f_x)
317 nullify(this%f_y)
318 nullify(this%f_z)
319
320 nullify(this%m_x)
321 nullify(this%m_y)
322 nullify(this%m_z)
323 nullify(this%E)
324 nullify(this%temperature)
325 nullify(this%max_wave_speed)
326
327 nullify(this%u)
328 nullify(this%v)
329 nullify(this%w)
330 nullify(this%p)
331 nullify(this%rho)
332 nullify(this%mu)
333 nullify(this%kappa)
334
335 call this%material_properties%free()
336
337 end subroutine fluid_scheme_compressible_free
338
342 class(fluid_scheme_compressible_t), target, intent(inout) :: this
343 integer :: n, i
344 type(field_t), pointer :: temp
345 integer :: temp_indices(1)
346
347 n = this%dm_Xh%size()
348 call neko_scratch_registry%request_field(temp, temp_indices(1), .false.)
349
351 call field_col3(this%m_x, this%u, this%rho)
352 call field_col3(this%m_y, this%v, this%rho)
353 call field_col3(this%m_z, this%w, this%rho)
354
357 call field_cmult2(this%E, this%p, 1.0_rp/(this%gamma - 1.0_rp), n)
358 call field_col3(temp, this%u, this%u, n)
359 call field_addcol3(temp, this%v, this%v, n)
360 call field_addcol3(temp, this%w, this%w, n)
361 call field_col2(temp, this%rho, n)
362 call field_cmult(temp, 0.5_rp, n)
363 call field_add2(this%E, temp, n)
364
366 do i = 1, n
367 this%temperature%x(i,1,1,1) = this%p%x(i,1,1,1) / &
368 (this%rho%x(i,1,1,1) * (this%gamma - 1.0_rp))
369 end do
370
371 call neko_scratch_registry%relinquish_field(temp_indices)
372
374 call this%compute_max_wave_speed()
375
377
382 function fluid_scheme_compressible_compute_cfl(this, dt) result(c)
383 class(fluid_scheme_compressible_t), intent(in) :: this
384 real(kind=dp), intent(in) :: dt
385 real(kind=dp) :: c
386 integer :: n
387
388 associate(u => this%u, v => this%v, w => this%w, p => this%p, &
389 rho => this%rho, xh => this%Xh, c_xh => this%c_Xh, &
390 msh => this%msh, gamma => this%gamma, &
391 max_wave_speed => this%max_wave_speed)
392
393 n = xh%lx * xh%ly * xh%lz * msh%nelv
394
395 ! Use the compressible CFL function with precomputed maximum wave speed
396 c = cfl_compressible(dt, max_wave_speed%x, xh, c_xh, msh%nelv, msh%gdim)
397 end associate
398
400
406 params, user)
407 class(fluid_scheme_compressible_t), target, intent(inout) :: this
408 type(json_file), intent(inout) :: params
409 type(user_t), target, intent(in) :: user
410 procedure(user_material_properties_intf), pointer :: dummy_mp_ptr
411 type(time_state_t) :: dummy_time_state
412 real(kind=rp) :: const_mu, const_kappa
413
414 dummy_mp_ptr => dummy_user_material_properties
415
416 call neko_registry%add_field(this%dm_Xh, this%name // "_mu")
417 this%mu => neko_registry%get_field(this%name // "_mu")
418
419 call neko_registry%add_field(this%dm_Xh, this%name // "_kappa")
420 this%kappa => neko_registry%get_field(this%name // "_kappa")
421
422 call this%material_properties%init(3)
423 call this%material_properties%assign(1, this%rho)
424 call this%material_properties%assign(2, this%mu)
425 call this%material_properties%assign(3, this%kappa)
426
427 if (.not. associated(user%material_properties, dummy_mp_ptr)) then
428 this%user_material_properties => user%material_properties
429 this%variable_material_properties = .true.
430 call user%material_properties(this%name, this%material_properties, &
431 dummy_time_state)
432 else
433 this%variable_material_properties = .false.
434 this%user_material_properties => dummy_user_material_properties
435 call json_get_or_lookup_or_default(params, 'case.fluid.mu', const_mu, &
436 0.0_rp)
437 call json_get_or_lookup_or_default(params, 'case.fluid.kappa', &
438 const_kappa, 0.0_rp)
439
440 call field_cfill(this%mu, const_mu)
441 call field_cfill(this%kappa, const_kappa)
442 end if
443
444 ! Reported by log_solver_info, once the Fluid section is open.
445 call this%update_physical_flux()
446
448
454 class(fluid_scheme_compressible_t), intent(inout) :: this
455 type(time_state_t), intent(in) :: time
456
457 if (.not. this%variable_material_properties) return
458
459 call this%user_material_properties(this%name, this%material_properties, &
460 time)
461
462 call this%update_physical_flux()
463
465
482 class(fluid_scheme_compressible_t), intent(inout) :: this
483 real(kind=rp) :: mu_amax, kappa_amax
484 integer :: n
485
486 n = this%dm_Xh%size()
487
488 if (neko_bcknd_device .eq. 1) then
489 mu_amax = device_glamax(this%mu%x_d, n)
490 kappa_amax = device_glamax(this%kappa%x_d, n)
491 else
492 mu_amax = glamax(this%mu%x, n)
493 kappa_amax = glamax(this%kappa%x, n)
494 end if
495
496 this%mu_amax = mu_amax
497 this%kappa_amax = kappa_amax
498
499 this%add_physical_stress = (mu_amax .ne. 0.0_rp)
500 this%add_physical_flux = this%add_physical_stress .or. &
501 (kappa_amax .ne. 0.0_rp)
502
503 call compressible_rhs_set_physical_flux(this%add_physical_flux, &
504 this%add_physical_stress)
505
507
511 class(fluid_scheme_compressible_t), intent(inout) :: this
512 integer :: n
513
514 n = this%u%dof%size()
515
517 if (neko_bcknd_device .eq. 1) then
518 call compressible_ops_device_compute_max_wave_speed( &
519 this%max_wave_speed, this%u, this%v, this%w, this%gamma, this%p, &
520 this%rho, n)
521 else
522 call compressible_ops_cpu_compute_max_wave_speed(this%max_wave_speed%x, &
523 this%u%x, this%v%x, this%w%x, this%gamma, this%p%x, this%rho%x, n)
524 end if
525
527
533 subroutine fluid_scheme_compressible_log_solver_info(this, params, scheme, lx)
534 class(fluid_scheme_compressible_t), intent(inout) :: this
535 type(json_file), intent(inout) :: params
536 character(len=*), intent(in) :: scheme
537 integer, intent(in) :: lx
538 character(len=LOG_SIZE) :: log_buf
539 logical :: logical_val
540 integer :: integer_val
541
542 call neko_log%section('Fluid')
543 write(log_buf, '(A, A)') 'Type : ', trim(scheme)
544 call neko_log%message(log_buf)
545 write(log_buf, '(A, A)') 'Name : ', trim(this%name)
546 call neko_log%message(log_buf)
547
548 ! Polynomial order
549 if (lx .lt. 10) then
550 write(log_buf, '(A, I1)') 'Poly order : ', lx-1
551 else if (lx .ge. 10) then
552 write(log_buf, '(A, I2)') 'Poly order : ', lx-1
553 else
554 write(log_buf, '(A, I3)') 'Poly order : ', lx-1
555 end if
556 call neko_log%message(log_buf)
557
558 ! Global points information
559 write(log_buf, '(A, I0)') 'GLL points : ', this%glb_n_points
560 call neko_log%message(log_buf)
561 write(log_buf, '(A, I0)') 'Unique pts.: ', this%glb_unique_points
562 call neko_log%message(log_buf)
563
564 ! Material properties
565 write(log_buf, '(A,ES13.6)') 'gamma :', this%gamma
566 call neko_log%message(log_buf)
567
568 call json_get_or_default(params, 'case.numerics.time_order', integer_val, 4)
569 write(log_buf, '(A, I0)') 'RK order : ', integer_val
570 call neko_log%message(log_buf)
571
572 ! Physical viscosity and conductivity. For user-defined properties the
573 ! fields need not be uniform, so report the largest magnitude found.
574 if (this%variable_material_properties) then
575 write(log_buf, '(A,ES13.6,A)') 'mu :', this%mu_amax, &
576 ' (user, max)'
577 call neko_log%message(log_buf)
578 write(log_buf, '(A,ES13.6,A)') 'kappa :', this%kappa_amax, &
579 ' (user, max)'
580 call neko_log%message(log_buf)
581 else
582 write(log_buf, '(A,ES13.6)') 'mu :', this%mu_amax
583 call neko_log%message(log_buf)
584 write(log_buf, '(A,ES13.6)') 'kappa :', this%kappa_amax
585 call neko_log%message(log_buf)
586 end if
587
588 if (this%add_physical_flux) then
589 write(log_buf, '(A, A)') 'NS fluxes : ', 'enabled'
590 else
591 write(log_buf, '(A, A)') 'NS fluxes : ', &
592 'disabled (mu = kappa = 0, Euler)'
593 end if
594 call neko_log%message(log_buf)
595
596 call neko_log%end_section()
597
599
Copy data between host and device (or device and device)
Definition device.F90:72
Abstract interface to sets rho and mu.
Retrieves a parameter by name or assigns a provided default value. In the latter case also adds the m...
Compute CFL condition for compressible flow.
Abstract interface for setting material properties.
Defines a boundary condition.
Definition bc.f90:34
CPU implementation of compressible flow operations.
subroutine, public compressible_ops_cpu_compute_max_wave_speed(max_wave_speed, u, v, w, gamma, p, rho, n)
Compute maximum wave speed for compressible flows on CPU.
Device implementation of compressible flow operations.
subroutine, public compressible_ops_device_compute_max_wave_speed(max_wave_speed, u, v, w, gamma, p, rho, n)
Compute maximum wave speed for compressible flows on device.
real(kind=rp) function, public device_glamax(a_d, n, strm)
Max of the absolute value of a vector of length n.
Device abstraction, common interface for various accelerators.
Definition device.F90:34
integer, parameter, public host_to_device
Definition device.F90:48
subroutine, public field_col2(a, b, n)
Vector multiplication .
subroutine, public field_cmult2(a, b, c, n)
Multiplication by constant c .
subroutine, public field_cfill(a, c, n)
Set all elements to a constant c .
subroutine, public field_addcol3(a, b, c, n)
Returns .
subroutine, public field_add2(a, b, n)
Vector addition .
subroutine, public field_col3(a, b, c, n)
Vector multiplication with 3 vectors .
subroutine, public field_cmult(a, c, n)
Multiplication by constant c .
Defines a field.
Definition field.f90:34
subroutine fluid_scheme_compressible_log_solver_info(this, params, scheme, lx)
Log comprehensive solver information.
subroutine fluid_scheme_compressible_free(this)
Free allocated memory and cleanup resources.
subroutine fluid_scheme_compressible_update_material_properties(this, time)
Update variable material properties.
subroutine fluid_scheme_compressible_set_material_properties(this, params, user)
Set material properties mu and rho.
real(kind=dp) function fluid_scheme_compressible_compute_cfl(this, dt)
Compute CFL number.
subroutine fluid_scheme_compressible_init(this, msh, lx, params, scheme, user)
Initialize common data for compressible fluid scheme.
subroutine fluid_scheme_compressible_update_physical_flux(this)
Refresh the physical-flux switches from the current material properties.
subroutine fluid_scheme_compressible_compute_max_wave_speed(this)
Compute maximum wave speed for compressible flows.
subroutine fluid_scheme_compressible_validate(this)
Validate field initialization and compute derived quantities.
Utilities for retrieving parameters from the case files.
Logging routines.
Definition log.f90:34
type(log_t), public neko_log
Global log stream.
Definition log.f90:91
integer, parameter, public log_size
Definition log.f90:46
Definition math.f90:60
real(kind=rp) function, public glamax(a, n)
Max of the absolute value of a vector of length n.
Definition math.f90:674
real(kind=rp) function, public glsum(a, n)
Sum a vector of length n.
Definition math.f90:633
Defines a mesh.
Definition mesh.f90:34
Build configurations.
integer, parameter neko_bcknd_device
integer, parameter, public i8
Definition num_types.f90:7
integer, parameter, public dp
Definition num_types.f90:10
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:14
Operators.
Definition operators.f90:34
Defines a registry for storing solution fields.
Definition registry.f90:34
type(registry_t), target, public neko_registry
Global field registry.
Definition registry.f90:158
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
integer, parameter, public gll
Definition space.f90:50
Module with things related to the simulation time.
Interfaces for user interaction with NEKO.
Definition user_intf.f90:34
subroutine, public dummy_user_material_properties(scheme_name, properties, time)
Base type for a boundary condition.
Definition bc.f90:73
Base type of all fluid formulations.
A struct that contains all info about the time, expand as needed.
A type collecting all the overridable user routines and flag to suppress type injection from custom m...