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 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
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_or_lookup_or_default(params, &
301 'case.fluid.velocity_solver.max_iterations', &
302 integer_val, ksp_max_iter)
303 call json_get(params, 'case.fluid.velocity_solver.type', string_val1)
304 call json_get(params, 'case.fluid.velocity_solver.preconditioner.type', &
305 string_val2)
306 call json_get(params, &
307 'case.fluid.velocity_solver.preconditioner', json_subdict)
308 call json_get_or_lookup(params, &
309 'case.fluid.velocity_solver.absolute_tolerance', &
310 real_val)
311 call json_get_or_default(params, &
312 'case.fluid.velocity_solver.monitor', &
313 logical_val, .false.)
314
315 call neko_log%message('Type : ('// trim(string_val1) // &
316 ', ' // trim(string_val2) // ')')
317
318 write(log_buf, '(A,ES13.6)') 'Abs tol :', real_val
319 call neko_log%message(log_buf)
320 call this%solver_factory(this%ksp_vel, this%dm_Xh%size(), &
321 string_val1, integer_val, real_val, logical_val)
322 call this%precon_factory_(this%pc_vel, this%ksp_vel, &
323 this%c_Xh, this%bcs_vel, &
324 string_val2, json_subdict)
325 call neko_log%end_section()
326 end if
327
328 ! Strict convergence for the velocity solver
329 call json_get_or_default(params, 'case.fluid.strict_convergence', &
330 this%strict_convergence, .false.)
331 ! Allow stabilization period where we do not warn about non-convergence
332 call json_get_or_default(params, 'case.fluid.allow_stabilization', &
333 this%allow_stabilization, .false.)
334
335
336 !! Initialize time-lag fields
337 call this%ulag%init(this%u, 2)
338 call this%vlag%init(this%v, 2)
339 call this%wlag%init(this%w, 2)
340
341 call neko_registry%add_field(this%dm_Xh, 'u_e')
342 call neko_registry%add_field(this%dm_Xh, 'v_e')
343 call neko_registry%add_field(this%dm_Xh, 'w_e')
344 this%u_e => neko_registry%get_field('u_e')
345 this%v_e => neko_registry%get_field('v_e')
346 this%w_e => neko_registry%get_field('w_e')
347
348 ! Initialize the source term
349 call neko_log%section('Fluid Source term')
350 call this%source_term%init(this%f_x, this%f_y, this%f_z, this%c_Xh, user, &
351 this%name)
352 call this%source_term%add(params, 'case.fluid.source_terms')
353 call neko_log%end_section()
354
355 if (params%valid_path('case.fluid.svv')) then
356 call json_get(params, 'case.fluid', json_subdict)
357 call json_get_or_default(json_subdict, 'svv.enabled', &
358 this%svv_enabled, .false.)
359 if (this%svv_enabled) then
360 if (.not. kspv_init) then
361 call neko_error("SVV is only supported by fluid " // &
362 "schemes with an implicit velocity solve")
363 end if
364 if (full_stress_formulation) then
365 if (trim(string_val1) .ne. 'coupled_cg' .and. &
366 trim(string_val1) .ne. 'fused_coupled_cg') then
367 call neko_error("Full-stress SVV requires a " // &
368 "coupled velocity solver (`coupled_cg` or " // &
369 "`fused_coupled_cg`)")
370 end if
371 end if
372 allocate(this%svv)
373 call this%svv%init(json_subdict, this%c_Xh, this%rho)
374 end if
375 end if
376
377 end subroutine fluid_scheme_init_base
378
379 subroutine fluid_scheme_free(this)
380 class(fluid_scheme_incompressible_t), intent(inout) :: this
381 class(bc_t), pointer :: bc
382 integer :: i
383
384
385 if (allocated(this%svv)) then
386 call this%svv%free()
387 deallocate(this%svv)
388 end if
389 this%svv_enabled = .false.
390
391 call this%Xh%free()
392
393 if (allocated(this%ksp_vel)) then
394 call this%ksp_vel%free()
395 deallocate(this%ksp_vel)
396 end if
397
398 if (allocated(this%ksp_prs)) then
399 call this%ksp_prs%free()
400 deallocate(this%ksp_prs)
401 end if
402
403 if (allocated(this%pc_vel)) then
404 call this%pc_vel%free()
405 deallocate(this%pc_vel)
406 end if
407
408 if (allocated(this%pc_prs)) then
409 call this%pc_prs%free()
410 deallocate(this%pc_prs)
411 end if
412
413 do i = 1, this%bcs_vel%size()
414 bc => this%bcs_vel%get(i)
415 if (associated(bc)) then
416 call bc%free()
417 deallocate(bc)
418 end if
419 end do
420 call this%bcs_vel%free()
421
422 do i = 1, this%bcs_prs%size()
423 bc => this%bcs_prs%get(i)
424 if (associated(bc)) then
425 call bc%free()
426 deallocate(bc)
427 end if
428 end do
429 call this%bcs_prs%free()
430
431 call this%source_term%free()
432
433 call this%gs_Xh%free()
434
435 call this%c_Xh%free()
436
437 nullify(this%u)
438 nullify(this%v)
439 nullify(this%w)
440 nullify(this%p)
441
442 nullify(this%u_e)
443 nullify(this%v_e)
444 nullify(this%w_e)
445
446 call this%ulag%free()
447 call this%vlag%free()
448 call this%wlag%free()
449
450
451 if (associated(this%f_x)) then
452 call this%f_x%free()
453 deallocate(this%f_x)
454 end if
455
456 if (associated(this%f_y)) then
457 call this%f_y%free()
458 deallocate(this%f_y)
459 end if
460
461 if (associated(this%f_z)) then
462 call this%f_z%free()
463 deallocate(this%f_z)
464 end if
465
466 nullify(this%f_x)
467 nullify(this%f_y)
468 nullify(this%f_z)
469 nullify(this%rho)
470 nullify(this%mu)
471 nullify(this%mu_tot)
472
473 call this%dm_Xh%free()
474 call this%Xh%free()
475 nullify(this%msh)
476
477 end subroutine fluid_scheme_free
478
481 subroutine fluid_scheme_validate(this)
482 class(fluid_scheme_incompressible_t), target, intent(inout) :: this
483 ! Variables for retrieving json parameters
484 logical :: logical_val
485
486 if ( (.not. associated(this%u)) .or. &
487 (.not. associated(this%v)) .or. &
488 (.not. associated(this%w)) .or. &
489 (.not. associated(this%p))) then
490 call neko_error('Fields are not registered')
491 end if
492
493 if ( (.not. allocated(this%u%x)) .or. &
494 (.not. allocated(this%v%x)) .or. &
495 (.not. allocated(this%w%x)) .or. &
496 (.not. allocated(this%p%x))) then
497 call neko_error('Fields are not allocated')
498 end if
499
500 if (this%u%Xh .ne. this%v%Xh .or. &
501 this%u%Xh .ne. this%w%Xh) then
502 call neko_error('Different function spaces for velocity components')
503 end if
504
505 if (this%u%msh%nelv .ne. this%p%msh%nelv) then
506 call neko_error('Velocity and pressure defined on different meshes')
507 end if
508
509 if (.not. allocated(this%ksp_vel)) then
510 call neko_error('No Krylov solver for velocity defined')
511 end if
512
513 if (.not. allocated(this%ksp_prs)) then
514 call neko_error('No Krylov solver for pressure defined')
515 end if
516
517 end subroutine fluid_scheme_validate
518
523 subroutine fluid_scheme_bc_apply_vel(this, time, strong)
524 class(fluid_scheme_incompressible_t), intent(inout) :: this
525 type(time_state_t), intent(in) :: time
526 logical, intent(in) :: strong
527 integer :: i
528 class(bc_t), pointer :: b
529
530 call this%bcs_vel%apply_vector(&
531 this%u%x, this%v%x, this%w%x, this%dm_Xh%size(), time, strong)
532
533 call rotate_cyc(this%u, this%v, this%w, 1, this%c_Xh)
534 call this%gs_Xh%op(this%u, gs_op_min, glb_cmd_event)
536 call this%gs_Xh%op(this%v, gs_op_min, glb_cmd_event)
538 call this%gs_Xh%op(this%w, gs_op_min, glb_cmd_event)
540 call rotate_cyc(this%u, this%v, this%w, 0, this%c_Xh)
541
542 ! Double pass for Dirichlet bcs only.
543 b => null()
544 do i = 1, this%bcs_vel%size()
545 b => this%bcs_vel%get(i)
546 if (b%bc_type .eq. bc_dirichlet) then
547 call b%apply_vector_generic(this%u, this%v, this%w,time, strong)
548 end if
549 end do
550
551 call rotate_cyc(this%u, this%v, this%w, 1, this%c_Xh)
552 call this%gs_Xh%op(this%u, gs_op_max, glb_cmd_event)
554 call this%gs_Xh%op(this%v, gs_op_max, glb_cmd_event)
556 call this%gs_Xh%op(this%w, gs_op_max, glb_cmd_event)
558 call rotate_cyc(this%u, this%v, this%w, 0, this%c_Xh)
559
560 do i = 1, this%bcs_vel%size()
561 b => this%bcs_vel%get(i)
562 b%updated = .false.
563 end do
564 nullify(b)
565
566 end subroutine fluid_scheme_bc_apply_vel
567
570 subroutine fluid_scheme_bc_apply_prs(this, time)
571 class(fluid_scheme_incompressible_t), intent(inout) :: this
572 type(time_state_t), intent(in) :: time
573
574 integer :: i
575 class(bc_t), pointer :: b
576 b => null()
577
578 call this%bcs_prs%apply(this%p, time)
579 call this%gs_Xh%op(this%p, gs_op_min, glb_cmd_event)
581
582 call this%bcs_prs%apply(this%p, time)
583 call this%gs_Xh%op(this%p, gs_op_max, glb_cmd_event)
585
586 do i = 1, this%bcs_prs%size()
587 b => this%bcs_prs%get(i)
588 b%updated = .false.
589 end do
590 nullify(b)
591
592 end subroutine fluid_scheme_bc_apply_prs
593
596 subroutine fluid_scheme_solver_factory(ksp, n, solver, &
597 max_iter, abstol, monitor)
598 class(ksp_t), allocatable, target, intent(inout) :: ksp
599 integer, intent(in), value :: n
600 character(len=*), intent(in) :: solver
601 integer, intent(in) :: max_iter
602 real(kind=rp), intent(in) :: abstol
603 logical, intent(in) :: monitor
604
605 call krylov_solver_factory(ksp, n, solver, max_iter, abstol, &
606 monitor = monitor)
607
608 end subroutine fluid_scheme_solver_factory
609
611 subroutine fluid_scheme_precon_factory(this, pc, ksp, coef, bclst, &
612 pctype, json)
613 class(fluid_scheme_incompressible_t), intent(inout) :: this
614 class(pc_t), allocatable, target, intent(inout) :: pc
615 class(ksp_t), target, intent(inout) :: ksp
616 type(coef_t), target, intent(in) :: coef
617 type(bc_list_t), target, intent(inout) :: bclst
618 character(len=*) :: pctype
619 type(json_file), intent(inout) :: json
620
621 call precon_factory(pc, pctype, coef, bclst, json)
622
623 call ksp%set_pc(pc)
624
625 end subroutine fluid_scheme_precon_factory
626
628 function fluid_compute_cfl(this, dt) result(c)
629 class(fluid_scheme_incompressible_t), intent(in) :: this
630 real(kind=dp), intent(in) :: dt
631 real(kind=dp) :: c
632
633 c = cfl(dt, this%u, this%v, this%w, &
634 this%Xh, this%c_Xh, this%msh%nelv, this%msh%gdim)
635
636 end function fluid_compute_cfl
637
638
643 subroutine fluid_scheme_update_material_properties(this, time)
644 class(fluid_scheme_incompressible_t), intent(inout) :: this
645 type(time_state_t), intent(in) :: time
646 type(field_t), pointer :: nut
647
648 call this%user_material_properties(this%name, this%material_properties, &
649 time)
650
651 if (len(trim(this%nut_field_name)) > 0) then
652 nut => neko_registry%get_field(this%nut_field_name)
653 ! Copy material property
654 call field_copy(this%mu_tot, this%mu)
655 ! Add turbulent contribution
656 call field_addcol3(this%mu_tot, nut, this%rho)
657 end if
658
659 ! Since mu, rho is a field_t, and we use the %x(1,1,1,1)
660 ! host array data to pass constant density and viscosity
661 ! to some routines, we need to make sure that the host
662 ! values are also filled
663 if (neko_bcknd_device .eq. 1) then
664 call device_memcpy(this%rho%x, this%rho%x_d, this%rho%size(), &
665 device_to_host, sync = .false.)
666 end if
667 end subroutine fluid_scheme_update_material_properties
668
672 subroutine fluid_scheme_set_material_properties(this, params, user)
673 class(fluid_scheme_incompressible_t), target, intent(inout) :: this
674 type(json_file), intent(inout) :: params
675 type(user_t), target, intent(in) :: user
676 character(len=LOG_SIZE) :: log_buf
677 ! A local pointer that is needed to make Intel happy
678 procedure(user_material_properties_intf), pointer :: dummy_mp_ptr
679 logical :: nondimensional
680 real(kind=rp) :: dummy_lambda, dummy_cp
681 real(kind=rp) :: const_mu, const_rho
682 type(time_state_t) :: dummy_time_state
683
684
685 dummy_mp_ptr => dummy_user_material_properties
686
687 call neko_registry%add_field(this%dm_Xh, this%name // "_mu")
688 call neko_registry%add_field(this%dm_Xh, this%name // "_mu_tot")
689 call neko_registry%add_field(this%dm_Xh, this%name // "_rho")
690 this%mu => neko_registry%get_field(this%name // "_mu")
691 this%mu_tot => neko_registry%get_field(this%name // "_mu_tot")
692 this%rho => neko_registry%get_field(this%name // "_rho")
693
694 call this%material_properties%init(2)
695 call this%material_properties%assign(1, this%rho)
696 call this%material_properties%assign(2, this%mu)
697
698 if (.not. associated(user%material_properties, dummy_mp_ptr)) then
699
700 write(log_buf, '(A)') 'Material properties must be set in the user' // &
701 ' file!'
702 call neko_log%message(log_buf)
703 this%user_material_properties => user%material_properties
704
705 call user%material_properties(this%name, this%material_properties, &
706 dummy_time_state)
707
708 else
709 this%user_material_properties => dummy_user_material_properties
710 ! Incorrect user input
711 if (params%valid_path('case.fluid.Re') .and. &
712 (params%valid_path('case.fluid.mu') .or. &
713 params%valid_path('case.fluid.rho'))) then
714 call neko_error("To set the material properties for the fluid, " // &
715 "either provide Re OR mu and rho in the case file.")
716
717 else if (params%valid_path('case.fluid.Re')) then
718 ! Non-dimensional case
719 write(log_buf, '(A)') 'Non-dimensional fluid material properties &
720 & input.'
721 call neko_log%message(log_buf, lvl = neko_log_verbose)
722 write(log_buf, '(A)') 'Density will be set to 1, dynamic viscosity to&
723 & 1/Re.'
724 call neko_log%message(log_buf, lvl = neko_log_verbose)
725
726 ! Read Re into mu for further manipulation.
727 call json_get_or_lookup(params, 'case.fluid.Re', const_mu)
728 write(log_buf, '(A)') 'Read non-dimensional material properties'
729 call neko_log%message(log_buf)
730 write(log_buf, '(A,ES13.6)') 'Re :', const_mu
731 call neko_log%message(log_buf)
732
733 ! Set rho to 1 since the setup is non-dimensional.
734 const_rho = 1.0_rp
735 ! Invert the Re to get viscosity.
736 const_mu = 1.0_rp/const_mu
737 else
738 ! Dimensional case
739 call json_get_or_lookup(params, 'case.fluid.mu', const_mu)
740 call json_get_or_lookup(params, 'case.fluid.rho', const_rho)
741 end if
742 end if
743
744 ! We need to fill the fields based on the parsed const values
745 ! if the user routine is not used.
746 if (associated(user%material_properties, dummy_mp_ptr)) then
747 ! Fill mu and rho field with the physical value
748 call field_cfill(this%mu, const_mu)
749 call field_cfill(this%mu_tot, const_mu)
750 call field_cfill(this%rho, const_rho)
751
752
753 write(log_buf, '(A,ES13.6)') 'rho :', const_rho
754 call neko_log%message(log_buf)
755 write(log_buf, '(A,ES13.6)') 'mu :', const_mu
756 call neko_log%message(log_buf)
757 end if
758
759 ! Copy over material property to the total one
760 call field_copy(this%mu_tot, this%mu)
761
762 ! Since mu, rho is a field_t, and we use the %x(1,1,1,1)
763 ! host array data to pass constant density and viscosity
764 ! to some routines, we need to make sure that the host
765 ! values are also filled
766 if (neko_bcknd_device .eq. 1) then
767 call device_memcpy(this%rho%x, this%rho%x_d, this%rho%size(), &
768 device_to_host, sync = .false.)
769 call device_memcpy(this%mu%x, this%mu%x_d, this%mu%size(), &
770 device_to_host, sync = .false.)
771 call device_memcpy(this%mu_tot%x, this%mu_tot%x_d, this%mu%size(), &
772 device_to_host, sync = .false.)
773 end if
774 end subroutine fluid_scheme_set_material_properties
775
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
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_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_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
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: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: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
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:74
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...