Neko  0.8.1
A portable framework for high-order spectral element flow simulations
fluid_scheme.f90
Go to the documentation of this file.
1 ! Copyright (c) 2020-2024, 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 !
35  use gather_scatter
36  use mean_sqr_flow, only : mean_sqr_flow_t
37  use neko_config
38  use checkpoint, only : chkp_t
39  use mean_flow, only : mean_flow_t
40  use num_types
41  use comm
44  use field_list, only : field_list_t
45  use field, only : field_t
46  use space
47  use dofmap, only : dofmap_t
48  use krylov, only : ksp_t
49  use coefs
50  use wall, only : no_slip_wall_t
51  use inflow, only : inflow_t
53  use blasius, only : blasius_t
54  use dirichlet, only : dirichlet_t
55  use dong_outflow, only : dong_outflow_t
56  use symmetry, only : symmetry_t
57  use non_normal, only : non_normal_t
60  use krylov_fctry
61  use precon_fctry
62  use fluid_stats, only : fluid_stats_t
63  use bc
64  use mesh
65  use math
67  use mathops
68  use operators, only : cfl
69  use logger
70  use field_registry
72  use json_module, only : json_file, json_core, json_value
74  use user_intf, only : user_t
75  use utils, only : neko_warning, neko_error
77  use field_series
79  implicit none
80 
82  type, abstract :: fluid_scheme_t
83  type(field_t), pointer :: u => null()
84  type(field_t), pointer :: v => null()
85  type(field_t), pointer :: w => null()
86  type(field_t), pointer :: p => null()
87  type(field_series_t) :: ulag, vlag, wlag
88  type(space_t) :: xh
89  type(dofmap_t) :: dm_xh
90  type(gs_t) :: gs_xh
91  type(coef_t) :: c_xh
95  type(field_t), pointer :: f_x => null()
97  type(field_t), pointer :: f_y => null()
99  type(field_t), pointer :: f_z => null()
100  class(ksp_t), allocatable :: ksp_vel
101  class(ksp_t), allocatable :: ksp_prs
102  class(pc_t), allocatable :: pc_vel
103  class(pc_t), allocatable :: pc_prs
104  integer :: vel_projection_dim
105  integer :: pr_projection_dim
106  integer :: vel_projection_activ_step
107  integer :: pr_projection_activ_step
108  type(no_slip_wall_t) :: bc_wall
109  class(inflow_t), allocatable :: bc_inflow
110 
111  ! Attributes for field dirichlet BCs
112  type(field_dirichlet_vector_t) :: bc_field_vel
113  type(field_dirichlet_t) :: bc_field_prs
114  procedure(field_dirichlet_update), nopass, pointer :: dirichlet_update_ &
115  => null()
116  type(bc_list_t) :: field_dirichlet_bcs
117  type(field_list_t) :: field_dirichlet_fields
118 
119  type(dirichlet_t) :: bc_prs
120  type(dong_outflow_t) :: bc_dong
121  type(symmetry_t) :: bc_sym
122  type(bc_list_t) :: bclst_vel
123  type(bc_list_t) :: bclst_prs
124  type(field_t) :: bdry
125  type(json_file), pointer :: params
126  type(mesh_t), pointer :: msh => null()
127  type(chkp_t) :: chkp
128  type(mean_flow_t) :: mean
130  type(mean_sqr_flow_t) :: mean_sqr
131  logical :: forced_flow_rate = .false.
132  logical :: freeze = .false.
134  real(kind=rp), pointer :: mu => null()
136  real(kind=rp), pointer :: rho => null()
137  type(scratch_registry_t) :: scratch
139  character(len=NEKO_MSH_MAX_ZLBL_LEN), allocatable :: bc_labels(:)
140  contains
141  procedure, pass(this) :: fluid_scheme_init_all
142  procedure, pass(this) :: fluid_scheme_init_uvw
143  procedure, pass(this) :: scheme_free => fluid_scheme_free
144  procedure, pass(this) :: validate => fluid_scheme_validate
145  procedure, pass(this) :: bc_apply_vel => fluid_scheme_bc_apply_vel
146  procedure, pass(this) :: bc_apply_prs => fluid_scheme_bc_apply_prs
147  procedure, pass(this) :: set_usr_inflow => fluid_scheme_set_usr_inflow
148  procedure, pass(this) :: compute_cfl => fluid_compute_cfl
149  procedure(fluid_scheme_init_intrf), pass(this), deferred :: init
150  procedure(fluid_scheme_free_intrf), pass(this), deferred :: free
151  procedure(fluid_scheme_step_intrf), pass(this), deferred :: step
152  procedure(fluid_scheme_restart_intrf), pass(this), deferred :: restart
153  generic :: scheme_init => fluid_scheme_init_all, fluid_scheme_init_uvw
154  end type fluid_scheme_t
155 
157  abstract interface
158  subroutine fluid_scheme_init_intrf(this, msh, lx, params, user, &
159  material_properties)
160  import fluid_scheme_t
161  import json_file
162  import mesh_t
163  import user_t
164  import material_properties_t
165  class(fluid_scheme_t), target, intent(inout) :: this
166  type(mesh_t), target, intent(inout) :: msh
167  integer, intent(inout) :: lx
168  type(json_file), target, intent(inout) :: params
169  type(user_t), intent(in) :: user
170  type(material_properties_t), target, intent(inout) :: material_properties
171  end subroutine fluid_scheme_init_intrf
172  end interface
173 
175  abstract interface
176  subroutine fluid_scheme_free_intrf(this)
177  import fluid_scheme_t
178  class(fluid_scheme_t), intent(inout) :: this
179  end subroutine fluid_scheme_free_intrf
180  end interface
181 
183  abstract interface
184  subroutine fluid_scheme_step_intrf(this, t, tstep, dt, ext_bdf, dt_controller)
185  import fluid_scheme_t
188  import rp
189  class(fluid_scheme_t), target, intent(inout) :: this
190  real(kind=rp), intent(inout) :: t
191  integer, intent(inout) :: tstep
192  real(kind=rp), intent(in) :: dt
193  type(time_scheme_controller_t), intent(inout) :: ext_bdf
194  type(time_step_controller_t), intent(in) :: dt_controller
195  end subroutine fluid_scheme_step_intrf
196  end interface
197 
199  abstract interface
200  subroutine fluid_scheme_restart_intrf(this, dtlag, tlag)
201  import fluid_scheme_t
202  import rp
203  class(fluid_scheme_t), target, intent(inout) :: this
204  real(kind=rp) :: dtlag(10), tlag(10)
205 
206  end subroutine fluid_scheme_restart_intrf
207  end interface
208 
209 contains
210 
212  subroutine fluid_scheme_init_common(this, msh, lx, params, scheme, user, &
213  material_properties)
214  implicit none
215  class(fluid_scheme_t), target, intent(inout) :: this
216  type(mesh_t), target, intent(inout) :: msh
217  integer, intent(inout) :: lx
218  character(len=*), intent(in) :: scheme
219  type(json_file), target, intent(inout) :: params
220  type(user_t), target, intent(in) :: user
221  type(material_properties_t), target, intent(inout) :: material_properties
222  type(dirichlet_t) :: bdry_mask
223  character(len=LOG_SIZE) :: log_buf
224  real(kind=rp), allocatable :: real_vec(:)
225  real(kind=rp) :: real_val
226  logical :: logical_val
227  integer :: integer_val, ierr
228  character(len=:), allocatable :: string_val1, string_val2
229  ! A local pointer that is needed to make Intel happy
230 
231 
232  call neko_log%section('Fluid')
233  write(log_buf, '(A, A)') 'Type : ', trim(scheme)
234  call neko_log%message(log_buf)
235  if (lx .lt. 10) then
236  write(log_buf, '(A, I1)') 'lx : ', lx
237  else if (lx .ge. 10) then
238  write(log_buf, '(A, I2)') 'lx : ', lx
239  else
240  write(log_buf, '(A, I3)') 'lx : ', lx
241  end if
242 
243  !
244  ! Material properties
245  !
246 
247  this%rho => material_properties%rho
248  this%mu => material_properties%mu
249 
250  call neko_log%message(log_buf)
251  write(log_buf, '(A,ES13.6)') 'rho :', this%rho
252  call neko_log%message(log_buf)
253  write(log_buf, '(A,ES13.6)') 'mu :', this%mu
254 
255  call json_get(params, 'case.fluid.velocity_solver.type', string_val1)
256  call json_get(params, 'case.fluid.velocity_solver.preconditioner', &
257  string_val2)
258  call json_get(params, 'case.fluid.velocity_solver.absolute_tolerance', &
259  real_val)
260  call neko_log%message(log_buf)
261  call neko_log%message('Ksp vel. : ('// trim(string_val1) // &
262  ', ' // trim(string_val2) // ')')
263 
264  write(log_buf, '(A,ES13.6)') ' `-abs tol :', real_val
265 
266  call json_get(params, 'case.fluid.pressure_solver.type', string_val1)
267  call json_get(params, 'case.fluid.pressure_solver.preconditioner', &
268  string_val2)
269  call json_get(params, 'case.fluid.pressure_solver.absolute_tolerance', &
270  real_val)
271  call neko_log%message(log_buf)
272  call neko_log%message('Ksp prs. : ('// trim(string_val1) // &
273  ', ' // trim(string_val2) // ')')
274  write(log_buf, '(A,ES13.6)') ' `-abs tol :', real_val
275  call neko_log%message(log_buf)
276 
277  call json_get(params, 'case.numerics.dealias', logical_val)
278  write(log_buf, '(A, L1)') 'Dealias : ', logical_val
279  call neko_log%message(log_buf)
280 
281  call json_get_or_default(params, 'case.output_boundary', logical_val, &
282  .false.)
283  write(log_buf, '(A, L1)') 'Save bdry : ', logical_val
284  call neko_log%message(log_buf)
285 
286 
287  call json_get_or_default(params, &
288  'case.fluid.velocity_solver.projection_space_size',&
289  this%vel_projection_dim, 20)
290  call json_get_or_default(params, &
291  'case.fluid.pressure_solver.projection_space_size',&
292  this%pr_projection_dim, 20)
293  call json_get_or_default(params, &
294  'case.fluid.velocity_solver.projection_hold_steps',&
295  this%vel_projection_activ_step, 5)
296  call json_get_or_default(params, &
297  'case.fluid.pressure_solver.projection_hold_steps',&
298  this%pr_projection_activ_step, 5)
299 
300 
301  call json_get_or_default(params, 'case.fluid.freeze', this%freeze, .false.)
302 
303  if (params%valid_path("case.fluid.flow_rate_force")) then
304  this%forced_flow_rate = .true.
305  end if
306 
307  if (msh%gdim .eq. 2) then
308  call this%Xh%init(gll, lx, lx)
309  else
310  call this%Xh%init(gll, lx, lx, lx)
311  end if
312 
313  this%dm_Xh = dofmap_t(msh, this%Xh)
314 
315  this%params => params
316 
317  this%msh => msh
318 
319  call this%gs_Xh%init(this%dm_Xh)
320 
321  call this%c_Xh%init(this%gs_Xh)
322 
323 
324  this%scratch = scratch_registry_t(this%dm_Xh, 10, 2)
325 
326  allocate(this%bc_labels(neko_msh_max_zlbls))
327  this%bc_labels = "not"
328 
329  !
330  ! Setup velocity boundary conditions
331  !
332  if (params%valid_path('case.fluid.boundary_types')) then
333  call json_get(params, &
334  'case.fluid.boundary_types', &
335  this%bc_labels)
336  end if
337 
338  call bc_list_init(this%bclst_vel)
339 
340  call this%bc_sym%init(this%c_Xh)
341  call this%bc_sym%mark_zone(msh%sympln)
342  call this%bc_sym%mark_zones_from_list(msh%labeled_zones,&
343  'sym', this%bc_labels)
344  call this%bc_sym%finalize()
345  call this%bc_sym%init_msk()
346  call bc_list_add(this%bclst_vel, this%bc_sym)
347 
348  !
349  ! Inflow
350  !
351  if (params%valid_path('case.fluid.inflow_condition')) then
352  call json_get(params, 'case.fluid.inflow_condition.type', string_val1)
353  if (trim(string_val1) .eq. "uniform") then
354  allocate(inflow_t::this%bc_inflow)
355  else if (trim(string_val1) .eq. "blasius") then
356  allocate(blasius_t::this%bc_inflow)
357  else if (trim(string_val1) .eq. "user") then
358  allocate(usr_inflow_t::this%bc_inflow)
359  else
360  call neko_error('Invalid inflow condition '//string_val1)
361  end if
362 
363  call this%bc_inflow%init(this%c_Xh)
364  call this%bc_inflow%mark_zone(msh%inlet)
365  call this%bc_inflow%mark_zones_from_list(msh%labeled_zones,&
366  'v', this%bc_labels)
367  call this%bc_inflow%finalize()
368  call bc_list_add(this%bclst_vel, this%bc_inflow)
369 
370  if (trim(string_val1) .eq. "uniform") then
371  call json_get(params, 'case.fluid.inflow_condition.value', real_vec)
372  call this%bc_inflow%set_inflow(real_vec)
373  else if (trim(string_val1) .eq. "blasius") then
374  select type(bc_if => this%bc_inflow)
375  type is(blasius_t)
376  call bc_if%set_coef(this%C_Xh)
377  call json_get(params, 'case.fluid.blasius.delta', real_val)
378  call json_get(params, 'case.fluid.blasius.approximation',&
379  string_val2)
380  call json_get(params, 'case.fluid.blasius.freestream_velocity',&
381  real_vec)
382 
383  call bc_if%set_inflow(real_vec)
384  call bc_if%set_params(real_val, string_val2)
385 
386  end select
387  else if (trim(string_val1) .eq. "user") then
388  select type(bc_if => this%bc_inflow)
389  type is(usr_inflow_t)
390  call bc_if%set_coef(this%C_Xh)
391  end select
392  end if
393  end if
394 
395  call this%bc_wall%init(this%c_Xh)
396  call this%bc_wall%mark_zone(msh%wall)
397  call this%bc_wall%mark_zones_from_list(msh%labeled_zones,&
398  'w', this%bc_labels)
399  call this%bc_wall%finalize()
400  call bc_list_add(this%bclst_vel, this%bc_wall)
401 
402  ! Setup field dirichlet bc for u-velocity
403  call this%bc_field_vel%field_dirichlet_u%init(this%c_Xh)
404  call this%bc_field_vel%field_dirichlet_u%mark_zones_from_list(msh%labeled_zones,&
405  'd_vel_u', this%bc_labels)
406  call this%bc_field_vel%field_dirichlet_u%finalize()
407 
408  call mpi_allreduce(this%bc_field_vel%field_dirichlet_u%msk(0), integer_val, 1, &
409  mpi_integer, mpi_sum, neko_comm, ierr)
410  if (integer_val .gt. 0) call this%bc_field_vel%field_dirichlet_u%init_field('d_vel_u')
411 
412  ! Setup field dirichlet bc for v-velocity
413  call this%bc_field_vel%field_dirichlet_v%init(this%c_Xh)
414  call this%bc_field_vel%field_dirichlet_v%mark_zones_from_list(msh%labeled_zones,&
415  'd_vel_v', this%bc_labels)
416  call this%bc_field_vel%field_dirichlet_v%finalize()
417 
418  call mpi_allreduce(this%bc_field_vel%field_dirichlet_v%msk(0), integer_val, 1, &
419  mpi_integer, mpi_sum, neko_comm, ierr)
420  if (integer_val .gt. 0) call this%bc_field_vel%field_dirichlet_v%init_field('d_vel_v')
421 
422  ! Setup field dirichlet bc for w-velocity
423  call this%bc_field_vel%field_dirichlet_w%init(this%c_Xh)
424  call this%bc_field_vel%field_dirichlet_w%mark_zones_from_list(msh%labeled_zones,&
425  'd_vel_w', this%bc_labels)
426  call this%bc_field_vel%field_dirichlet_w%finalize()
427 
428  call mpi_allreduce(this%bc_field_vel%field_dirichlet_w%msk(0), integer_val, 1, &
429  mpi_integer, mpi_sum, neko_comm, ierr)
430  if (integer_val .gt. 0) call this%bc_field_vel%field_dirichlet_w%init_field('d_vel_w')
431 
432  ! Setup our global field dirichlet bc
433  call this%bc_field_vel%init(this%c_Xh)
434  call this%bc_field_vel%mark_zones_from_list(msh%labeled_zones,&
435  'd_vel_u', this%bc_labels)
436  call this%bc_field_vel%mark_zones_from_list(msh%labeled_zones,&
437  'd_vel_v', this%bc_labels)
438  call this%bc_field_vel%mark_zones_from_list(msh%labeled_zones,&
439  'd_vel_w', this%bc_labels)
440  call this%bc_field_vel%finalize()
441 
442  ! Add the field bc to velocity bcs
443  call bc_list_add(this%bclst_vel, this%bc_field_vel)
444 
445  !
446  ! Associate our field dirichlet update to the user one.
447  !
448  this%dirichlet_update_ => user%user_dirichlet_update
449 
450  !
451  ! Initialize field list and bc list for user_dirichlet_update
452  !
453  allocate(this%field_dirichlet_fields%fields(4))
454 
455  this%field_dirichlet_fields%fields(1)%f => &
456  this%bc_field_vel%field_dirichlet_u%field_bc
457  this%field_dirichlet_fields%fields(2)%f => &
458  this%bc_field_vel%field_dirichlet_v%field_bc
459  this%field_dirichlet_fields%fields(3)%f => &
460  this%bc_field_vel%field_dirichlet_w%field_bc
461  this%field_dirichlet_fields%fields(4)%f => &
462  this%bc_field_prs%field_bc
463 
464  call bc_list_init(this%field_dirichlet_bcs, size=4)
465  call bc_list_add(this%field_dirichlet_bcs, this%bc_field_vel%field_dirichlet_u)
466  call bc_list_add(this%field_dirichlet_bcs, this%bc_field_vel%field_dirichlet_v)
467  call bc_list_add(this%field_dirichlet_bcs, this%bc_field_vel%field_dirichlet_w)
468 
469  !
470  ! Check if we need to output boundaries
471  !
472  call json_get_or_default(params, 'case.output_boundary', logical_val,&
473  .false.)
474 
475  if (logical_val) then
476  call this%bdry%init(this%dm_Xh, 'bdry')
477  this%bdry = 0.0_rp
478 
479  call bdry_mask%init(this%c_Xh)
480  call bdry_mask%mark_zone(msh%wall)
481  call bdry_mask%mark_zones_from_list(msh%labeled_zones,&
482  'w', this%bc_labels)
483  call bdry_mask%finalize()
484  call bdry_mask%set_g(1.0_rp)
485  call bdry_mask%apply_scalar(this%bdry%x, this%dm_Xh%size())
486  call bdry_mask%free()
487 
488  call bdry_mask%init(this%c_Xh)
489  call bdry_mask%mark_zone(msh%inlet)
490  call bdry_mask%mark_zones_from_list(msh%labeled_zones,&
491  'v', this%bc_labels)
492  call bdry_mask%finalize()
493  call bdry_mask%set_g(2.0_rp)
494  call bdry_mask%apply_scalar(this%bdry%x, this%dm_Xh%size())
495  call bdry_mask%free()
496 
497  call bdry_mask%init(this%c_Xh)
498  call bdry_mask%mark_zone(msh%outlet)
499  call bdry_mask%mark_zones_from_list(msh%labeled_zones,&
500  'o', this%bc_labels)
501  call bdry_mask%finalize()
502  call bdry_mask%set_g(3.0_rp)
503  call bdry_mask%apply_scalar(this%bdry%x, this%dm_Xh%size())
504  call bdry_mask%free()
505 
506  call bdry_mask%init(this%c_Xh)
507  call bdry_mask%mark_zone(msh%sympln)
508  call bdry_mask%mark_zones_from_list(msh%labeled_zones,&
509  'sym', this%bc_labels)
510  call bdry_mask%finalize()
511  call bdry_mask%set_g(4.0_rp)
512  call bdry_mask%apply_scalar(this%bdry%x, this%dm_Xh%size())
513  call bdry_mask%free()
514 
515  call bdry_mask%init(this%c_Xh)
516  call bdry_mask%mark_zone(msh%periodic)
517  call bdry_mask%finalize()
518  call bdry_mask%set_g(5.0_rp)
519  call bdry_mask%apply_scalar(this%bdry%x, this%dm_Xh%size())
520  call bdry_mask%free()
521 
522  call bdry_mask%init(this%c_Xh)
523  call bdry_mask%mark_zone(msh%outlet_normal)
524  call bdry_mask%mark_zones_from_list(msh%labeled_zones,&
525  'on', this%bc_labels)
526  call bdry_mask%finalize()
527  call bdry_mask%set_g(6.0_rp)
528  call bdry_mask%apply_scalar(this%bdry%x, this%dm_Xh%size())
529  call bdry_mask%free()
530 
531  end if
532 
533  !
534  ! Setup right-hand side fields.
535  !
536  allocate(this%f_x)
537  allocate(this%f_y)
538  allocate(this%f_z)
539  call this%f_x%init(this%dm_Xh, fld_name="fluid_rhs_x")
540  call this%f_y%init(this%dm_Xh, fld_name="fluid_rhs_y")
541  call this%f_z%init(this%dm_Xh, fld_name="fluid_rhs_z")
542 
543  ! Initialize the source term
544  call this%source_term%init(params, this%f_x, this%f_y, this%f_z, this%c_Xh,&
545  user)
546 
547  end subroutine fluid_scheme_init_common
548 
550  subroutine fluid_scheme_init_uvw(this, msh, lx, params, kspv_init, scheme, &
551  user, material_properties)
552  implicit none
553  class(fluid_scheme_t), target, intent(inout) :: this
554  type(mesh_t), target, intent(inout) :: msh
555  integer, intent(inout) :: lx
556  type(json_file), target, intent(inout) :: params
557  type(user_t), target, intent(in) :: user
558  type(material_properties_t), target, intent(inout) :: material_properties
559  logical :: kspv_init
560  character(len=*), intent(in) :: scheme
561  ! Variables for extracting json
562  real(kind=rp) :: abs_tol
563  character(len=:), allocatable :: solver_type, precon_type
564  integer :: ksp_vel_maxiter
565 
566 
567  call fluid_scheme_init_common(this, msh, lx, params, scheme, user, &
569 
570  call neko_field_registry%add_field(this%dm_Xh, 'u')
571  call neko_field_registry%add_field(this%dm_Xh, 'v')
572  call neko_field_registry%add_field(this%dm_Xh, 'w')
573  this%u => neko_field_registry%get_field('u')
574  this%v => neko_field_registry%get_field('v')
575  this%w => neko_field_registry%get_field('w')
576 
577  call json_get(params, 'case.fluid.velocity_solver.type', solver_type)
578  call json_get(params, 'case.fluid.velocity_solver.preconditioner', &
579  precon_type)
580  call json_get(params, 'case.fluid.velocity_solver.absolute_tolerance', &
581  abs_tol)
582 
583  if (kspv_init) then
584  call json_get_or_default(params, &
585  'case.fluid.velocity_solver.max_iterations', &
586  ksp_vel_maxiter, 800)
587  call fluid_scheme_solver_factory(this%ksp_vel, this%dm_Xh%size(), &
588  solver_type, ksp_vel_maxiter, abs_tol)
589  call fluid_scheme_precon_factory(this%pc_vel, this%ksp_vel, &
590  this%c_Xh, this%dm_Xh, this%gs_Xh, this%bclst_vel, precon_type)
591  end if
592 
593  call neko_log%end_section()
594  end subroutine fluid_scheme_init_uvw
595 
597  subroutine fluid_scheme_init_all(this, msh, lx, params, kspv_init, kspp_init,&
598  scheme, user, material_properties)
599  implicit none
600  class(fluid_scheme_t), target, intent(inout) :: this
601  type(mesh_t), target, intent(inout) :: msh
602  integer, intent(inout) :: lx
603  type(json_file), target, intent(inout) :: params
604  type(user_t), target, intent(in) :: user
605  type(material_properties_t), target, intent(inout) :: material_properties
606  logical :: kspv_init
607  logical :: kspp_init
608  character(len=*), intent(in) :: scheme
609  real(kind=rp) :: real_val, dong_delta, dong_uchar
610  real(kind=rp), allocatable :: real_vec(:)
611  integer :: integer_val, ierr
612  character(len=:), allocatable :: string_val1, string_val2
613 
614  call fluid_scheme_init_common(this, msh, lx, params, scheme, user, &
616 
617  call neko_field_registry%add_field(this%dm_Xh, 'u')
618  call neko_field_registry%add_field(this%dm_Xh, 'v')
619  call neko_field_registry%add_field(this%dm_Xh, 'w')
620  call neko_field_registry%add_field(this%dm_Xh, 'p')
621  this%u => neko_field_registry%get_field('u')
622  this%v => neko_field_registry%get_field('v')
623  this%w => neko_field_registry%get_field('w')
624  this%p => neko_field_registry%get_field('p')
625 
626  !! lag fields
627  call this%ulag%init(this%u, 2)
628  call this%vlag%init(this%v, 2)
629  call this%wlag%init(this%w, 2)
630 
631 
632  !
633  ! Setup pressure boundary conditions
634  !
635  call bc_list_init(this%bclst_prs)
636  call this%bc_prs%init(this%c_Xh)
637  call this%bc_prs%mark_zones_from_list(msh%labeled_zones,&
638  'o', this%bc_labels)
639  call this%bc_prs%mark_zones_from_list(msh%labeled_zones,&
640  'on', this%bc_labels)
641 
642  ! Field dirichlet pressure bc
643  call this%bc_field_prs%init(this%c_Xh)
644  call this%bc_field_prs%mark_zones_from_list(msh%labeled_zones,&
645  'd_pres', this%bc_labels)
646  call this%bc_field_prs%finalize()
647  call mpi_allreduce(this%bc_field_prs%msk(0), integer_val, 1, &
648  mpi_integer, mpi_sum, neko_comm, ierr)
649 
650  if (integer_val .gt. 0) call this%bc_field_prs%init_field('d_pres')
651  call bc_list_add(this%bclst_prs, this%bc_field_prs)
652  call bc_list_add(this%field_dirichlet_bcs, this%bc_field_prs)
653 
654  if (msh%outlet%size .gt. 0) then
655  call this%bc_prs%mark_zone(msh%outlet)
656  end if
657  if (msh%outlet_normal%size .gt. 0) then
658  call this%bc_prs%mark_zone(msh%outlet_normal)
659  end if
660 
661  call this%bc_prs%finalize()
662  call this%bc_prs%set_g(0.0_rp)
663  call bc_list_add(this%bclst_prs, this%bc_prs)
664  call this%bc_dong%init(this%c_Xh)
665  call this%bc_dong%mark_zones_from_list(msh%labeled_zones,&
666  'o+dong', this%bc_labels)
667  call this%bc_dong%mark_zones_from_list(msh%labeled_zones,&
668  'on+dong', this%bc_labels)
669  call this%bc_dong%finalize()
670 
671  call json_get_or_default(params, 'case.fluid.outflow_condition.delta',&
672  dong_delta, 0.01_rp)
673  call json_get_or_default(params, 'case.fluid.outflow_condition.velocity_scale',&
674  dong_uchar, 1.0_rp)
675 
676 
677  call this%bc_dong%set_vars(dong_uchar, dong_delta)
678 
679  call bc_list_add(this%bclst_prs, this%bc_dong)
680 
681 
682  if (kspv_init) then
683  call json_get_or_default(params, &
684  'case.fluid.velocity_solver.max_iterations', &
685  integer_val, 800)
686  call json_get(params, 'case.fluid.velocity_solver.type', string_val1)
687  call json_get(params, 'case.fluid.velocity_solver.preconditioner', &
688  string_val2)
689  call json_get(params, 'case.fluid.velocity_solver.absolute_tolerance', &
690  real_val)
691 
692  call fluid_scheme_solver_factory(this%ksp_vel, this%dm_Xh%size(), &
693  string_val1, integer_val, real_val)
694  call fluid_scheme_precon_factory(this%pc_vel, this%ksp_vel, &
695  this%c_Xh, this%dm_Xh, this%gs_Xh, this%bclst_vel, string_val2)
696  end if
697 
698  if (kspp_init) then
699  call json_get_or_default(params, &
700  'case.fluid.pressure_solver.max_iterations', &
701  integer_val, 800)
702  call json_get(params, 'case.fluid.pressure_solver.type', string_val1)
703  call json_get(params, 'case.fluid.pressure_solver.preconditioner', &
704  string_val2)
705  call json_get(params, 'case.fluid.pressure_solver.absolute_tolerance', &
706  real_val)
707 
708  call fluid_scheme_solver_factory(this%ksp_prs, this%dm_Xh%size(), &
709  string_val1, integer_val, real_val)
710  call fluid_scheme_precon_factory(this%pc_prs, this%ksp_prs, &
711  this%c_Xh, this%dm_Xh, this%gs_Xh, this%bclst_prs, string_val2)
712  end if
713 
714 
715  call neko_log%end_section()
716 
717  end subroutine fluid_scheme_init_all
718 
720  subroutine fluid_scheme_free(this)
721  class(fluid_scheme_t), intent(inout) :: this
722 
723  call this%bdry%free()
724 
725  if (allocated(this%bc_inflow)) then
726  call this%bc_inflow%free()
727  end if
728 
729  call this%bc_wall%free()
730  call this%bc_sym%free()
731 
732  !
733  ! Free everything related to field_dirichlet BCs
734  !
735  call this%bc_field_prs%field_bc%free()
736  call this%bc_field_prs%free()
737  call this%bc_field_vel%field_dirichlet_u%field_bc%free()
738  call this%bc_field_vel%field_dirichlet_v%field_bc%free()
739  call this%bc_field_vel%field_dirichlet_w%field_bc%free()
740  call this%bc_field_vel%free()
741 
742  call this%field_dirichlet_fields%free()
743  call bc_list_free(this%field_dirichlet_bcs)
744  if (associated(this%dirichlet_update_)) then
745  this%dirichlet_update_ => null()
746  end if
747 
748  call this%Xh%free()
749 
750  if (allocated(this%ksp_vel)) then
751  call krylov_solver_destroy(this%ksp_vel)
752  deallocate(this%ksp_vel)
753  end if
754 
755  if (allocated(this%ksp_prs)) then
756  call krylov_solver_destroy(this%ksp_prs)
757  deallocate(this%ksp_prs)
758  end if
759 
760  if (allocated(this%pc_vel)) then
761  call precon_destroy(this%pc_vel)
762  deallocate(this%pc_vel)
763  end if
764 
765  if (allocated(this%pc_prs)) then
766  call precon_destroy(this%pc_prs)
767  deallocate(this%pc_prs)
768  end if
769 
770  if (allocated(this%bc_labels)) then
771  deallocate(this%bc_labels)
772  end if
773 
774  call this%source_term%free()
775 
776  call this%gs_Xh%free()
777 
778  call this%c_Xh%free()
779 
780  call bc_list_free(this%bclst_vel)
781 
782  call this%scratch%free()
783 
784  nullify(this%params)
785 
786  nullify(this%u)
787  nullify(this%v)
788  nullify(this%w)
789  nullify(this%p)
790 
791  call this%ulag%free()
792  call this%vlag%free()
793  call this%wlag%free()
794 
795 
796  if (associated(this%f_x)) then
797  call this%f_x%free()
798  end if
799 
800  if (associated(this%f_y)) then
801  call this%f_y%free()
802  end if
803 
804  if (associated(this%f_z)) then
805  call this%f_z%free()
806  end if
807 
808  nullify(this%f_x)
809  nullify(this%f_y)
810  nullify(this%f_z)
811 
812 
813  end subroutine fluid_scheme_free
814 
817  subroutine fluid_scheme_validate(this)
818  class(fluid_scheme_t), target, intent(inout) :: this
819  ! Variables for retrieving json parameters
820  logical :: logical_val
821 
822  if ( (.not. associated(this%u)) .or. &
823  (.not. associated(this%v)) .or. &
824  (.not. associated(this%w)) .or. &
825  (.not. associated(this%p))) then
826  call neko_error('Fields are not registered')
827  end if
828 
829  if ( (.not. allocated(this%u%x)) .or. &
830  (.not. allocated(this%v%x)) .or. &
831  (.not. allocated(this%w%x)) .or. &
832  (.not. allocated(this%p%x))) then
833  call neko_error('Fields are not allocated')
834  end if
835 
836  if (.not. allocated(this%ksp_vel)) then
837  call neko_error('No Krylov solver for velocity defined')
838  end if
839 
840  if (.not. allocated(this%ksp_prs)) then
841  call neko_error('No Krylov solver for pressure defined')
842  end if
843 
844  if (.not. associated(this%params)) then
845  call neko_error('No parameters defined')
846  end if
847 
848  if (allocated(this%bc_inflow)) then
849  select type(ip => this%bc_inflow)
850  type is(usr_inflow_t)
851  call ip%validate
852  end select
853  end if
854 
855  !
856  ! Setup checkpoint structure (if everything is fine)
857  !
858  call this%chkp%init(this%u, this%v, this%w, this%p)
859 
860  !
861  ! Setup mean flow fields if requested
862  !
863  if (this%params%valid_path('case.statistics')) then
864  call json_get_or_default(this%params, 'case.statistics.enabled',&
865  logical_val, .true.)
866  if (logical_val) then
867  call this%mean%init(this%u, this%v, this%w, this%p)
868  call this%stats%init(this%c_Xh, this%mean%u, &
869  this%mean%v, this%mean%w, this%mean%p)
870  end if
871  end if
872 
873 ! if (this%params%stats_mean_sqr_flow) then
874 ! call this%mean_sqr%init(this%u, this%v, this%w, this%p)
875 ! end if
876 
877  end subroutine fluid_scheme_validate
878 
883  subroutine fluid_scheme_bc_apply_vel(this, t, tstep)
884  class(fluid_scheme_t), intent(inout) :: this
885  real(kind=rp), intent(in) :: t
886  integer, intent(in) :: tstep
887 
888  call bc_list_apply_vector(this%bclst_vel,&
889  this%u%x, this%v%x, this%w%x, this%dm_Xh%size(), t, tstep)
890 
891  end subroutine fluid_scheme_bc_apply_vel
892 
895  subroutine fluid_scheme_bc_apply_prs(this, t, tstep)
896  class(fluid_scheme_t), intent(inout) :: this
897  real(kind=rp), intent(in) :: t
898  integer, intent(in) :: tstep
899 
900  call bc_list_apply_scalar(this%bclst_prs, this%p%x, &
901  this%p%dof%size(), t, tstep)
902 
903  end subroutine fluid_scheme_bc_apply_prs
904 
907  subroutine fluid_scheme_solver_factory(ksp, n, solver, max_iter, abstol)
908  class(ksp_t), allocatable, target, intent(inout) :: ksp
909  integer, intent(in), value :: n
910  character(len=*), intent(in) :: solver
911  integer, intent(in) :: max_iter
912  real(kind=rp), intent(in) :: abstol
913 
914  call krylov_solver_factory(ksp, n, solver, max_iter, abstol)
915 
916  end subroutine fluid_scheme_solver_factory
917 
919  subroutine fluid_scheme_precon_factory(pc, ksp, coef, dof, gs, bclst, pctype)
920  class(pc_t), allocatable, target, intent(inout) :: pc
921  class(ksp_t), target, intent(inout) :: ksp
922  type(coef_t), target, intent(inout) :: coef
923  type(dofmap_t), target, intent(inout) :: dof
924  type(gs_t), target, intent(inout) :: gs
925  type(bc_list_t), target, intent(inout) :: bclst
926  character(len=*) :: pctype
927 
928  call precon_factory(pc, pctype)
929 
930  select type(pcp => pc)
931  type is(jacobi_t)
932  call pcp%init(coef, dof, gs)
933  type is (sx_jacobi_t)
934  call pcp%init(coef, dof, gs)
935  type is (device_jacobi_t)
936  call pcp%init(coef, dof, gs)
937  type is(hsmg_t)
938  if (len_trim(pctype) .gt. 4) then
939  if (index(pctype, '+') .eq. 5) then
940  call pcp%init(dof%msh, dof%Xh, coef, dof, gs, &
941  bclst, trim(pctype(6:)))
942  else
943  call neko_error('Unknown coarse grid solver')
944  end if
945  else
946  call pcp%init(dof%msh, dof%Xh, coef, dof, gs, bclst)
947  end if
948  end select
949 
950  call ksp%set_pc(pc)
951 
952  end subroutine fluid_scheme_precon_factory
953 
955  subroutine fluid_scheme_set_usr_inflow(this, usr_eval)
956  class(fluid_scheme_t), intent(inout) :: this
957  procedure(usr_inflow_eval) :: usr_eval
958 
959  select type(bc_if => this%bc_inflow)
960  type is(usr_inflow_t)
961  call bc_if%set_eval(usr_eval)
962  class default
963  call neko_error("Not a user defined inflow condition")
964  end select
965  end subroutine fluid_scheme_set_usr_inflow
966 
968  function fluid_compute_cfl(this, dt) result(c)
969  class(fluid_scheme_t), intent(in) :: this
970  real(kind=rp), intent(in) :: dt
971  real(kind=rp) :: c
972 
973  c = cfl(dt, this%u%x, this%v%x, this%w%x, &
974  this%Xh, this%c_Xh, this%msh%nelv, this%msh%gdim)
975 
976  end function fluid_compute_cfl
977 
978 end module fluid_scheme
Abstract interface defining a dirichlet condition on a list of fields.
Abstract interface to dealocate a fluid formulation.
Abstract interface to initialize a fluid formulation.
Abstract interface to restart a fluid scheme.
Abstract interface to compute a time-step.
Retrieves a parameter by name or assigns a provided default value. In the latter case also adds the m...
Definition: json_utils.f90:53
Retrieves a parameter by name or throws an error.
Definition: json_utils.f90:44
Abstract interface defining a user defined inflow condition (pointwise)
Definition: usr_inflow.f90:79
Defines a boundary condition.
Definition: bc.f90:34
subroutine, public bc_list_add(bclst, bc)
Add a condition to a list of boundary conditions.
Definition: bc.f90:490
subroutine, public bc_list_apply_vector(bclst, x, y, z, n, t, tstep)
Apply a list of boundary conditions to a vector field.
Definition: bc.f90:572
subroutine, public bc_list_init(bclst, size)
Constructor for a list of boundary conditions.
Definition: bc.f90:449
subroutine, public bc_list_free(bclst)
Destructor for a list of boundary conditions.
Definition: bc.f90:476
subroutine, public bc_list_apply_scalar(bclst, x, n, t, tstep)
Apply a list of boundary conditions to a scalar field.
Definition: bc.f90:515
Defines a Blasius profile dirichlet condition.
Definition: blasius.f90:34
Defines a checkpoint.
Definition: checkpoint.f90:34
Coefficients.
Definition: coef.f90:34
Definition: comm.F90:1
type(mpi_comm) neko_comm
MPI communicator.
Definition: comm.F90:16
Defines a dirichlet boundary condition.
Definition: dirichlet.f90:34
Defines a mapping of the degrees of freedom.
Definition: dofmap.f90:35
Defines a dong outflow condition.
Defines inflow dirichlet conditions.
Defines inflow dirichlet conditions.
Defines a registry for storing solution fields.
type(field_registry_t), target, public neko_field_registry
Global field registry.
Stores a series fields.
Defines a field.
Definition: field.f90:34
Fluid formulations.
subroutine fluid_scheme_init_common(this, msh, lx, params, scheme, user, material_properties)
Initialize common data for the current scheme.
subroutine fluid_scheme_init_all(this, msh, lx, params, kspv_init, kspp_init, scheme, user, material_properties)
Initialize all components of the current scheme.
subroutine fluid_scheme_free(this)
Deallocate a fluid formulation.
real(kind=rp) function fluid_compute_cfl(this, dt)
Compute CFL.
subroutine fluid_scheme_solver_factory(ksp, n, solver, max_iter, abstol)
Initialize a linear solver.
subroutine fluid_scheme_set_usr_inflow(this, usr_eval)
Initialize a user defined inflow condition.
subroutine fluid_scheme_bc_apply_vel(this, t, tstep)
Apply all boundary conditions defined for velocity Here we perform additional gs operations to take c...
subroutine fluid_scheme_validate(this)
Validate that all fields, solvers etc necessary for performing time-stepping are defined.
subroutine fluid_scheme_precon_factory(pc, ksp, coef, dof, gs, bclst, pctype)
Initialize a Krylov preconditioner.
subroutine fluid_scheme_init_uvw(this, msh, lx, params, kspv_init, scheme, user, material_properties)
Initialize all velocity related components of the current scheme.
subroutine fluid_scheme_bc_apply_prs(this, t, tstep)
Apply all boundary conditions defined for pressure.
Implements the fluid_source_term_t type.
Computes various statistics for the fluid fields. We use the Reynolds decomposition for a field u = ...
Definition: fluid_stats.f90:36
Implements the fluid_user_source_term_t type.
Gather-scatter.
Defines inflow dirichlet conditions.
Definition: inflow.f90:34
Utilities for retrieving parameters from the case files.
Definition: json_utils.f90:34
subroutine, public krylov_solver_destroy(ksp)
Destroy an interative Krylov solver.
subroutine, public krylov_solver_factory(ksp, n, solver, max_iter, abstol, M)
Initialize an iterative Krylov solver.
Implements the base abstract type for Krylov solvers plus helper types.
Definition: krylov.f90:34
Logging routines.
Definition: log.f90:34
type(log_t), public neko_log
Global log stream.
Definition: log.f90:61
Implements material_properties_t type.
Definition: math.f90:60
Collection of vector field operations operating on and . Note that in general the indices and ....
Definition: mathops.f90:65
Defines a mean flow field.
Definition: mean_flow.f90:34
Defines a mean squared flow field.
Defines a mesh.
Definition: mesh.f90:34
integer, parameter, public neko_msh_max_zlbls
Max num. zone labels.
Definition: mesh.f90:55
Build configurations.
Definition: neko_config.f90:34
Dirichlet condition on axis aligned plane in the non normal direction.
Definition: non_normal.f90:34
integer, parameter, public rp
Global precision used in computations.
Definition: num_types.f90:12
Operators.
Definition: operators.f90:34
real(kind=rp) function, public cfl(dt, u, v, w, Xh, coef, nelv, gdim)
Definition: operators.f90:266
subroutine precon_destroy(pc)
Destroy a preconditioner.
subroutine precon_factory(pc, pctype)
Create a preconditioner.
Defines a registry for storing and requesting temporary fields This can be used when you have a funct...
Implements the source_term_t type and a wrapper source_term_wrapper_t.
Definition: source_term.f90:34
Defines a function space.
Definition: space.f90:34
integer, parameter, public gll
Definition: space.f90:48
Defines a container for all statistics.
Definition: statistics.f90:34
Mixed Dirichlet-Neumann axis aligned symmetry plane.
Definition: symmetry.f90:34
Compound scheme for the advection and diffusion operators in a transport equation.
Implements type time_step_controller.
Interfaces for user interaction with NEKO.
Definition: user_intf.f90:34
Defines inflow dirichlet conditions.
Definition: usr_inflow.f90:34
Utilities.
Definition: utils.f90:35
subroutine neko_warning(warning_msg)
Definition: utils.f90:191
Defines wall boundary conditions.
Definition: wall.f90:34
A list of boundary conditions.
Definition: bc.f90:102
Blasius profile for inlet (vector valued)
Definition: blasius.f90:48
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition: coef.f90:54
Generic Dirichlet boundary condition on .
Definition: dirichlet.f90:44
Dong outflow condition Follows "A Convective-like Energy-Stable Open Boundary Condition for Simulati...
User defined dirichlet condition, for which the user can work with an entire field....
Extension of the user defined dirichlet condition field_dirichlet
field_list_t, To be able to group fields together
Definition: field_list.f90:7
Base type of all fluid formulations.
Wrapper contaning and executing the fluid source terms.
A source-term for the fluid, with procedure pointers pointing to the actual implementation in the use...
Dirichlet condition for inlet (vector valued)
Definition: inflow.f90:43
Base abstract type for a canonical Krylov method, solving .
Definition: krylov.f90:65
Contains all the material properties necessary in the simulation.
Dirichlet condition in non normal direction of a plane.
Definition: non_normal.f90:50
The function space for the SEM solution fields.
Definition: space.f90:62
Mixed Dirichlet-Neumann symmetry plane condition.
Definition: symmetry.f90:50
Implements the logic to compute the time coefficients for the advection and diffusion operators in a ...
Provides a tool to set time step dt.
User defined dirichlet condition for inlet (vector valued)
Definition: usr_inflow.f90:45
No-slip Wall boundary condition.
Definition: wall.f90:43