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
44 use krylov, only : ksp_t, krylov_solver_factory, ksp_max_iter
45 use coefs, only : coef_t
46 use dirichlet, only : dirichlet_t
47 use jacobi, only : jacobi_t
48 use sx_jacobi, only : sx_jacobi_t
50 use hsmg, only : hsmg_t
51 use phmg, only : phmg_t
52 use precon, only : pc_t, precon_allocator, precon_destroy
53 use fluid_stats, only : fluid_stats_t
54 use bc, only : bc_t, bc_dirichlet
55 use bc_list, only : bc_list_t
56 use mesh, only : mesh_t
57 use math, only : glsum
58 use operators, only : cfl, rotate_cyc
60 use registry, only : neko_registry
63 use json_module, only : json_file
67 use utils, only : neko_error
71 use time_state, only : time_state_t
73 implicit none
74 private
75
80 class(ksp_t), allocatable :: ksp_vel
81 class(ksp_t), allocatable :: ksp_prs
82 class(pc_t), allocatable :: pc_vel
83 class(pc_t), allocatable :: pc_prs
84 integer :: vel_projection_dim
85 integer :: pr_projection_dim
86 integer :: vel_projection_activ_step
87 integer :: pr_projection_activ_step
88 logical :: pr_projection_reorthogonalize_basis
89 logical :: strict_convergence
90 logical :: allow_stabilization
92 logical :: svv_enabled = .false.
94 type(svv_t), allocatable :: svv
96 type(field_t), pointer :: u_e => null()
97 type(field_t), pointer :: v_e => null()
98 type(field_t), pointer :: w_e => null()
99
101 logical :: forced_flow_rate = .false.
102
104 character(len=:), allocatable :: nut_field_name
105
106 ! The total viscosity field
107 type(field_t), pointer :: mu_tot => null()
108
110 integer(kind=i8) :: glb_n_points
112 integer(kind=i8) :: glb_unique_points
113 contains
115 procedure, pass(this) :: init_base => fluid_scheme_init_base
116 procedure, pass(this) :: scheme_free => fluid_scheme_free
118 procedure, pass(this) :: validate => fluid_scheme_validate
120 procedure, pass(this) :: bc_apply_vel => fluid_scheme_bc_apply_vel
122 procedure, pass(this) :: bc_apply_prs => fluid_scheme_bc_apply_prs
124 procedure, pass(this) :: compute_cfl => fluid_compute_cfl
126 procedure, pass(this) :: set_material_properties => &
128
130 procedure, pass(this) :: update_material_properties => &
133 procedure, nopass :: solver_factory => fluid_scheme_solver_factory
135 procedure, pass(this) :: precon_factory_ => fluid_scheme_precon_factory
137
138 interface
139
140 module subroutine fluid_scheme_factory(object, type_name)
141 class(fluid_scheme_base_t), intent(inout), allocatable :: object
142 character(len=*) :: type_name
143 end subroutine fluid_scheme_factory
144 end interface
145
146 public :: fluid_scheme_incompressible_t, fluid_scheme_factory
147
148contains
149
151 subroutine fluid_scheme_init_base(this, msh, lx, params, scheme, user, &
152 kspv_init)
153 implicit none
154 class(fluid_scheme_incompressible_t), target, intent(inout) :: this
155 type(mesh_t), target, intent(inout) :: msh
156 integer, intent(in) :: lx
157 character(len=*), intent(in) :: scheme
158 type(json_file), target, intent(inout) :: params
159 type(user_t), target, intent(in) :: user
160 logical, intent(in) :: kspv_init
161 type(dirichlet_t) :: bdry_mask
162 character(len=LOG_SIZE) :: log_buf
163 real(kind=rp), allocatable :: real_vec(:)
164 real(kind=rp) :: real_val, kappa, b, z0
165 logical :: logical_val, full_stress_formulation
166 integer :: integer_val, ierr
167 type(json_file) :: wm_json
168 character(len=:), allocatable :: string_val1, string_val2
169 type(json_file) :: json_subdict
170
171 !
172 ! SEM simulation fundamentals
173 !
174
175 this%msh => msh
176
177 if (msh%gdim .eq. 2) then
178 call this%Xh%init(gll, lx, lx)
179 else
180 call this%Xh%init(gll, lx, lx, lx)
181 end if
182
183 call this%dm_Xh%init(msh, this%Xh)
184
185 call this%gs_Xh%init(this%dm_Xh)
186
187 call this%c_Xh%init(this%gs_Xh)
188
189 ! Assign Dofmap to scratch registry
190 call neko_scratch_registry%set_dofmap(this%dm_Xh)
191
192 ! Assign a name
193 call json_get_or_default(params, 'case.fluid.name', this%name, "fluid")
194
195 !
196 ! First section of fluid log
197 !
198
199 call neko_log%section('Fluid')
200 write(log_buf, '(A, A)') 'Type : ', trim(scheme)
201 call neko_log%message(log_buf)
202 write(log_buf, '(A, A)') 'Name : ', trim(this%name)
203 call neko_log%message(log_buf)
204
205 ! Assign velocity fields
206 call neko_registry%add_field(this%dm_Xh, 'u')
207 call neko_registry%add_field(this%dm_Xh, 'v')
208 call neko_registry%add_field(this%dm_Xh, 'w')
209 this%u => neko_registry%get_field('u')
210 this%v => neko_registry%get_field('v')
211 this%w => neko_registry%get_field('w')
212
213 !
214 ! Material properties
215 !
216 call this%set_material_properties(params, user)
217
218 ! Projection spaces
219 call json_get_or_lookup_or_default(params, &
220 'case.fluid.velocity_solver.projection_space_size', &
221 this%vel_projection_dim, 0)
222 call json_get_or_lookup_or_default(params, &
223 'case.fluid.pressure_solver.projection_space_size', &
224 this%pr_projection_dim, 0)
225 call json_get_or_lookup_or_default(params, &
226 'case.fluid.velocity_solver.projection_hold_steps', &
227 this%vel_projection_activ_step, 5)
228 call json_get_or_lookup_or_default(params, &
229 'case.fluid.pressure_solver.projection_hold_steps', &
230 this%pr_projection_activ_step, 5)
231 call json_get_or_default(params, &
232 'case.fluid.pressure_solver.projection_reorthogonalize_basis', &
233 this%pr_projection_reorthogonalize_basis, .false.)
234
235 call json_get_or_default(params, 'case.fluid.freeze', this%freeze, .false.)
236
237 if (params%valid_path("case.fluid.flow_rate_force")) then
238 this%forced_flow_rate = .true.
239 end if
240
241
242 if (lx .lt. 10) then
243 write(log_buf, '(A, I1)') 'Poly order : ', lx-1
244 else if (lx .ge. 10) then
245 write(log_buf, '(A, I2)') 'Poly order : ', lx-1
246 else
247 write(log_buf, '(A, I3)') 'Poly order : ', lx-1
248 end if
249 call neko_log%message(log_buf)
250 this%glb_n_points = int(this%msh%glb_nelv, i8)*int(this%Xh%lxyz, i8)
251 this%glb_unique_points = int(glsum(this%c_Xh%mult, this%dm_Xh%size()), i8)
252
253 write(log_buf, '(A, I0)') 'GLL points : ', this%glb_n_points
254 call neko_log%message(log_buf)
255 write(log_buf, '(A, I0)') 'Unique pts.: ', this%glb_unique_points
256 call neko_log%message(log_buf)
257
258
259 call json_get(params, 'case.numerics.dealias', logical_val)
260 write(log_buf, '(A, L1)') 'Dealias : ', logical_val
261 call neko_log%message(log_buf)
262
263
264 call json_get_or_default(params, 'case.output_boundary', logical_val, &
265 .false.)
266 write(log_buf, '(A, L1)') 'Save bdry : ', logical_val
267 call neko_log%message(log_buf)
268
269 call json_get_or_default(params, "case.fluid.full_stress_formulation", &
270 full_stress_formulation, .false.)
271 write(log_buf, '(A, L1)') 'Full stress: ', full_stress_formulation
272 call neko_log%message(log_buf)
273
274
275 !
276 ! Setup right-hand side fields.
277 !
278 allocate(this%f_x)
279 allocate(this%f_y)
280 allocate(this%f_z)
281 call this%f_x%init(this%dm_Xh, fld_name = "fluid_rhs_x")
282 call this%f_y%init(this%dm_Xh, fld_name = "fluid_rhs_y")
283 call this%f_z%init(this%dm_Xh, fld_name = "fluid_rhs_z")
284
285 ! Initialize velocity solver
286 if (kspv_init) then
287 call neko_log%section("Velocity solver")
288 call json_get_or_lookup_or_default(params, &
289 'case.fluid.velocity_solver.max_iterations', &
290 integer_val, ksp_max_iter)
291 call json_get(params, 'case.fluid.velocity_solver.type', string_val1)
292 call json_get(params, 'case.fluid.velocity_solver.preconditioner.type', &
293 string_val2)
294 call json_get(params, &
295 'case.fluid.velocity_solver.preconditioner', json_subdict)
296 call json_get_or_lookup(params, &
297 'case.fluid.velocity_solver.absolute_tolerance', &
298 real_val)
299 call json_get_or_default(params, &
300 'case.fluid.velocity_solver.monitor', &
301 logical_val, .false.)
302
303 call neko_log%message('Type : ('// trim(string_val1) // &
304 ', ' // trim(string_val2) // ')')
305
306 write(log_buf, '(A,ES13.6)') 'Abs tol :', real_val
307 call neko_log%message(log_buf)
308 call this%solver_factory(this%ksp_vel, this%dm_Xh%size(), &
309 string_val1, integer_val, real_val, logical_val)
310 call this%precon_factory_(this%pc_vel, this%ksp_vel, &
311 this%c_Xh, this%dm_Xh, this%gs_Xh, this%bcs_vel, &
312 string_val2, json_subdict)
313 call neko_log%end_section()
314 end if
315
316 ! Strict convergence for the velocity solver
317 call json_get_or_default(params, 'case.fluid.strict_convergence', &
318 this%strict_convergence, .false.)
319 ! Allow stabilization period where we do not warn about non-convergence
320 call json_get_or_default(params, 'case.fluid.allow_stabilization', &
321 this%allow_stabilization, .false.)
322
323
324 !! Initialize time-lag fields
325 call this%ulag%init(this%u, 2)
326 call this%vlag%init(this%v, 2)
327 call this%wlag%init(this%w, 2)
328
329 call neko_registry%add_field(this%dm_Xh, 'u_e')
330 call neko_registry%add_field(this%dm_Xh, 'v_e')
331 call neko_registry%add_field(this%dm_Xh, 'w_e')
332 this%u_e => neko_registry%get_field('u_e')
333 this%v_e => neko_registry%get_field('v_e')
334 this%w_e => neko_registry%get_field('w_e')
335
336 ! Initialize the source term
337 call neko_log%section('Fluid Source term')
338 call this%source_term%init(this%f_x, this%f_y, this%f_z, this%c_Xh, user, &
339 this%name)
340 call this%source_term%add(params, 'case.fluid.source_terms')
341 call neko_log%end_section()
342
343 if (params%valid_path('case.fluid.svv')) then
344 call json_get(params, 'case.fluid', json_subdict)
345 call json_get_or_default(json_subdict, 'svv.enabled', &
346 this%svv_enabled, .false.)
347 if (this%svv_enabled) then
348 if (.not. kspv_init) then
349 call neko_error("SVV is only supported by fluid " // &
350 "schemes with an implicit velocity solve")
351 end if
352 if (full_stress_formulation) then
353 if (trim(string_val1) .ne. 'coupled_cg' .and. &
354 trim(string_val1) .ne. 'fused_coupled_cg') then
355 call neko_error("Full-stress SVV requires a " // &
356 "coupled velocity solver (`coupled_cg` or " // &
357 "`fused_coupled_cg`)")
358 end if
359 end if
360 allocate(this%svv)
361 call this%svv%init(json_subdict, this%c_Xh, this%rho)
362 end if
363 end if
364
365 end subroutine fluid_scheme_init_base
366
367 subroutine fluid_scheme_free(this)
368 class(fluid_scheme_incompressible_t), intent(inout) :: this
369 class(bc_t), pointer :: bc
370 integer :: i
371
372
373 if (allocated(this%svv)) then
374 call this%svv%free()
375 deallocate(this%svv)
376 end if
377 this%svv_enabled = .false.
378
379 call this%Xh%free()
380
381 if (allocated(this%ksp_vel)) then
382 call this%ksp_vel%free()
383 deallocate(this%ksp_vel)
384 end if
385
386 if (allocated(this%ksp_prs)) then
387 call this%ksp_prs%free()
388 deallocate(this%ksp_prs)
389 end if
390
391 if (allocated(this%pc_vel)) then
392 call precon_destroy(this%pc_vel)
393 deallocate(this%pc_vel)
394 end if
395
396 if (allocated(this%pc_prs)) then
397 call precon_destroy(this%pc_prs)
398 deallocate(this%pc_prs)
399 end if
400
401 do i = 1, this%bcs_vel%size()
402 bc => this%bcs_vel%get(i)
403 if (associated(bc)) then
404 call bc%free()
405 deallocate(bc)
406 end if
407 end do
408 call this%bcs_vel%free()
409
410 do i = 1, this%bcs_prs%size()
411 bc => this%bcs_prs%get(i)
412 if (associated(bc)) then
413 call bc%free()
414 deallocate(bc)
415 end if
416 end do
417 call this%bcs_prs%free()
418
419 call this%source_term%free()
420
421 call this%gs_Xh%free()
422
423 call this%c_Xh%free()
424
425 nullify(this%u)
426 nullify(this%v)
427 nullify(this%w)
428 nullify(this%p)
429
430 nullify(this%u_e)
431 nullify(this%v_e)
432 nullify(this%w_e)
433
434 call this%ulag%free()
435 call this%vlag%free()
436 call this%wlag%free()
437
438
439 if (associated(this%f_x)) then
440 call this%f_x%free()
441 deallocate(this%f_x)
442 end if
443
444 if (associated(this%f_y)) then
445 call this%f_y%free()
446 deallocate(this%f_y)
447 end if
448
449 if (associated(this%f_z)) then
450 call this%f_z%free()
451 deallocate(this%f_z)
452 end if
453
454 nullify(this%f_x)
455 nullify(this%f_y)
456 nullify(this%f_z)
457 nullify(this%rho)
458 nullify(this%mu)
459 nullify(this%mu_tot)
460
461 call this%dm_Xh%free()
462 call this%Xh%free()
463 nullify(this%msh)
464
465 end subroutine fluid_scheme_free
466
469 subroutine fluid_scheme_validate(this)
470 class(fluid_scheme_incompressible_t), target, intent(inout) :: this
471 ! Variables for retrieving json parameters
472 logical :: logical_val
473
474 if ( (.not. associated(this%u)) .or. &
475 (.not. associated(this%v)) .or. &
476 (.not. associated(this%w)) .or. &
477 (.not. associated(this%p))) then
478 call neko_error('Fields are not registered')
479 end if
480
481 if ( (.not. allocated(this%u%x)) .or. &
482 (.not. allocated(this%v%x)) .or. &
483 (.not. allocated(this%w%x)) .or. &
484 (.not. allocated(this%p%x))) then
485 call neko_error('Fields are not allocated')
486 end if
487
488 if (this%u%Xh .ne. this%v%Xh .or. &
489 this%u%Xh .ne. this%w%Xh) then
490 call neko_error('Different function spaces for velocity components')
491 end if
492
493 if (this%u%msh%nelv .ne. this%p%msh%nelv) then
494 call neko_error('Velocity and pressure defined on different meshes')
495 end if
496
497 if (.not. allocated(this%ksp_vel)) then
498 call neko_error('No Krylov solver for velocity defined')
499 end if
500
501 if (.not. allocated(this%ksp_prs)) then
502 call neko_error('No Krylov solver for pressure defined')
503 end if
504
505 end subroutine fluid_scheme_validate
506
511 subroutine fluid_scheme_bc_apply_vel(this, time, strong)
512 class(fluid_scheme_incompressible_t), intent(inout) :: this
513 type(time_state_t), intent(in) :: time
514 logical, intent(in) :: strong
515 integer :: i
516 class(bc_t), pointer :: b
517
518 call this%bcs_vel%apply_vector(&
519 this%u%x, this%v%x, this%w%x, this%dm_Xh%size(), time, strong)
520
521 call rotate_cyc(this%u, this%v, this%w, 1, this%c_Xh)
522 call this%gs_Xh%op(this%u, gs_op_min, glb_cmd_event)
524 call this%gs_Xh%op(this%v, gs_op_min, glb_cmd_event)
526 call this%gs_Xh%op(this%w, gs_op_min, glb_cmd_event)
528 call rotate_cyc(this%u, this%v, this%w, 0, this%c_Xh)
529
530 ! Double pass for Dirichlet bcs only.
531 b => null()
532 do i = 1, this%bcs_vel%size()
533 b => this%bcs_vel%get(i)
534 if (b%bc_type .eq. bc_dirichlet) then
535 call b%apply_vector_generic(this%u, this%v, this%w,time, strong)
536 end if
537 end do
538
539 call rotate_cyc(this%u, this%v, this%w, 1, this%c_Xh)
540 call this%gs_Xh%op(this%u, gs_op_max, glb_cmd_event)
542 call this%gs_Xh%op(this%v, gs_op_max, glb_cmd_event)
544 call this%gs_Xh%op(this%w, gs_op_max, glb_cmd_event)
546 call rotate_cyc(this%u, this%v, this%w, 0, this%c_Xh)
547
548 do i = 1, this%bcs_vel%size()
549 b => this%bcs_vel%get(i)
550 b%updated = .false.
551 end do
552 nullify(b)
553
554 end subroutine fluid_scheme_bc_apply_vel
555
558 subroutine fluid_scheme_bc_apply_prs(this, time)
559 class(fluid_scheme_incompressible_t), intent(inout) :: this
560 type(time_state_t), intent(in) :: time
561
562 integer :: i
563 class(bc_t), pointer :: b
564 b => null()
565
566 call this%bcs_prs%apply(this%p, time)
567 call this%gs_Xh%op(this%p, gs_op_min, glb_cmd_event)
569
570 call this%bcs_prs%apply(this%p, time)
571 call this%gs_Xh%op(this%p, gs_op_max, glb_cmd_event)
573
574 do i = 1, this%bcs_prs%size()
575 b => this%bcs_prs%get(i)
576 b%updated = .false.
577 end do
578 nullify(b)
579
580 end subroutine fluid_scheme_bc_apply_prs
581
584 subroutine fluid_scheme_solver_factory(ksp, n, solver, &
585 max_iter, abstol, monitor)
586 class(ksp_t), allocatable, target, intent(inout) :: ksp
587 integer, intent(in), value :: n
588 character(len=*), intent(in) :: solver
589 integer, intent(in) :: max_iter
590 real(kind=rp), intent(in) :: abstol
591 logical, intent(in) :: monitor
592
593 call krylov_solver_factory(ksp, n, solver, max_iter, abstol, &
594 monitor = monitor)
595
596 end subroutine fluid_scheme_solver_factory
597
599 subroutine fluid_scheme_precon_factory(this, pc, ksp, coef, dof, gs, bclst, &
600 pctype, pcparams)
601 class(fluid_scheme_incompressible_t), intent(inout) :: this
602 class(pc_t), allocatable, target, intent(inout) :: pc
603 class(ksp_t), target, intent(inout) :: ksp
604 type(coef_t), target, intent(in) :: coef
605 type(dofmap_t), target, intent(in) :: dof
606 type(gs_t), target, intent(inout) :: gs
607 type(bc_list_t), target, intent(inout) :: bclst
608 character(len=*) :: pctype
609 type(json_file), intent(inout) :: pcparams
610
611 call precon_allocator(pc, pctype)
612
613 select type (pcp => pc)
614 type is (jacobi_t)
615 call pcp%init(coef, dof, gs)
616 type is (sx_jacobi_t)
617 call pcp%init(coef, dof, gs)
618 type is (device_jacobi_t)
619 call pcp%init(coef, dof, gs)
620 type is (hsmg_t)
621 call pcp%init(coef, bclst, pcparams)
622 type is (phmg_t)
623 call pcp%init(coef, bclst, pcparams)
624 end select
625
626 call ksp%set_pc(pc)
627
628 end subroutine fluid_scheme_precon_factory
629
631 function fluid_compute_cfl(this, dt) result(c)
632 class(fluid_scheme_incompressible_t), intent(in) :: this
633 real(kind=dp), intent(in) :: dt
634 real(kind=dp) :: c
635
636 c = cfl(dt, this%u, this%v, this%w, &
637 this%Xh, this%c_Xh, this%msh%nelv, this%msh%gdim)
638
639 end function fluid_compute_cfl
640
641
646 subroutine fluid_scheme_update_material_properties(this, time)
647 class(fluid_scheme_incompressible_t), intent(inout) :: this
648 type(time_state_t), intent(in) :: time
649 type(field_t), pointer :: nut
650
651 call this%user_material_properties(this%name, this%material_properties, &
652 time)
653
654 if (len(trim(this%nut_field_name)) > 0) then
655 nut => neko_registry%get_field(this%nut_field_name)
656 ! Copy material property
657 call field_copy(this%mu_tot, this%mu)
658 ! Add turbulent contribution
659 call field_addcol3(this%mu_tot, nut, this%rho)
660 end if
661
662 ! Since mu, rho is a field_t, and we use the %x(1,1,1,1)
663 ! host array data to pass constant density and viscosity
664 ! to some routines, we need to make sure that the host
665 ! values are also filled
666 if (neko_bcknd_device .eq. 1) then
667 call device_memcpy(this%rho%x, this%rho%x_d, this%rho%size(), &
668 device_to_host, sync = .false.)
669 end if
670 end subroutine fluid_scheme_update_material_properties
671
675 subroutine fluid_scheme_set_material_properties(this, params, user)
676 class(fluid_scheme_incompressible_t), target, intent(inout) :: this
677 type(json_file), intent(inout) :: params
678 type(user_t), target, intent(in) :: user
679 character(len=LOG_SIZE) :: log_buf
680 ! A local pointer that is needed to make Intel happy
681 procedure(user_material_properties_intf), pointer :: dummy_mp_ptr
682 logical :: nondimensional
683 real(kind=rp) :: dummy_lambda, dummy_cp
684 real(kind=rp) :: const_mu, const_rho
685 type(time_state_t) :: dummy_time_state
686
687
688 dummy_mp_ptr => dummy_user_material_properties
689
690 call neko_registry%add_field(this%dm_Xh, this%name // "_mu")
691 call neko_registry%add_field(this%dm_Xh, this%name // "_mu_tot")
692 call neko_registry%add_field(this%dm_Xh, this%name // "_rho")
693 this%mu => neko_registry%get_field(this%name // "_mu")
694 this%mu_tot => neko_registry%get_field(this%name // "_mu_tot")
695 this%rho => neko_registry%get_field(this%name // "_rho")
696
697 call this%material_properties%init(2)
698 call this%material_properties%assign(1, this%rho)
699 call this%material_properties%assign(2, this%mu)
700
701 if (.not. associated(user%material_properties, dummy_mp_ptr)) then
702
703 write(log_buf, '(A)') 'Material properties must be set in the user' // &
704 ' file!'
705 call neko_log%message(log_buf)
706 this%user_material_properties => user%material_properties
707
708 call user%material_properties(this%name, this%material_properties, &
709 dummy_time_state)
710
711 else
712 this%user_material_properties => dummy_user_material_properties
713 ! Incorrect user input
714 if (params%valid_path('case.fluid.Re') .and. &
715 (params%valid_path('case.fluid.mu') .or. &
716 params%valid_path('case.fluid.rho'))) then
717 call neko_error("To set the material properties for the fluid, " // &
718 "either provide Re OR mu and rho in the case file.")
719
720 else if (params%valid_path('case.fluid.Re')) then
721 ! Non-dimensional case
722 write(log_buf, '(A)') 'Non-dimensional fluid material properties &
723 & input.'
724 call neko_log%message(log_buf, lvl = neko_log_verbose)
725 write(log_buf, '(A)') 'Density will be set to 1, dynamic viscosity to&
726 & 1/Re.'
727 call neko_log%message(log_buf, lvl = neko_log_verbose)
728
729 ! Read Re into mu for further manipulation.
730 call json_get_or_lookup(params, 'case.fluid.Re', const_mu)
731 write(log_buf, '(A)') 'Read non-dimensional material properties'
732 call neko_log%message(log_buf)
733 write(log_buf, '(A,ES13.6)') 'Re :', const_mu
734 call neko_log%message(log_buf)
735
736 ! Set rho to 1 since the setup is non-dimensional.
737 const_rho = 1.0_rp
738 ! Invert the Re to get viscosity.
739 const_mu = 1.0_rp/const_mu
740 else
741 ! Dimensional case
742 call json_get_or_lookup(params, 'case.fluid.mu', const_mu)
743 call json_get_or_lookup(params, 'case.fluid.rho', const_rho)
744 end if
745 end if
746
747 ! We need to fill the fields based on the parsed const values
748 ! if the user routine is not used.
749 if (associated(user%material_properties, dummy_mp_ptr)) then
750 ! Fill mu and rho field with the physical value
751 call field_cfill(this%mu, const_mu)
752 call field_cfill(this%mu_tot, const_mu)
753 call field_cfill(this%rho, const_rho)
754
755
756 write(log_buf, '(A,ES13.6)') 'rho :', const_rho
757 call neko_log%message(log_buf)
758 write(log_buf, '(A,ES13.6)') 'mu :', const_mu
759 call neko_log%message(log_buf)
760 end if
761
762 ! Copy over material property to the total one
763 call field_copy(this%mu_tot, this%mu)
764
765 ! Since mu, rho is a field_t, and we use the %x(1,1,1,1)
766 ! host array data to pass constant density and viscosity
767 ! to some routines, we need to make sure that the host
768 ! values are also filled
769 if (neko_bcknd_device .eq. 1) then
770 call device_memcpy(this%rho%x, this%rho%x_d, this%rho%size(), &
771 device_to_host, sync = .false.)
772 call device_memcpy(this%mu%x, this%mu%x_d, this%mu%size(), &
773 device_to_host, sync = .false.)
774 call device_memcpy(this%mu_tot%x, this%mu_tot%x_d, this%mu%size(), &
775 device_to_host, sync = .false.)
776 end if
777 end subroutine fluid_scheme_set_material_properties
778
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.
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
Jacobi preconditioner accelerator backend.
Device abstraction, common interface for various accelerators.
Definition device.F90:34
subroutine, public device_event_sync(event)
Synchronize an event.
Definition device.F90:1667
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_precon_factory(this, pc, ksp, coef, dof, gs, bclst, pctype, pcparams)
Initialize a Krylov preconditioner.
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_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_solver_factory(ksp, n, solver, max_iter, abstol, monitor)
Initialize a linear solver.
subroutine fluid_scheme_bc_apply_prs(this, time)
Apply all boundary conditions defined for pressure.
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.
Krylov preconditioner.
Definition pc_hsmg.f90:61
Jacobi preconditioner.
Definition pc_jacobi.f90:34
Utilities for retrieving parameters from the case files.
Implements the base abstract type for Krylov solvers plus helper types.
Definition krylov.f90:34
integer, parameter, public ksp_max_iter
Maximum number of iters.
Definition krylov.f90:52
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:91
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: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
Hybrid ph-multigrid preconditioner.
Definition phmg.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.
Jacobi preconditioner SX-Aurora backend.
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:135
Defines a jacobi preconditioner.
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.
Defines a jacobi preconditioner.
Definition pc_jacobi.f90:45
Base abstract type for a canonical Krylov method, solving .
Definition krylov.f90:74
Defines a canonical Krylov preconditioner.
Definition precon.f90:40
Spectral vanishing viscosity configuration and coefficients.
Defines a jacobi preconditioner for SX-Aurora.
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...