Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
fluid_scheme_incompressible.f90
Go to the documentation of this file.
1! Copyright (c) 2020-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!
36 use gather_scatter, only : gs_t, gs_op_min, gs_op_max
38 use checkpoint, only : chkp_t
39 use num_types, only : rp, i8, dp
41 use field, only : field_t
42 use space, only : gll, operator(.ne.)
43 use dofmap, only : dofmap_t
45 use coefs, only : coef_t
46 use dirichlet, only : dirichlet_t
47 use precon, only : pc_t, precon_factory
48 use fluid_stats, only : fluid_stats_t
49 use bc, only : bc_t, bc_dirichlet
50 use bc_list, only : bc_list_t
51 use mesh, only : mesh_t
52 use math, only : glsum
53 use operators, only : cfl, rotate_cyc
55 use registry, only : neko_registry
58 use json_module, only : json_file
62 use utils, only : neko_error
66 use time_state, only : time_state_t
68 implicit none
69 private
70
75 class(ksp_t), allocatable :: ksp_vel
76 class(ksp_t), allocatable :: ksp_prs
77 class(pc_t), allocatable :: pc_vel
78 class(pc_t), allocatable :: pc_prs
79 integer :: vel_projection_dim
80 integer :: pr_projection_dim
81 integer :: vel_projection_activ_step
82 integer :: pr_projection_activ_step
83 logical :: pr_projection_reorthogonalize_basis
84 logical :: strict_convergence
85 logical :: allow_stabilization
87 logical :: svv_enabled = .false.
89 type(svv_t), allocatable :: svv
91 type(field_t), pointer :: u_e => null()
92 type(field_t), pointer :: v_e => null()
93 type(field_t), pointer :: w_e => null()
94
96 logical :: forced_flow_rate = .false.
97
99 character(len=:), allocatable :: nut_field_name
100
101 ! The total viscosity field
102 type(field_t), pointer :: mu_tot => null()
103
105 integer(kind=i8) :: glb_n_points
107 integer(kind=i8) :: glb_unique_points
108 contains
110 procedure, pass(this) :: init_base => fluid_scheme_init_base
111 procedure, pass(this) :: scheme_free => fluid_scheme_free
113 procedure, pass(this) :: validate => fluid_scheme_validate
115 procedure, pass(this) :: bc_apply_vel => fluid_scheme_bc_apply_vel
117 procedure, pass(this) :: bc_apply_prs => fluid_scheme_bc_apply_prs
119 procedure, pass(this) :: compute_cfl => fluid_compute_cfl
121 procedure, pass(this) :: set_material_properties => &
123
125 procedure, pass(this) :: update_material_properties => &
128 procedure, nopass :: solver_factory => fluid_scheme_solver_factory
130 procedure, pass(this) :: precon_factory_ => fluid_scheme_precon_factory
132
133 interface
134
135 module subroutine fluid_scheme_factory(object, type_name)
136 class(fluid_scheme_base_t), intent(inout), allocatable :: object
137 character(len=*) :: type_name
138 end subroutine fluid_scheme_factory
139 end interface
140
141 public :: fluid_scheme_incompressible_t, fluid_scheme_factory
142
143contains
144
146 subroutine fluid_scheme_init_base(this, msh, lx, params, scheme, user, &
147 kspv_init)
148 implicit none
149 class(fluid_scheme_incompressible_t), target, intent(inout) :: this
150 type(mesh_t), target, intent(inout) :: msh
151 integer, intent(in) :: lx
152 character(len=*), intent(in) :: scheme
153 type(json_file), target, intent(inout) :: params
154 type(user_t), target, intent(in) :: user
155 logical, intent(in) :: kspv_init
156 type(dirichlet_t) :: bdry_mask
157 character(len=LOG_SIZE) :: log_buf
158 real(kind=rp), allocatable :: real_vec(:)
159 real(kind=rp) :: real_val, kappa, b, z0
160 logical :: logical_val, full_stress_formulation
161 integer :: integer_val, ierr
162 type(json_file) :: wm_json
163 character(len=:), allocatable :: string_val1, string_val2
164 type(json_file) :: json_subdict, solver_params
165
166 !
167 ! SEM simulation fundamentals
168 !
169
170 this%msh => msh
171
172 if (msh%gdim .eq. 2) then
173 call this%Xh%init(gll, lx, lx)
174 else
175 call this%Xh%init(gll, lx, lx, lx)
176 end if
177
178 call this%dm_Xh%init(msh, this%Xh)
179
180 call this%gs_Xh%init(this%dm_Xh)
181
182 call this%c_Xh%init(this%gs_Xh)
183
184 ! Assign Dofmap to scratch registry
185 call neko_scratch_registry%set_dofmap(this%dm_Xh)
186
187 ! Assign a name
188 call json_get_or_default(params, 'case.fluid.name', this%name, "fluid")
189
190 !
191 ! First section of fluid log
192 !
193
194 call neko_log%section('Fluid')
195 write(log_buf, '(A, A)') 'Type : ', trim(scheme)
196 call neko_log%message(log_buf)
197 write(log_buf, '(A, A)') 'Name : ', trim(this%name)
198 call neko_log%message(log_buf)
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
208 !
209 ! Material properties
210 !
211 call this%set_material_properties(params, user)
212
213 ! Projection spaces
214 call json_get_or_lookup_or_default(params, &
215 'case.fluid.velocity_solver.projection_space_size', &
216 this%vel_projection_dim, 0)
217 call json_get_or_lookup_or_default(params, &
218 'case.fluid.pressure_solver.projection_space_size', &
219 this%pr_projection_dim, 0)
220 call json_get_or_lookup_or_default(params, &
221 'case.fluid.velocity_solver.projection_hold_steps', &
222 this%vel_projection_activ_step, 5)
223 call json_get_or_lookup_or_default(params, &
224 'case.fluid.pressure_solver.projection_hold_steps', &
225 this%pr_projection_activ_step, 5)
226 call json_get_or_default(params, &
227 'case.fluid.pressure_solver.projection_reorthogonalize_basis', &
228 this%pr_projection_reorthogonalize_basis, .false.)
229
230 call json_get_or_default(params, 'case.fluid.freeze', this%freeze, .false.)
231
232 if (params%valid_path("case.fluid.flow_rate_force")) then
233 this%forced_flow_rate = .true.
234 end if
235
236
237 if (lx .lt. 10) then
238 write(log_buf, '(A, I1)') 'Poly order : ', lx-1
239 else if (lx .ge. 10) then
240 write(log_buf, '(A, I2)') 'Poly order : ', lx-1
241 else
242 write(log_buf, '(A, I3)') 'Poly order : ', lx-1
243 end if
244 call neko_log%message(log_buf)
245 this%glb_n_points = int(this%msh%glb_nelv, i8)*int(this%Xh%lxyz, i8)
246 this%glb_unique_points = int(glsum(this%c_Xh%mult, this%dm_Xh%size()), i8)
247
248 write(log_buf, '(A, I0)') 'GLL points : ', this%glb_n_points
249 call neko_log%message(log_buf)
250 write(log_buf, '(A, I0)') 'Unique pts.: ', this%glb_unique_points
251 call neko_log%message(log_buf)
252
253
254 call json_get(params, 'case.numerics.dealias', logical_val)
255 write(log_buf, '(A, L1)') 'Dealias : ', logical_val
256 call neko_log%message(log_buf)
257
258
259 call json_get_or_default(params, 'case.output_boundary', logical_val, &
260 .false.)
261 write(log_buf, '(A, L1)') 'Save bdry : ', logical_val
262 call neko_log%message(log_buf)
263
264 call json_get_or_default(params, "case.fluid.full_stress_formulation", &
265 full_stress_formulation, .false.)
266 write(log_buf, '(A, L1)') 'Full stress: ', full_stress_formulation
267 call neko_log%message(log_buf)
268
269 ! Compressed geometric factors, read by the standard Helmholtz
270 ! operators of the fluid, the scalars and the multigrid levels
271 call json_get_or_default(params, &
272 'case.numerics.compress_geometric_factors', logical_val, .false.)
273 write(log_buf, '(A, L1)') 'Compress G : ', logical_val
274 call neko_log%message(log_buf)
275 if (logical_val) then
276 if (params%valid_path( &
277 'case.numerics.compress_geometric_factors_tolerance')) then
278 call json_get_or_lookup(params, &
279 'case.numerics.compress_geometric_factors_tolerance', real_val)
280 call this%c_Xh%enable_geo_compression(real_val)
281 else
282 call this%c_Xh%enable_geo_compression()
283 end if
284 end if
285
286
287 !
288 ! Setup right-hand side fields.
289 !
290 allocate(this%f_x)
291 allocate(this%f_y)
292 allocate(this%f_z)
293 call this%f_x%init(this%dm_Xh, fld_name = "fluid_rhs_x")
294 call this%f_y%init(this%dm_Xh, fld_name = "fluid_rhs_y")
295 call this%f_z%init(this%dm_Xh, fld_name = "fluid_rhs_z")
296
297 ! Initialize velocity solver
298 if (kspv_init) then
299 call neko_log%section("Velocity solver")
300 call json_get(params, 'case.fluid.velocity_solver', solver_params)
301 call json_get(params, 'case.fluid.velocity_solver.type', string_val1)
302 call json_get(params, 'case.fluid.velocity_solver.preconditioner.type', &
303 string_val2)
304 call json_get(params, &
305 'case.fluid.velocity_solver.preconditioner', json_subdict)
306 call json_get_or_lookup(params, &
307 'case.fluid.velocity_solver.absolute_tolerance', &
308 real_val)
309
310 call neko_log%message('Type : ('// trim(string_val1) // &
311 ', ' // trim(string_val2) // ')')
312
313 write(log_buf, '(A,ES13.6)') 'Abs tol :', real_val
314 call neko_log%message(log_buf)
315 call this%solver_factory(this%ksp_vel, this%dm_Xh%size(), &
316 solver_params)
317 call this%precon_factory_(this%pc_vel, this%ksp_vel, &
318 this%c_Xh, this%bcs_vel, &
319 string_val2, json_subdict)
320 call neko_log%end_section()
321 end if
322
323 ! Strict convergence for the velocity solver
324 call json_get_or_default(params, 'case.fluid.strict_convergence', &
325 this%strict_convergence, .false.)
326 ! Allow stabilization period where we do not warn about non-convergence
327 call json_get_or_default(params, 'case.fluid.allow_stabilization', &
328 this%allow_stabilization, .false.)
329
330
331 !! Initialize time-lag fields
332 call this%ulag%init(this%u, 2)
333 call this%vlag%init(this%v, 2)
334 call this%wlag%init(this%w, 2)
335
336 call neko_registry%add_field(this%dm_Xh, 'u_e')
337 call neko_registry%add_field(this%dm_Xh, 'v_e')
338 call neko_registry%add_field(this%dm_Xh, 'w_e')
339 this%u_e => neko_registry%get_field('u_e')
340 this%v_e => neko_registry%get_field('v_e')
341 this%w_e => neko_registry%get_field('w_e')
342
343 ! Initialize the source term
344 call neko_log%section('Fluid Source term')
345 call this%source_term%init(this%f_x, this%f_y, this%f_z, this%c_Xh, user, &
346 this%name)
347 call this%source_term%add(params, 'case.fluid.source_terms')
348 call neko_log%end_section()
349
350 if (params%valid_path('case.fluid.svv')) then
351 call json_get(params, 'case.fluid', json_subdict)
352 call json_get_or_default(json_subdict, 'svv.enabled', &
353 this%svv_enabled, .false.)
354 if (this%svv_enabled) then
355 if (.not. kspv_init) then
356 call neko_error("SVV is only supported by fluid " // &
357 "schemes with an implicit velocity solve")
358 end if
359 if (full_stress_formulation) then
360 if (trim(string_val1) .ne. 'coupled_cg' .and. &
361 trim(string_val1) .ne. 'fused_coupled_cg') then
362 call neko_error("Full-stress SVV requires a " // &
363 "coupled velocity solver (`coupled_cg` or " // &
364 "`fused_coupled_cg`)")
365 end if
366 end if
367 allocate(this%svv)
368 call this%svv%init(json_subdict, this%c_Xh, this%rho)
369 end if
370 end if
371
372 end subroutine fluid_scheme_init_base
373
374 subroutine fluid_scheme_free(this)
375 class(fluid_scheme_incompressible_t), intent(inout) :: this
376 class(bc_t), pointer :: bc
377 integer :: i
378
379
380 if (allocated(this%svv)) then
381 call this%svv%free()
382 deallocate(this%svv)
383 end if
384 this%svv_enabled = .false.
385
386 call this%Xh%free()
387
388 if (allocated(this%ksp_vel)) then
389 call this%ksp_vel%free()
390 deallocate(this%ksp_vel)
391 end if
392
393 if (allocated(this%ksp_prs)) then
394 call this%ksp_prs%free()
395 deallocate(this%ksp_prs)
396 end if
397
398 if (allocated(this%pc_vel)) then
399 call this%pc_vel%free()
400 deallocate(this%pc_vel)
401 end if
402
403 if (allocated(this%pc_prs)) then
404 call this%pc_prs%free()
405 deallocate(this%pc_prs)
406 end if
407
408 do i = 1, this%bcs_vel%size()
409 bc => this%bcs_vel%get(i)
410 if (associated(bc)) then
411 call bc%free()
412 deallocate(bc)
413 end if
414 end do
415 call this%bcs_vel%free()
416
417 do i = 1, this%bcs_prs%size()
418 bc => this%bcs_prs%get(i)
419 if (associated(bc)) then
420 call bc%free()
421 deallocate(bc)
422 end if
423 end do
424 call this%bcs_prs%free()
425
426 call this%source_term%free()
427
428 call this%gs_Xh%free()
429
430 call this%c_Xh%free()
431
432 nullify(this%u)
433 nullify(this%v)
434 nullify(this%w)
435 nullify(this%p)
436
437 nullify(this%u_e)
438 nullify(this%v_e)
439 nullify(this%w_e)
440
441 call this%ulag%free()
442 call this%vlag%free()
443 call this%wlag%free()
444
445
446 if (associated(this%f_x)) then
447 call this%f_x%free()
448 deallocate(this%f_x)
449 end if
450
451 if (associated(this%f_y)) then
452 call this%f_y%free()
453 deallocate(this%f_y)
454 end if
455
456 if (associated(this%f_z)) then
457 call this%f_z%free()
458 deallocate(this%f_z)
459 end if
460
461 nullify(this%f_x)
462 nullify(this%f_y)
463 nullify(this%f_z)
464 nullify(this%rho)
465 nullify(this%mu)
466 nullify(this%mu_tot)
467
468 call this%dm_Xh%free()
469 call this%Xh%free()
470 nullify(this%msh)
471
472 end subroutine fluid_scheme_free
473
476 subroutine fluid_scheme_validate(this)
477 class(fluid_scheme_incompressible_t), target, intent(inout) :: this
478 ! Variables for retrieving json parameters
479 logical :: logical_val
480
481 if ( (.not. associated(this%u)) .or. &
482 (.not. associated(this%v)) .or. &
483 (.not. associated(this%w)) .or. &
484 (.not. associated(this%p))) then
485 call neko_error('Fields are not registered')
486 end if
487
488 if ( (.not. allocated(this%u%x)) .or. &
489 (.not. allocated(this%v%x)) .or. &
490 (.not. allocated(this%w%x)) .or. &
491 (.not. allocated(this%p%x))) then
492 call neko_error('Fields are not allocated')
493 end if
494
495 if (this%u%Xh .ne. this%v%Xh .or. &
496 this%u%Xh .ne. this%w%Xh) then
497 call neko_error('Different function spaces for velocity components')
498 end if
499
500 if (this%u%msh%nelv .ne. this%p%msh%nelv) then
501 call neko_error('Velocity and pressure defined on different meshes')
502 end if
503
504 if (.not. allocated(this%ksp_vel)) then
505 call neko_error('No Krylov solver for velocity defined')
506 end if
507
508 if (.not. allocated(this%ksp_prs)) then
509 call neko_error('No Krylov solver for pressure defined')
510 end if
511
512 end subroutine fluid_scheme_validate
513
518 subroutine fluid_scheme_bc_apply_vel(this, time, strong)
519 class(fluid_scheme_incompressible_t), intent(inout) :: this
520 type(time_state_t), intent(in) :: time
521 logical, intent(in) :: strong
522 integer :: i
523 class(bc_t), pointer :: b
524
525 call this%bcs_vel%apply_vector(&
526 this%u%x, this%v%x, this%w%x, this%dm_Xh%size(), time, strong)
527
528 call rotate_cyc(this%u, this%v, this%w, 1, this%c_Xh)
529 call this%gs_Xh%op(this%u, gs_op_min, glb_cmd_event)
531 call this%gs_Xh%op(this%v, gs_op_min, glb_cmd_event)
533 call this%gs_Xh%op(this%w, gs_op_min, glb_cmd_event)
535 call rotate_cyc(this%u, this%v, this%w, 0, this%c_Xh)
536
537 ! Double pass for Dirichlet bcs only.
538 b => null()
539 do i = 1, this%bcs_vel%size()
540 b => this%bcs_vel%get(i)
541 if (b%bc_type .eq. bc_dirichlet) then
542 call b%apply_vector_generic(this%u, this%v, this%w,time, strong)
543 end if
544 end do
545
546 call rotate_cyc(this%u, this%v, this%w, 1, this%c_Xh)
547 call this%gs_Xh%op(this%u, gs_op_max, glb_cmd_event)
549 call this%gs_Xh%op(this%v, gs_op_max, glb_cmd_event)
551 call this%gs_Xh%op(this%w, gs_op_max, glb_cmd_event)
553 call rotate_cyc(this%u, this%v, this%w, 0, this%c_Xh)
554
555 do i = 1, this%bcs_vel%size()
556 b => this%bcs_vel%get(i)
557 b%updated = .false.
558 end do
559 nullify(b)
560
561 end subroutine fluid_scheme_bc_apply_vel
562
565 subroutine fluid_scheme_bc_apply_prs(this, time)
566 class(fluid_scheme_incompressible_t), intent(inout) :: this
567 type(time_state_t), intent(in) :: time
568
569 integer :: i
570 class(bc_t), pointer :: b
571 b => null()
572
573 call this%bcs_prs%apply(this%p, time)
574 call this%gs_Xh%op(this%p, gs_op_min, glb_cmd_event)
576
577 call this%bcs_prs%apply(this%p, time)
578 call this%gs_Xh%op(this%p, gs_op_max, glb_cmd_event)
580
581 do i = 1, this%bcs_prs%size()
582 b => this%bcs_prs%get(i)
583 b%updated = .false.
584 end do
585 nullify(b)
586
587 end subroutine fluid_scheme_bc_apply_prs
588
591 subroutine fluid_scheme_solver_factory(ksp, n, params)
592 class(ksp_t), allocatable, target, intent(inout) :: ksp
593 integer, intent(in), value :: n
594 type(json_file), intent(inout) :: params
595
596 call krylov_solver_factory(ksp, n, params)
597
598 end subroutine fluid_scheme_solver_factory
599
601 subroutine fluid_scheme_precon_factory(this, pc, ksp, coef, bclst, &
602 pctype, json)
603 class(fluid_scheme_incompressible_t), intent(inout) :: this
604 class(pc_t), allocatable, target, intent(inout) :: pc
605 class(ksp_t), target, intent(inout) :: ksp
606 type(coef_t), target, intent(in) :: coef
607 type(bc_list_t), target, intent(inout) :: bclst
608 character(len=*) :: pctype
609 type(json_file), intent(inout) :: json
610
611 call precon_factory(pc, pctype, coef, bclst, json)
612
613 call ksp%set_pc(pc)
614
615 end subroutine fluid_scheme_precon_factory
616
618 function fluid_compute_cfl(this, dt) result(c)
619 class(fluid_scheme_incompressible_t), intent(in) :: this
620 real(kind=dp), intent(in) :: dt
621 real(kind=dp) :: c
622
623 c = cfl(dt, this%u, this%v, this%w, &
624 this%Xh, this%c_Xh, this%msh%nelv, this%msh%gdim)
625
626 end function fluid_compute_cfl
627
628
633 subroutine fluid_scheme_update_material_properties(this, time)
634 class(fluid_scheme_incompressible_t), intent(inout) :: this
635 type(time_state_t), intent(in) :: time
636 type(field_t), pointer :: nut
637
638 call this%user_material_properties(this%name, this%material_properties, &
639 time)
640
641 if (len(trim(this%nut_field_name)) > 0) then
642 nut => neko_registry%get_field(this%nut_field_name)
643 ! Copy material property
644 call field_copy(this%mu_tot, this%mu)
645 ! Add turbulent contribution
646 call field_addcol3(this%mu_tot, nut, this%rho)
647 end if
648
649 ! Since mu, rho is a field_t, and we use the %x(1,1,1,1)
650 ! host array data to pass constant density and viscosity
651 ! to some routines, we need to make sure that the host
652 ! values are also filled
653 if (neko_bcknd_device .eq. 1) then
654 call device_memcpy(this%rho%x, this%rho%x_d, this%rho%size(), &
655 device_to_host, sync = .false.)
656 end if
657 end subroutine fluid_scheme_update_material_properties
658
662 subroutine fluid_scheme_set_material_properties(this, params, user)
663 class(fluid_scheme_incompressible_t), target, intent(inout) :: this
664 type(json_file), intent(inout) :: params
665 type(user_t), target, intent(in) :: user
666 character(len=LOG_SIZE) :: log_buf
667 ! A local pointer that is needed to make Intel happy
668 procedure(user_material_properties_intf), pointer :: dummy_mp_ptr
669 logical :: nondimensional
670 real(kind=rp) :: dummy_lambda, dummy_cp
671 real(kind=rp) :: const_mu, const_rho
672 type(time_state_t) :: dummy_time_state
673
674
675 dummy_mp_ptr => dummy_user_material_properties
676
677 call neko_registry%add_field(this%dm_Xh, this%name // "_mu")
678 call neko_registry%add_field(this%dm_Xh, this%name // "_mu_tot")
679 call neko_registry%add_field(this%dm_Xh, this%name // "_rho")
680 this%mu => neko_registry%get_field(this%name // "_mu")
681 this%mu_tot => neko_registry%get_field(this%name // "_mu_tot")
682 this%rho => neko_registry%get_field(this%name // "_rho")
683
684 call this%material_properties%init(2)
685 call this%material_properties%assign(1, this%rho)
686 call this%material_properties%assign(2, this%mu)
687
688 if (.not. associated(user%material_properties, dummy_mp_ptr)) then
689
690 write(log_buf, '(A)') 'Material properties must be set in the user' // &
691 ' file!'
692 call neko_log%message(log_buf)
693 this%user_material_properties => user%material_properties
694
695 call user%material_properties(this%name, this%material_properties, &
696 dummy_time_state)
697
698 else
699 this%user_material_properties => dummy_user_material_properties
700 ! Incorrect user input
701 if (params%valid_path('case.fluid.Re') .and. &
702 (params%valid_path('case.fluid.mu') .or. &
703 params%valid_path('case.fluid.rho'))) then
704 call neko_error("To set the material properties for the fluid, " // &
705 "either provide Re OR mu and rho in the case file.")
706
707 else if (params%valid_path('case.fluid.Re')) then
708 ! Non-dimensional case
709 write(log_buf, '(A)') 'Non-dimensional fluid material properties &
710 & input.'
711 call neko_log%message(log_buf, lvl = neko_log_verbose)
712 write(log_buf, '(A)') 'Density will be set to 1, dynamic viscosity to&
713 & 1/Re.'
714 call neko_log%message(log_buf, lvl = neko_log_verbose)
715
716 ! Read Re into mu for further manipulation.
717 call json_get_or_lookup(params, 'case.fluid.Re', const_mu)
718 write(log_buf, '(A)') 'Read non-dimensional material properties'
719 call neko_log%message(log_buf)
720 write(log_buf, '(A,ES13.6)') 'Re :', const_mu
721 call neko_log%message(log_buf)
722
723 ! Set rho to 1 since the setup is non-dimensional.
724 const_rho = 1.0_rp
725 ! Invert the Re to get viscosity.
726 const_mu = 1.0_rp/const_mu
727 else
728 ! Dimensional case
729 call json_get_or_lookup(params, 'case.fluid.mu', const_mu)
730 call json_get_or_lookup(params, 'case.fluid.rho', const_rho)
731 end if
732 end if
733
734 ! We need to fill the fields based on the parsed const values
735 ! if the user routine is not used.
736 if (associated(user%material_properties, dummy_mp_ptr)) then
737 ! Fill mu and rho field with the physical value
738 call field_cfill(this%mu, const_mu)
739 call field_cfill(this%mu_tot, const_mu)
740 call field_cfill(this%rho, const_rho)
741
742
743 write(log_buf, '(A,ES13.6)') 'rho :', const_rho
744 call neko_log%message(log_buf)
745 write(log_buf, '(A,ES13.6)') 'mu :', const_mu
746 call neko_log%message(log_buf)
747 end if
748
749 ! Copy over material property to the total one
750 call field_copy(this%mu_tot, this%mu)
751
752 ! Since mu, rho is a field_t, and we use the %x(1,1,1,1)
753 ! host array data to pass constant density and viscosity
754 ! to some routines, we need to make sure that the host
755 ! values are also filled
756 if (neko_bcknd_device .eq. 1) then
757 call device_memcpy(this%rho%x, this%rho%x_d, this%rho%size(), &
758 device_to_host, sync = .false.)
759 call device_memcpy(this%mu%x, this%mu%x_d, this%mu%size(), &
760 device_to_host, sync = .false.)
761 call device_memcpy(this%mu_tot%x, this%mu_tot%x_d, this%mu%size(), &
762 device_to_host, sync = .false.)
763 end if
764 end subroutine fluid_scheme_set_material_properties
765
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...
Retrieves a parameter by name or throws an error.
Factory for Krylov solvers. Both creates and initializes the object, either from its parameters or fr...
Definition krylov.f90:221
Compute CFL condition.
Definition operators.f90:98
Apply cyclic boundary condition to a vector field.
Abstract interface for setting material properties.
Defines a list of bc_t.
Definition bc_list.f90:34
Defines a boundary condition.
Definition bc.f90:34
integer, parameter, public bc_dirichlet
Supported boundary condition types. The values are set in order of precedence for global resolution....
Definition bc.f90:67
Defines format-independent checkpoint registration and restart state.
Coefficients.
Definition coef.f90:34
Device abstraction, common interface for various accelerators.
Definition device.F90:34
subroutine, public device_event_sync(event)
Synchronize an event.
Definition device.F90:1705
integer, parameter, public device_to_host
Definition device.F90:48
type(c_ptr), bind(C), public glb_cmd_event
Event for the global command queue.
Definition device.F90:63
Defines a dirichlet boundary condition.
Definition dirichlet.f90:34
Defines a mapping of the degrees of freedom.
Definition dofmap.f90:35
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_copy(a, b, n)
Copy a vector .
Defines a field.
Definition field.f90:34
subroutine fluid_scheme_set_material_properties(this, params, user)
Sets rho and mu.
subroutine fluid_scheme_update_material_properties(this, time)
Call user material properties routine and update the values of mu if necessary.
subroutine fluid_scheme_validate(this)
Validate that all fields, solvers etc necessary for performing time-stepping are defined.
real(kind=dp) function fluid_compute_cfl(this, dt)
Compute CFL.
subroutine fluid_scheme_solver_factory(ksp, n, params)
Initialize a linear solver from its JSON solver block.
subroutine fluid_scheme_bc_apply_vel(this, time, strong)
Apply all boundary conditions defined for velocity Here we perform additional gs operations to take c...
subroutine fluid_scheme_bc_apply_prs(this, time)
Apply all boundary conditions defined for pressure.
subroutine fluid_scheme_precon_factory(this, pc, ksp, coef, bclst, pctype, json)
Initialize a Krylov preconditioner.
subroutine fluid_scheme_init_base(this, msh, lx, params, scheme, user, kspv_init)
Initialise a fluid scheme.
Implements the fluid_source_term_t type.
Computes various statistics for the fluid fields. We use the Reynolds decomposition for a field u = ...
Gather-scatter.
Utilities for retrieving parameters from the case files.
Implements the base abstract type for Krylov solvers plus helper types.
Definition krylov.f90:34
Logging routines.
Definition log.f90:34
integer, parameter, public neko_log_verbose
Verbose.
Definition log.f90:54
type(log_t), public neko_log
Global log stream.
Definition log.f90:92
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:643
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
Krylov preconditioner.
Definition precon.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.
Implements the source_term_t type and a wrapper source_term_wrapper_t.
Defines a function space.
Definition space.f90:34
integer, parameter, public gll
Definition space.f90:50
Data and filter construction for spectral vanishing viscosity.
Defines a container for all statistics.
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)
Utilities.
Definition utils.f90:35
Base type for a boundary condition.
Definition bc.f90:73
A list of allocatable `bc_t`. Follows the standard interface of lists.
Definition bc_list.f90:49
Collection of live simulation data registered for checkpointing.
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:136
Generic Dirichlet boundary condition on .
Definition dirichlet.f90:49
Base type of all fluid formulations.
Wrapper contaning and executing the fluid source terms.
Gather-scatter kernel.
Base abstract type for a canonical Krylov method, solving .
Definition krylov.f90:77
Defines a canonical Krylov preconditioner.
Definition precon.f90:44
Spectral vanishing viscosity configuration and coefficients.
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...