Neko 1.99.7
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, 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
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 : &
56 use compressible_ops_device, only : &
60 use time_state, only : time_state_t
61 use logger, only : neko_log, log_size
62 use math, only : glsum
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 :: s => null()
78 type(field_t), pointer :: artificial_visc => null()
79 type(field_t), pointer :: kappa => null()
80
81 real(kind=rp) :: gamma
82
84 integer(kind=i8) :: glb_n_points
86 integer(kind=i8) :: glb_unique_points
87
88 contains
90 procedure, pass(this) :: scheme_init => fluid_scheme_compressible_init
92 procedure, pass(this) :: scheme_free => fluid_scheme_compressible_free
93
95 procedure, pass(this) :: validate => fluid_scheme_compressible_validate
97 procedure, pass(this) :: compute_cfl &
100 procedure, pass(this) :: set_material_properties => &
103 procedure, pass(this) :: update_material_properties => &
106 procedure, pass(this) :: compute_entropy => &
109 procedure, pass(this) :: compute_max_wave_speed => &
112 procedure, pass(this) :: log_solver_info => &
114
116
117contains
125 subroutine fluid_scheme_compressible_init(this, msh, lx, params, scheme, user)
126 class(fluid_scheme_compressible_t), target, intent(inout) :: this
127 type(mesh_t), target, intent(inout) :: msh
128 integer, intent(in) :: lx
129 character(len=*), intent(in) :: scheme
130 type(json_file), target, intent(inout) :: params
131 type(user_t), target, intent(in) :: user
132
133 !
134 ! SEM simulation fundamentals
135 !
136
137 this%msh => msh
138
139 if (msh%gdim .eq. 2) then
140 call this%Xh%init(gll, lx, lx)
141 else
142 call this%Xh%init(gll, lx, lx, lx)
143 end if
144
145 call this%dm_Xh%init(msh, this%Xh)
146
147 call this%gs_Xh%init(this%dm_Xh)
148
149 call this%c_Xh%init(this%gs_Xh)
150
151 ! Assign Dofmap to scratch registry
152 call neko_scratch_registry%set_dofmap(this%dm_Xh)
153
154 ! Case parameters
155 this%params => params
156
157 ! Assign a name
158 call json_get_or_default(params, 'case.fluid.name', this%name, "fluid")
159
160 ! Material properties will be set up via set_material_properties
161 call neko_registry%add_field(this%dm_Xh, this%name // "_rho")
162 this%rho => neko_registry%get_field(this%name // "_rho")
163
164 ! Assign momentum fields
165 call neko_registry%add_field(this%dm_Xh, "m_x")
166 call neko_registry%add_field(this%dm_Xh, "m_y")
167 call neko_registry%add_field(this%dm_Xh, "m_z")
168 this%m_x => neko_registry%get_field("m_x")
169 this%m_y => neko_registry%get_field("m_y")
170 this%m_z => neko_registry%get_field("m_z")
171 call this%m_x%init(this%dm_Xh, "m_x")
172 call this%m_y%init(this%dm_Xh, "m_y")
173 call this%m_z%init(this%dm_Xh, "m_z")
174
175 ! Assign energy field
176 call neko_registry%add_field(this%dm_Xh, "E")
177 this%E => neko_registry%get_field("E")
178 call this%E%init(this%dm_Xh, "E")
179
180 ! Assign temperature field
181 call neko_registry%add_field(this%dm_Xh, "temperature")
182 this%temperature => neko_registry%get_field("temperature")
183 call this%temperature%init(this%dm_Xh, "temperature")
184
185 ! Assign maximum wave speed field
186 call neko_registry%add_field(this%dm_Xh, "max_wave_speed")
187 this%max_wave_speed => neko_registry%get_field("max_wave_speed")
188 call this%max_wave_speed%init(this%dm_Xh, "max_wave_speed")
189
190 ! Assign entropy field
191 call neko_registry%add_field(this%dm_Xh, "S")
192 this%S => neko_registry%get_field("S")
193 call this%S%init(this%dm_Xh, "S")
194
195 ! Assign artificial viscosity field (without physical viscosity)
196 call neko_registry%add_field(this%dm_Xh, "artificial_visc")
197 this%artificial_visc => neko_registry%get_field("artificial_visc")
198 call this%artificial_visc%init(this%dm_Xh, "artificial_visc")
199
200 ! ! Assign velocity fields
201 call neko_registry%add_field(this%dm_Xh, "u")
202 call neko_registry%add_field(this%dm_Xh, "v")
203 call neko_registry%add_field(this%dm_Xh, "w")
204 this%u => neko_registry%get_field("u")
205 this%v => neko_registry%get_field("v")
206 this%w => neko_registry%get_field("w")
207 call this%u%init(this%dm_Xh, "u")
208 call this%v%init(this%dm_Xh, "v")
209 call this%w%init(this%dm_Xh, "w")
210 call neko_registry%add_field(this%dm_Xh, 'p')
211 this%p => neko_registry%get_field('p')
212 call this%p%init(this%dm_Xh, "p")
213
214 !
215 ! Setup right-hand side fields.
216 !
217 allocate(this%f_x)
218 allocate(this%f_y)
219 allocate(this%f_z)
220 call this%f_x%init(this%dm_Xh, fld_name = "fluid_rhs_x")
221 call this%f_y%init(this%dm_Xh, fld_name = "fluid_rhs_y")
222 call this%f_z%init(this%dm_Xh, fld_name = "fluid_rhs_z")
223
224 ! Material properties
225 call this%set_material_properties(params, user)
226
227 ! Compressible parameters
228 call json_get_or_default(params, 'case.fluid.gamma', this%gamma, 1.4_rp)
229
230 ! Calculate global points for logging
231 this%glb_n_points = int(this%msh%glb_nelv, i8)*int(this%Xh%lxyz, i8)
232 this%glb_unique_points = int(glsum(this%c_Xh%mult, this%dm_Xh%size()), i8)
233
234 !
235 ! Log solver information
236 !
237 call this%log_solver_info(params, scheme, lx)
238 end subroutine fluid_scheme_compressible_init
239
243 class(fluid_scheme_compressible_t), intent(inout) :: this
244 class(bc_t), pointer :: bc
245 integer :: i
246
247 do i = 1, this%bcs_vel%size()
248 bc => this%bcs_vel%get(i)
249 if (associated(bc)) then
250 call bc%free()
251 deallocate(bc)
252 end if
253 end do
254 call this%bcs_vel%free()
255
256 do i = 1, this%bcs_prs%size()
257 bc => this%bcs_prs%get(i)
258 if (associated(bc)) then
259 call bc%free()
260 deallocate(bc)
261 end if
262 end do
263 call this%bcs_prs%free()
264
265 call this%dm_Xh%free()
266 call this%gs_Xh%free()
267 call this%c_Xh%free()
268 call this%Xh%free()
269
270 if (associated(this%m_x)) then
271 call this%m_x%free()
272 end if
273
274 if (associated(this%m_y)) then
275 call this%m_y%free()
276 end if
277
278 if (associated(this%m_z)) then
279 call this%m_z%free()
280 end if
281
282 if (associated(this%E)) then
283 call this%E%free()
284 end if
285
286 if (associated(this%temperature)) then
287 call this%temperature%free()
288 end if
289
290 if (associated(this%max_wave_speed)) then
291 call this%max_wave_speed%free()
292 end if
293
294 if (associated(this%S)) then
295 call this%S%free()
296 end if
297
298 if (associated(this%f_x)) then
299 call this%f_x%free()
300 deallocate(this%f_x)
301 end if
302
303 if (associated(this%f_y)) then
304 call this%f_y%free()
305 deallocate(this%f_y)
306 end if
307
308 if (associated(this%f_z)) then
309 call this%f_z%free()
310 deallocate(this%f_z)
311 end if
312
313 nullify(this%f_x)
314 nullify(this%f_y)
315 nullify(this%f_z)
316
317 nullify(this%m_x)
318 nullify(this%m_y)
319 nullify(this%m_z)
320 nullify(this%E)
321 nullify(this%temperature)
322 nullify(this%max_wave_speed)
323 nullify(this%S)
324
325 nullify(this%u)
326 nullify(this%v)
327 nullify(this%w)
328 nullify(this%p)
329 nullify(this%rho)
330 nullify(this%mu)
331 nullify(this%kappa)
332
333 call this%material_properties%free()
334
335 end subroutine fluid_scheme_compressible_free
336
340 class(fluid_scheme_compressible_t), target, intent(inout) :: this
341 integer :: n, i
342 type(field_t), pointer :: temp
343 integer :: temp_indices(1)
344
345 n = this%dm_Xh%size()
346 call neko_scratch_registry%request_field(temp, temp_indices(1), .false.)
347
349 call field_col3(this%m_x, this%u, this%rho)
350 call field_col3(this%m_y, this%v, this%rho)
351 call field_col3(this%m_z, this%w, this%rho)
352
355 call field_cmult2(this%E, this%p, 1.0_rp/(this%gamma - 1.0_rp), n)
356 call field_col3(temp, this%u, this%u, n)
357 call field_addcol3(temp, this%v, this%v, n)
358 call field_addcol3(temp, this%w, this%w, n)
359 call field_col2(temp, this%rho, n)
360 call field_cmult(temp, 0.5_rp, n)
361 call field_add2(this%E, temp, n)
362
364 do i = 1, n
365 this%temperature%x(i,1,1,1) = this%p%x(i,1,1,1) / &
366 (this%rho%x(i,1,1,1) * (this%gamma - 1.0_rp))
367 end do
368
369 call neko_scratch_registry%relinquish_field(temp_indices)
370
372 call this%compute_max_wave_speed()
373
375
380 function fluid_scheme_compressible_compute_cfl(this, dt) result(c)
381 class(fluid_scheme_compressible_t), intent(in) :: this
382 real(kind=rp), intent(in) :: dt
383 real(kind=rp) :: c
384 integer :: n
385
386 associate(u => this%u, v => this%v, w => this%w, p => this%p, &
387 rho => this%rho, xh => this%Xh, c_xh => this%c_Xh, &
388 msh => this%msh, gamma => this%gamma, &
389 max_wave_speed => this%max_wave_speed)
390
391 n = xh%lx * xh%ly * xh%lz * msh%nelv
392
393 ! Use the compressible CFL function with precomputed maximum wave speed
394 c = cfl_compressible(dt, max_wave_speed%x, xh, c_xh, msh%nelv, msh%gdim)
395 end associate
396
398
404 params, user)
405 class(fluid_scheme_compressible_t), target, intent(inout) :: this
406 type(json_file), intent(inout) :: params
407 type(user_t), target, intent(in) :: user
408 procedure(user_material_properties_intf), pointer :: dummy_mp_ptr
409 type(time_state_t) :: dummy_time_state
410 character(len=LOG_SIZE) :: log_buf
411 real(kind=rp) :: const_mu, const_kappa
412
413 dummy_mp_ptr => dummy_user_material_properties
414
415 call neko_registry%add_field(this%dm_Xh, this%name // "_mu")
416 this%mu => neko_registry%get_field(this%name // "_mu")
417
418 call neko_registry%add_field(this%dm_Xh, this%name // "_kappa")
419 this%kappa => neko_registry%get_field(this%name // "_kappa")
420
421 call this%material_properties%init(3)
422 call this%material_properties%assign(1, this%rho)
423 call this%material_properties%assign(2, this%mu)
424 call this%material_properties%assign(3, this%kappa)
425
426 if (.not. associated(user%material_properties, dummy_mp_ptr)) then
427 this%user_material_properties => user%material_properties
428 call user%material_properties(this%name, this%material_properties, &
429 dummy_time_state)
430 else
431 this%user_material_properties => dummy_user_material_properties
432 call json_get_or_lookup_or_default(params, 'case.fluid.mu', const_mu, &
433 0.0_rp)
434 call json_get_or_lookup_or_default(params, 'case.fluid.kappa', &
435 const_kappa, 0.0_rp)
436
437 call field_cfill(this%mu, const_mu)
438 call field_cfill(this%kappa, const_kappa)
439
440 write(log_buf, '(A,ES13.6)') 'mu :', const_mu
441 call neko_log%message(log_buf)
442 write(log_buf, '(A,ES13.6)') 'kappa :', const_kappa
443 call neko_log%message(log_buf)
444 end if
445
447
453 class(fluid_scheme_compressible_t), intent(inout) :: this
454 type(time_state_t), intent(in) :: time
455
456 call this%user_material_properties(this%name, this%material_properties, &
457 time)
458
460
464 class(fluid_scheme_compressible_t), intent(inout) :: this
465 integer :: n
466
467 n = this%S%dof%size()
468
470 if (neko_bcknd_device .eq. 1) then
471 call compressible_ops_device_compute_entropy(this%S, this%p, this%rho, &
472 this%gamma, n)
473 else
474 call compressible_ops_cpu_compute_entropy(this%S%x, this%p%x, &
475 this%rho%x, this%gamma, n)
476 end if
477
479
483 class(fluid_scheme_compressible_t), intent(inout) :: this
484 integer :: n
485
486 n = this%u%dof%size()
487
489 if (neko_bcknd_device .eq. 1) then
490 call compressible_ops_device_compute_max_wave_speed( &
491 this%max_wave_speed, this%u, this%v, this%w, this%gamma, this%p, &
492 this%rho, n)
493 else
494 call compressible_ops_cpu_compute_max_wave_speed(this%max_wave_speed%x, &
495 this%u%x, this%v%x, this%w%x, this%gamma, this%p%x, this%rho%x, n)
496 end if
497
499
505 subroutine fluid_scheme_compressible_log_solver_info(this, params, scheme, lx)
506 class(fluid_scheme_compressible_t), intent(inout) :: this
507 type(json_file), intent(inout) :: params
508 character(len=*), intent(in) :: scheme
509 integer, intent(in) :: lx
510 character(len=LOG_SIZE) :: log_buf
511 logical :: logical_val
512 real(kind=rp) :: real_val
513 integer :: integer_val
514
515 call neko_log%section('Fluid')
516 write(log_buf, '(A, A)') 'Type : ', trim(scheme)
517 call neko_log%message(log_buf)
518 write(log_buf, '(A, A)') 'Name : ', trim(this%name)
519 call neko_log%message(log_buf)
520
521 ! Polynomial order
522 if (lx .lt. 10) then
523 write(log_buf, '(A, I1)') 'Poly order : ', lx-1
524 else if (lx .ge. 10) then
525 write(log_buf, '(A, I2)') 'Poly order : ', lx-1
526 else
527 write(log_buf, '(A, I3)') 'Poly order : ', lx-1
528 end if
529 call neko_log%message(log_buf)
530
531 ! Global points information
532 write(log_buf, '(A, I0)') 'GLL points : ', this%glb_n_points
533 call neko_log%message(log_buf)
534 write(log_buf, '(A, I0)') 'Unique pts.: ', this%glb_unique_points
535 call neko_log%message(log_buf)
536
537 ! Material properties
538 write(log_buf, '(A,ES13.6)') 'gamma :', this%gamma
539 call neko_log%message(log_buf)
540
541 ! Compressible-specific parameters
542 call json_get_or_default(params, 'case.numerics.c_avisc_low', real_val, &
543 0.5_rp)
544 write(log_buf, '(A,ES13.6)') 'c_avisc_low:', real_val
545 call neko_log%message(log_buf)
546
547 call json_get_or_default(params, 'case.numerics.time_order', integer_val, 4)
548 write(log_buf, '(A, I0)') 'RK order : ', integer_val
549 call neko_log%message(log_buf)
550 call neko_log%end_section()
551
553
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_entropy(s, p, rho, gamma, n)
Compute entropy field S = 1/(gamma-1) * rho * (log(p) - gamma * log(rho)) on CPU.
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_entropy(s, p, rho, gamma, n)
Compute entropy field S = 1/(gamma-1) * rho * (log(p) - gamma * log(rho)) on device.
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.
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.
subroutine fluid_scheme_compressible_init(this, msh, lx, params, scheme, user)
Initialize common data for compressible fluid scheme.
real(kind=rp) function fluid_scheme_compressible_compute_cfl(this, dt)
Compute CFL number.
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.
subroutine fluid_scheme_compressible_compute_entropy(this)
Compute entropy field S = 1/(gamma-1) * rho * (log(p) - gamma * log(rho))
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:80
integer, parameter, public log_size
Definition log.f90:46
Definition math.f90:60
real(kind=rp) function, public glsum(a, n)
Sum a vector of length n.
Definition math.f90:629
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 rp
Global precision used in computations.
Definition num_types.f90:12
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:144
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:62
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...