Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
fluid_pnpn.f90
Go to the documentation of this file.
1! Copyright (c) 2022-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!
35 use coefs, only : coef_t
36 use registry, only : neko_registry
37 use logger, only : neko_log, log_size
38 use num_types, only : rp, dp
39 use krylov, only : ksp_monitor_t
41 pnpn_prs_res_factory, pnpn_vel_res_factory, &
42 pnpn_prs_res_stress_factory, pnpn_vel_res_stress_factory
44 rhs_maker_oifs_t, rhs_maker_sumab_fctry, rhs_maker_bdf_fctry, &
45 rhs_maker_ext_fctry, rhs_maker_oifs_fctry
50 use fluid_aux, only : fluid_step_info
51 use projection, only : projection_t
55 use advection, only : advection_t, advection_factory
57 use json_module, only : json_file, json_core, json_value
60 use ax_product, only : ax_t, ax_helm_allocator
61 use ax_helm_svv, only : ax_helm_svv_t
63 use field, only : field_t
64 use dirichlet, only : dirichlet_t
69 use non_normal, only : non_normal_t
71 use symmetry, only : symmetry_t
72 use checkpoint, only : chkp_t
74 use mesh, only : mesh_t
75 use user_intf, only : user_t
77 use gs_ops, only : gs_op_add
79 use mathops, only : opadd2cm, opcolv
83 use bc, only : bc_t, bc_dirichlet
84 use mixed_bc, only : mixed_bc_t
88 use file, only : file_t
89 use operators, only : ortho, rotate_cyc
90 use opr_device, only : device_ortho
91 use time_state, only : time_state_t
92 use comm, only : neko_comm
93 use ale_manager, only : ale_manager_t
95 use mpi_f08, only : mpi_allreduce, mpi_in_place, mpi_max, mpi_lor, &
96 mpi_integer, mpi_logical
97 implicit none
98 private
99
100
101
103
106 integer :: schwarz_iterations = 0
107
109 type(field_t) :: p_res, u_res, v_res, w_res
110
113 type(field_t) :: dp, du, dv, dw
114
116 type(ale_manager_t) :: ale
117
118 ! ! Implicit operators, i.e. the left-hand-side of the Helmholz problem.
119 !
120
121 ! Coupled Helmholz operator for velocity
122 class(ax_t), allocatable :: ax_vel
123 ! Helmholz operator for pressure
124 class(ax_t), allocatable :: ax_prs
125
126 !
127 ! Projections for solver speed-up
128 !
129
131 type(projection_t) :: proj_prs
132 type(projection_vel_t) :: proj_vel
133
134 !
135 ! Special Karniadakis scheme boundary conditions in the pressure equation
136 !
137
139 type(facet_normal_t) :: bc_prs_surface
140
142 type(facet_normal_t) :: bc_sym_surface
143
145 class(vector_bc_projector_t), allocatable :: bcs_vel_projector
147 type(scalar_bc_projector_t) :: bcs_prs_projector
148
149
150 ! Checker for wether we have a strong pressure bc. If not, the pressure
151 ! is demeaned at every time step.
152 logical :: prs_dirichlet = .false.
153
154
155 ! The advection operator.
156 class(advection_t), allocatable :: adv
157
158 ! Time OIFS interpolation scheme for advection.
159 logical :: oifs
160
161 ! Time variables
162 type(field_t) :: abx1, aby1, abz1
163 type(field_t) :: abx2, aby2, abz2
164
165 ! Advection terms for the oifs method
166 type(field_t) :: advx, advy, advz
167
169 class(pnpn_prs_res_t), allocatable :: prs_res
170
172 class(pnpn_vel_res_t), allocatable :: vel_res
173
175 class(rhs_maker_sumab_t), allocatable :: sumab
176
178 class(rhs_maker_ext_t), allocatable :: makeabf
179
181 class(rhs_maker_bdf_t), allocatable :: makebdf
182
184 class(rhs_maker_oifs_t), allocatable :: makeoifs
185
187 type(fluid_volflow_t) :: vol_flow
188
190 logical :: full_stress_formulation = .false.
191
192 contains
194 procedure, pass(this) :: init => fluid_pnpn_init
196 procedure, pass(this) :: free => fluid_pnpn_free
198 procedure, pass(this) :: step => fluid_pnpn_step
200 procedure, pass(this) :: restart => fluid_pnpn_restart
202 procedure, pass(this) :: setup_bcs => fluid_pnpn_setup_bcs
204 procedure, pass(this) :: write_boundary_conditions => &
206 end type fluid_pnpn_t
207
208 interface
209
216 module subroutine pressure_bc_factory(object, scheme, json, coef, user)
217 class(bc_t), pointer, intent(inout) :: object
218 type(fluid_pnpn_t), intent(in) :: scheme
219 type(json_file), intent(inout) :: json
220 type(coef_t), target, intent(in) :: coef
221 type(user_t), target, intent(in) :: user
222 end subroutine pressure_bc_factory
223 end interface
224
225 interface
226
233 module subroutine velocity_bc_factory(object, scheme, json, coef, user)
234 class(bc_t), pointer, intent(inout) :: object
235 type(fluid_pnpn_t), intent(inout) :: scheme
236 type(json_file), intent(inout) :: json
237 type(coef_t), target, intent(in) :: coef
238 type(user_t), target, intent(in) :: user
239 end subroutine velocity_bc_factory
240 end interface
241
242contains
243
244 subroutine fluid_pnpn_init(this, msh, lx, params, user, chkp)
245 class(fluid_pnpn_t), target, intent(inout) :: this
246 type(mesh_t), target, intent(inout) :: msh
247 integer, intent(in) :: lx
248 type(json_file), target, intent(inout) :: params
249 type(user_t), target, intent(in) :: user
250 type(chkp_t), target, intent(inout) :: chkp
251 character(len=15), parameter :: scheme = 'Modular (Pn/Pn)'
252 integer :: i
253 class(bc_t), pointer :: bc_i, vel_bc
254 real(kind=rp) :: abs_tol
255 character(len=LOG_SIZE) :: log_buf
256 integer :: ierr, integer_val, solver_maxiter
257 character(len=:), allocatable :: solver_type, precon_type
258 logical :: monitor, found
259 logical :: advection
260 type(json_file) :: numerics_params, precon_params
261 type(checkpoint_payload_t), pointer :: payload
262 real(kind=dp), pointer :: tlag(:), dtlag(:)
263
264 call this%free()
265
266 ! Initialize base class
267 call this%init_base(msh, lx, params, scheme, user, .true.)
268
269 ! Add pressure field to the registry. For this scheme it is in the same
270 ! Xh as the velocity
271 call neko_registry%add_field(this%dm_Xh, 'p')
272 this%p => neko_registry%get_field('p')
273
274 !
275 ! Select governing equations via associated residual and Ax types
276 !
277
278 call json_get_or_lookup(params, 'case.numerics.time_order', integer_val)
279 allocate(this%ext_bdf)
280 call this%ext_bdf%init(integer_val)
281
282 call json_get_or_default(params, "case.fluid.full_stress_formulation", &
283 this%full_stress_formulation, .false.)
284
285 call json_get_or_default(params, "case.fluid.cyclic", this%c_Xh%cyclic, &
286 .false.)
287 call this%c_Xh%generate_cyclic_bc()
288
289 ! Setup backend dependent Ax routines for the velocity
290 call fluid_pnpn_ax_vel_factory(this)
291
292 if (this%full_stress_formulation) then
293 ! Setup backend dependent prs residual routines
294 call pnpn_prs_res_stress_factory(this%prs_res)
295
296 ! Setup backend dependent vel residual routines
297 call pnpn_vel_res_stress_factory(this%vel_res)
298
299 ! Allocate coupled projector for velocity boundary conditions
300 allocate(coupled_vector_bc_projector_t :: this%bcs_vel_projector)
301 else
302 ! Setup backend dependent prs residual routines
303 call pnpn_prs_res_factory(this%prs_res)
304
305 ! Setup backend dependent vel residual routines
306 call pnpn_vel_res_factory(this%vel_res)
307
308 ! Allocate segregated projector for velocity boundary conditions
309 allocate(segregated_vector_bc_projector_t :: this%bcs_vel_projector)
310 end if
311
312 ! Initialize the velocity bc projector
313 call this%bcs_vel_projector%init(this%c_Xh)
314
315 if (params%valid_path('case.fluid.nut_field')) then
316 if (.not. this%full_stress_formulation) then
317 call neko_error("You need to set full_stress_formulation to " // &
318 "true for the fluid to have a spatially varying " // &
319 "viscocity field.")
320 end if
321 call json_get(params, 'case.fluid.nut_field', this%nut_field_name)
322 else
323 this%nut_field_name = ""
324 end if
325
326 ! Setup Ax for the pressure
327 call ax_helm_allocator(this%Ax_prs, type_name = "standard")
328
329
330 ! Setup backend dependent summation of AB/BDF
331 call rhs_maker_sumab_fctry(this%sumab)
332
333 ! Setup backend dependent summation of extrapolation scheme
334 call rhs_maker_ext_fctry(this%makeabf)
335
336 ! Setup backend depenent contributions to F from lagged BD terms
337 call rhs_maker_bdf_fctry(this%makebdf)
338
339 ! Setup backend dependent summations of the OIFS method
340 call rhs_maker_oifs_fctry(this%makeoifs)
341
342 ! Initialize variables specific to this plan
343 associate(xh_lx => this%Xh%lx, xh_ly => this%Xh%ly, xh_lz => this%Xh%lz, &
344 dm_xh => this%dm_Xh, nelv => this%msh%nelv)
345
346 call this%p_res%init(dm_xh, "p_res")
347 call this%u_res%init(dm_xh, "u_res")
348 call this%v_res%init(dm_xh, "v_res")
349 call this%w_res%init(dm_xh, "w_res")
350 call this%abx1%init(dm_xh, "abx1")
351 call this%aby1%init(dm_xh, "aby1")
352 call this%abz1%init(dm_xh, "abz1")
353 call this%abx2%init(dm_xh, "abx2")
354 call this%aby2%init(dm_xh, "aby2")
355 call this%abz2%init(dm_xh, "abz2")
356 call this%advx%init(dm_xh, "advx")
357 call this%advy%init(dm_xh, "advy")
358 call this%advz%init(dm_xh, "advz")
359 end associate
360
361 call this%du%init(this%dm_Xh, 'du')
362 call this%dv%init(this%dm_Xh, 'dv')
363 call this%dw%init(this%dm_Xh, 'dw')
364 call this%dp%init(this%dm_Xh, 'dp')
365 ! Initialize ALE
366 call this%ale%init(this%c_Xh, params, user, chkp)
367
368 call neko_log%section("Fluid boundary conditions")
369 ! Set up boundary conditions
370 call this%setup_bcs(user, params)
371
372 ! Check if we need to output boundaries
373 call json_get_or_default(params, 'case.output_boundary', found, .false.)
374 if (found) call this%write_boundary_conditions()
375 call neko_log%end_section()
376
377 call this%proj_prs%init(this%dm_Xh%size(), this%pr_projection_dim, &
378 this%pr_projection_activ_step, &
379 this%pr_projection_reorthogonalize_basis)
380
381 call this%proj_vel%init(this%dm_Xh%size(), this%vel_projection_dim, &
382 this%vel_projection_activ_step)
383
384
385
386 ! Determine the time-interpolation scheme
387 call json_get_or_default(params, 'case.numerics.oifs', this%oifs, .false.)
388 if (params%valid_path('case.fluid.flow_rate_force')) then
389 call this%vol_flow%init(this%dm_Xh, params)
390 end if
391
392 ! Setup pressure solver
393 call neko_log%section("Pressure solver")
394
395 call json_get_or_lookup_or_default(params, &
396 'case.fluid.pressure_solver.max_iterations', &
397 solver_maxiter, 800)
398 call json_get(params, 'case.fluid.pressure_solver.type', solver_type)
399 call json_get(params, 'case.fluid.pressure_solver.preconditioner.type', &
400 precon_type)
401 call json_get(params, &
402 'case.fluid.pressure_solver.preconditioner', precon_params)
403 call json_get_or_lookup(params, &
404 'case.fluid.pressure_solver.absolute_tolerance', &
405 abs_tol)
406 call json_get_or_default(params, 'case.fluid.pressure_solver.monitor', &
407 monitor, .false.)
408 call neko_log%message('Type : ('// trim(solver_type) // &
409 ', ' // trim(precon_type) // ')')
410 write(log_buf, '(A,ES13.6)') 'Abs tol :', abs_tol
411 call neko_log%message(log_buf)
412
413 call this%solver_factory(this%ksp_prs, this%dm_Xh%size(), &
414 solver_type, solver_maxiter, abs_tol, monitor)
415 call this%precon_factory_(this%pc_prs, this%ksp_prs, &
416 this%c_Xh, this%dm_Xh, this%gs_Xh, this%bcs_prs, &
417 precon_type, precon_params)
418 call neko_log%end_section()
419
420 ! Initialize the advection factory
421 call json_get_or_default(params, 'case.fluid.advection', advection, .true.)
422 ! OIFS integrates the advection term. With advection disabled, fall back to
423 ! the standard BDF history assembly.
424 this%oifs = this%oifs .and. advection
425 call json_get(params, 'case.numerics', numerics_params)
426 call chkp%get_time_history(tlag, dtlag)
427 call advection_factory(this%adv, numerics_params, this%c_Xh, &
428 this%ulag, this%vlag, this%wlag, &
429 dtlag, tlag, this%ext_bdf, &
430 .not. advection)
431 ! Should be in init_base maybe?
432 this%chkp => chkp
433 ! Register the scheme state for checkpointing.
434 payload => this%chkp%add_payload("fluid")
435 call payload%add_field(this%u)
436 call payload%add_field(this%v)
437 call payload%add_field(this%w)
438 call payload%add_field(this%p)
439 call payload%add_field(this%abx1)
440 call payload%add_field(this%abx2)
441 call payload%add_field(this%aby1)
442 call payload%add_field(this%aby2)
443 call payload%add_field(this%abz1)
444 call payload%add_field(this%abz2)
445 call payload%add_series(this%ulag)
446 call payload%add_series(this%vlag)
447 call payload%add_series(this%wlag)
448
450 call json_get_or_default(params, 'case.fluid.schwarz_iterations', &
451 this%schwarz_iterations, 0)
452
453 call neko_log%end_section()
454
455 nullify(bc_i, vel_bc)
456
457 end subroutine fluid_pnpn_init
458
461 subroutine fluid_pnpn_ax_vel_factory(this)
462 class(fluid_pnpn_t), target, intent(inout) :: this
463
464 if (this%full_stress_formulation) then
465 if (this%svv_enabled) then
466 call ax_helm_allocator(this%Ax_vel, type_name = "full_svv")
467 select type (operator => this%Ax_vel)
468 class is (ax_helm_svv_full_t)
469 operator%svv => this%svv
470 end select
471 else
472 call ax_helm_allocator(this%Ax_vel, type_name = "full")
473 end if
474 else
475 if (this%svv_enabled) then
476 call ax_helm_allocator(this%Ax_vel, type_name = "standard_svv")
477 select type (operator => this%Ax_vel)
478 class is (ax_helm_svv_t)
479 operator%svv => this%svv
480 end select
481 else
482 call ax_helm_allocator(this%Ax_vel, type_name = "standard")
483 end if
484 end if
485
486 end subroutine fluid_pnpn_ax_vel_factory
487
488 subroutine fluid_pnpn_restart(this, chkp)
489 class(fluid_pnpn_t), target, intent(inout) :: this
490 type(chkp_t), intent(inout) :: chkp
491 integer :: i, j, n
492 class(bc_t), pointer :: bc_i
493
494 n = this%u%dof%size()
495 if (allocated(chkp%previous_mesh%elements) .or. &
496 chkp%previous_Xh%lx .ne. this%Xh%lx) then
497 associate(u => this%u, v => this%v, w => this%w, p => this%p, &
498 c_xh => this%c_Xh, ulag => this%ulag, vlag => this%vlag, &
499 wlag => this%wlag)
500 do concurrent(j = 1:n)
501 u%x(j,1,1,1) = u%x(j,1,1,1) * c_xh%mult(j,1,1,1)
502 v%x(j,1,1,1) = v%x(j,1,1,1) * c_xh%mult(j,1,1,1)
503 w%x(j,1,1,1) = w%x(j,1,1,1) * c_xh%mult(j,1,1,1)
504 p%x(j,1,1,1) = p%x(j,1,1,1) * c_xh%mult(j,1,1,1)
505 end do
506 do i = 1, this%ulag%size()
507 do concurrent(j = 1:n)
508 ulag%lf(i)%x(j,1,1,1) = ulag%lf(i)%x(j,1,1,1) &
509 * c_xh%mult(j,1,1,1)
510 vlag%lf(i)%x(j,1,1,1) = vlag%lf(i)%x(j,1,1,1) &
511 * c_xh%mult(j,1,1,1)
512 wlag%lf(i)%x(j,1,1,1) = wlag%lf(i)%x(j,1,1,1) &
513 * c_xh%mult(j,1,1,1)
514 end do
515 end do
516 end associate
517 end if
518
519 if (neko_bcknd_device .eq. 1) then
520 associate(u => this%u, v => this%v, w => this%w, &
521 ulag => this%ulag, vlag => this%vlag, wlag => this%wlag,&
522 p => this%p)
523 call device_memcpy(u%x, u%x_d, u%dof%size(), &
524 host_to_device, sync = .false.)
525 call device_memcpy(v%x, v%x_d, v%dof%size(), &
526 host_to_device, sync = .false.)
527 call device_memcpy(w%x, w%x_d, w%dof%size(), &
528 host_to_device, sync = .false.)
529 call device_memcpy(p%x, p%x_d, p%dof%size(), &
530 host_to_device, sync = .false.)
531 call device_memcpy(ulag%lf(1)%x, ulag%lf(1)%x_d, &
532 u%dof%size(), host_to_device, sync = .false.)
533 call device_memcpy(ulag%lf(2)%x, ulag%lf(2)%x_d, &
534 u%dof%size(), host_to_device, sync = .false.)
535
536 call device_memcpy(vlag%lf(1)%x, vlag%lf(1)%x_d, &
537 v%dof%size(), host_to_device, sync = .false.)
538 call device_memcpy(vlag%lf(2)%x, vlag%lf(2)%x_d, &
539 v%dof%size(), host_to_device, sync = .false.)
540
541 call device_memcpy(wlag%lf(1)%x, wlag%lf(1)%x_d, &
542 w%dof%size(), host_to_device, sync = .false.)
543 call device_memcpy(wlag%lf(2)%x, wlag%lf(2)%x_d, &
544 w%dof%size(), host_to_device, sync = .false.)
545 call device_memcpy(this%abx1%x, this%abx1%x_d, &
546 w%dof%size(), host_to_device, sync = .false.)
547 call device_memcpy(this%abx2%x, this%abx2%x_d, &
548 w%dof%size(), host_to_device, sync = .false.)
549 call device_memcpy(this%aby1%x, this%aby1%x_d, &
550 w%dof%size(), host_to_device, sync = .false.)
551 call device_memcpy(this%aby2%x, this%aby2%x_d, &
552 w%dof%size(), host_to_device, sync = .false.)
553 call device_memcpy(this%abz1%x, this%abz1%x_d, &
554 w%dof%size(), host_to_device, sync = .false.)
555 call device_memcpy(this%abz2%x, this%abz2%x_d, &
556 w%dof%size(), host_to_device, sync = .false.)
557 call device_memcpy(this%advx%x, this%advx%x_d, &
558 w%dof%size(), host_to_device, sync = .false.)
559 call device_memcpy(this%advy%x, this%advy%x_d, &
560 w%dof%size(), host_to_device, sync = .false.)
561 call device_memcpy(this%advz%x, this%advz%x_d, &
562 w%dof%size(), host_to_device, sync = .false.)
563 end associate
564 end if
565 ! Make sure that continuity is maintained (important for interpolation)
566 ! Do not do this for lagged rhs
567 ! (derivatives are not necessairly coninous across elements)
568
569 if (allocated(chkp%previous_mesh%elements) &
570 .or. chkp%previous_Xh%lx .ne. this%Xh%lx) then
571
572 call rotate_cyc(this%u, this%v, this%w, 1, this%c_Xh)
573 call this%gs_Xh%op(this%u, gs_op_add)
574 call this%gs_Xh%op(this%v, gs_op_add)
575 call this%gs_Xh%op(this%w, gs_op_add)
576 call this%gs_Xh%op(this%p, gs_op_add)
577 call rotate_cyc(this%u, this%v, this%w, 0, this%c_Xh)
578
579 do i = 1, this%ulag%size()
580 call rotate_cyc(this%ulag%lf(i), this%vlag%lf(i), &
581 this%wlag%lf(i), 1, this%c_Xh)
582 call this%gs_Xh%op(this%ulag%lf(i), gs_op_add)
583 call this%gs_Xh%op(this%vlag%lf(i), gs_op_add)
584 call this%gs_Xh%op(this%wlag%lf(i), gs_op_add)
585 call rotate_cyc(this%ulag%lf(i), this%vlag%lf(i), &
586 this%wlag%lf(i), 0, this%c_Xh)
587 end do
588 end if
589
590 call this%ale%sync_chkp(this%c_Xh, this%Xh, this%adv, chkp, this%gs_Xh)
591 if (this%ale%active) then
592 call this%bc_prs_surface%recompute_normals()
593 call this%bc_sym_surface%recompute_normals()
594 end if
595
596 ! Restore velocity bcs that need it (overset mostly)
597 do i = 1, this%bcs_vel%size()
598 bc_i => this%bcs_vel%get(i)
599 call bc_i%restart(this%u, this%v, this%w, &
600 this%ulag, this%vlag, this%wlag)
601 end do
602
603 ! Restore pressure bcs that need it (overset mostly)
604 do i = 1, this%bcs_prs%size()
605 bc_i => this%bcs_prs%get(i)
606 call bc_i%restart(this%p)
607 end do
608
609 nullify(bc_i)
610
611 end subroutine fluid_pnpn_restart
612
613 subroutine fluid_pnpn_free(this)
614 class(fluid_pnpn_t), intent(inout) :: this
615
616 if (allocated(this%Ax_vel)) then
617 call this%Ax_vel%free()
618 deallocate(this%Ax_vel)
619 end if
620
621 if (allocated(this%Ax_prs)) then
622 call this%Ax_prs%free()
623 deallocate(this%Ax_prs)
624 end if
625
626 !Deallocate velocity and pressure fields
627 call this%scheme_free()
628
629 if (allocated(this%ext_bdf)) then
630 call this%ext_bdf%free()
631 deallocate(this%ext_bdf)
632 end if
633
634 call this%bc_prs_surface%free()
635 call this%bc_sym_surface%free()
636 if (allocated(this%bcs_vel_projector)) then
637 call this%bcs_vel_projector%free()
638 deallocate(this%bcs_vel_projector)
639 end if
640 call this%bcs_prs_projector%free()
641 call this%proj_prs%free()
642 call this%proj_vel%free()
643
644 call this%p_res%free()
645 call this%u_res%free()
646 call this%v_res%free()
647 call this%w_res%free()
648
649 call this%ale%free()
650
651 call this%du%free()
652 call this%dv%free()
653 call this%dw%free()
654 call this%dp%free()
655
656 call this%abx1%free()
657 call this%aby1%free()
658 call this%abz1%free()
659
660 call this%abx2%free()
661 call this%aby2%free()
662 call this%abz2%free()
663
664 call this%advx%free()
665 call this%advy%free()
666 call this%advz%free()
667
668 if (allocated(this%adv)) then
669 call this%adv%free()
670 deallocate(this%adv)
671 end if
672
673 if (allocated(this%prs_res)) then
674 deallocate(this%prs_res)
675 end if
676
677 if (allocated(this%vel_res)) then
678 deallocate(this%vel_res)
679 end if
680
681 if (allocated(this%sumab)) then
682 deallocate(this%sumab)
683 end if
684
685 if (allocated(this%makeabf)) then
686 deallocate(this%makeabf)
687 end if
688
689 if (allocated(this%makebdf)) then
690 deallocate(this%makebdf)
691 end if
692
693 if (allocated(this%makeoifs)) then
694 deallocate(this%makeoifs)
695 end if
696
697 if (allocated(this%ext_bdf)) then
698 deallocate(this%ext_bdf)
699 end if
700
701 call this%vol_flow%free()
702
703 end subroutine fluid_pnpn_free
704
711 subroutine fluid_pnpn_step(this, time, dt_controller)
712 class(fluid_pnpn_t), target, intent(inout) :: this
713 type(time_state_t), intent(in) :: time
714 type(time_step_controller_t), intent(in) :: dt_controller
715 ! number of degrees of freedom
716 integer :: n
717 ! Solver results monitors (pressure + 3 velocity)
718 type(ksp_monitor_t) :: ksp_results(4)
719 integer :: iter
720
721 type(file_t) :: dump_file
722 class(bc_t), pointer :: bc_i
723
724 if (this%freeze) return
725
726 n = this%dm_Xh%size()
727
728 call profiler_start_region('Fluid', 1)
729 associate(u => this%u, v => this%v, w => this%w, p => this%p, &
730 u_e => this%u_e, v_e => this%v_e, w_e => this%w_e, &
731 du => this%du, dv => this%dv, dw => this%dw, dp => this%dp, &
732 u_res => this%u_res, v_res => this%v_res, w_res => this%w_res, &
733 p_res => this%p_res, ax_vel => this%Ax_vel, ax_prs => this%Ax_prs, &
734 xh => this%Xh, &
735 c_xh => this%c_Xh, dm_xh => this%dm_Xh, gs_xh => this%gs_Xh, &
736 ulag => this%ulag, vlag => this%vlag, wlag => this%wlag, &
737 msh => this%msh, prs_res => this%prs_res, &
738 source_term => this%source_term, vel_res => this%vel_res, &
739 sumab => this%sumab, makeoifs => this%makeoifs, &
740 makeabf => this%makeabf, makebdf => this%makebdf, &
741 vel_projection_dim => this%vel_projection_dim, &
742 pr_projection_dim => this%pr_projection_dim, &
743 oifs => this%oifs, &
744 rho => this%rho, mu_tot => this%mu_tot, &
745 f_x => this%f_x, f_y => this%f_y, f_z => this%f_z, &
746 t => time%t, tstep => time%tstep, dt => time%dt, &
747 ext_bdf => this%ext_bdf, event => glb_cmd_event, &
748 ale => this%ale)
749
750 ! Extrapolate the velocity if it's not done in nut_field estimation
751 call sumab%compute_fluid(u_e, v_e, w_e, u, v, w, &
752 ulag, vlag, wlag, ext_bdf%advection_coeffs%x, ext_bdf%nadv)
753
754 ! Compute the source terms
755 call this%source_term%compute(time)
756
757 ! Add Neumann bc contributions to the RHS
758 call this%bcs_vel%apply_vector(f_x%x, f_y%x, f_z%x, &
759 this%dm_Xh%size(), time, strong = .false.)
760
761 if (this%ale%active) then
762 if (oifs) then
763 call neko_error("ALE is not yet supported " // &
764 "with OIFS time integration.")
765 end if
767 call this%adv%compute_ale(u, v, w, &
768 ale%wm_x, ale%wm_y, ale%wm_z, &
769 f_x, f_y, f_z, &
770 xh, c_xh, dm_xh%size())
771 end if
772
773
774 if (oifs) then
775 ! Add the advection operators to the right-hand-side.
776 call this%adv%compute(u, v, w, &
777 this%advx, this%advy, this%advz, &
778 xh, this%c_Xh, dm_xh%size(), real(dt, kind=rp))
779
780 ! At this point the RHS contains the sum of the advection operator and
781 ! additional source terms, evaluated using the velocity field from the
782 ! previous time-step. Now, this value is used in the explicit time
783 ! scheme to advance both terms in time.
784
785 call makeabf%compute_fluid(this%abx1, this%aby1, this%abz1,&
786 this%abx2, this%aby2, this%abz2, &
787 f_x%x, f_y%x, f_z%x, &
788 rho%x(1,1,1,1), ext_bdf%advection_coeffs%x, n)
789
790 ! Now, the source terms from the previous time step are added to the
791 ! RHS.
792 call makeoifs%compute_fluid(this%advx%x, this%advy%x, this%advz%x, &
793 f_x%x, f_y%x, f_z%x, &
794 rho%x(1,1,1,1), real(dt, kind=rp), n)
795 else
796 ! Add the advection operators to the right-hand-side.
797 call this%adv%compute(u, v, w, &
798 f_x, f_y, f_z, &
799 xh, this%c_Xh, dm_xh%size())
800
801 ! At this point the RHS contains the sum of the advection operator and
802 ! additional source terms, evaluated using the velocity field from the
803 ! previous time-step. Now, this value is used in the explicit time
804 ! scheme to advance both terms in time.
805
806 call makeabf%compute_fluid(this%abx1, this%aby1, this%abz1,&
807 this%abx2, this%aby2, this%abz2, &
808 f_x%x, f_y%x, f_z%x, &
809 rho%x(1,1,1,1), ext_bdf%advection_coeffs%x, n)
810
811 ! Add the RHS contributions coming from the BDF scheme.
812 ! Blag and Blaglag are history of B matrices, mainly used for ALE.
813 ! For a normal simulation (no moving mesh), Blag and Blaglag
814 ! are just the initial B matrix, filled at initialization.
815 call makebdf%compute_fluid(ulag, vlag, wlag, f_x%x, f_y%x, f_z%x, &
816 u, v, w, c_xh%B, c_xh%Blag, c_xh%Blaglag, rho%x(1,1,1,1), &
817 real(dt, kind=rp), &
818 ext_bdf%diffusion_coeffs%x, ext_bdf%ndiff, n)
819
820 end if
821
822 if (this%ale%active) then
823 ! Advance Mesh (Moves points, updates B history, updates wm_lags)
824 call this%ale%advance_mesh(c_xh, time, ext_bdf%nadv)
825
826 call profiler_start_region('ALE recompute metrics')
827 ! Update Metrics
828 call c_xh%recompute_metrics()
829 ! Update the metrics used by the adv operator for delaiasing (coef_GL)
830 ! Maps the updated coef_GLL to coef_GL.
831 call this%adv%recompute_metrics(c_xh, .true.)
832
833 call this%bc_prs_surface%recompute_normals()
834 call this%bc_sym_surface%recompute_normals()
835 call profiler_end_region('ALE recompute metrics')
836 end if
837
838 call ulag%update()
839 call vlag%update()
840 call wlag%update()
841
842 ! Update material properties if necessary
843 call this%update_material_properties(time)
844
845 ! Update the SVV coefficient if necessary
846 if (this%svv_enabled) then
847 call this%svv%update(rho, tstep)
848 end if
849
850 do iter = 1, 1 + this%schwarz_iterations
851
852 call this%bc_apply_vel(time, strong = .true.)
853 call this%bc_apply_prs(time)
854
855 ! Compute pressure residual.
856 call profiler_start_region('Pressure_residual', 18)
857 call prs_res%compute(p, p_res,&
858 u, v, w, &
859 u_e, v_e, w_e, &
860 f_x, f_y, f_z, &
861 c_xh, gs_xh, &
862 this%bc_prs_surface, this%bc_sym_surface,&
863 ax_prs, ext_bdf%diffusion_coeffs%x(1), real(dt, kind=rp), &
864 mu_tot, rho, event)
865
866
867 ! De-mean the pressure residual when no strong pressure boundaries present
868 if (.not. this%prs_dirichlet .and. neko_bcknd_device .eq. 1) then
869 call device_ortho(p_res%x_d, this%glb_n_points, n)
870 else if (.not. this%prs_dirichlet) then
871 call ortho(p_res%x, this%glb_n_points, n)
872 end if
873
874 call gs_xh%op(p_res, gs_op_add, event)
875 call device_event_sync(event)
876
877 ! Set the residual to zero at strong pressure boundaries.
878 call this%bcs_prs_projector%apply(p_res%x, p%dof%size())
879
880
881 call profiler_end_region('Pressure_residual', 18)
882
883 ! Do projections only on the actual solutions of the tstep
884 ! not intermediate solutions from the subiterations.
885 if (iter .eq. 1) then
886 call this%proj_prs%pre_solving(p_res%x, tstep, c_xh, n, &
887 dt_controller, ax = ax_prs, gs_h = gs_xh, &
888 bclst = this%bcs_prs_projector, string = 'Pressure')
889 end if
890
891 call this%pc_prs%update()
892
893 call profiler_start_region('Pressure_solve', 3)
894
895 ! Solve for the pressure increment.
896 ksp_results(1) = &
897 this%ksp_prs%solve(ax_prs, dp, p_res%x, n, c_xh, &
898 this%bcs_prs_projector, gs_xh)
899 ksp_results(1)%name = 'Pressure'
900
901
902 call profiler_end_region('Pressure_solve', 3)
903
904 if (iter .eq. 1) then
905 call this%proj_prs%post_solving(dp%x, ax_prs, c_xh, &
906 this%bcs_prs_projector, gs_xh, n, tstep, dt_controller)
907 end if
908
909 ! Update the pressure with the increment. Demean if necessary.
910 call field_add2(p, dp, n)
911 if (.not. this%prs_dirichlet .and. neko_bcknd_device .eq. 1) then
912 call device_ortho(p%x_d, this%glb_n_points, n)
913 else if (.not. this%prs_dirichlet) then
914 call ortho(p%x, this%glb_n_points, n)
915 end if
916
917 ! Compute velocity residual.
918 call profiler_start_region('Velocity_residual', 19)
919 call vel_res%compute(ax_vel, u, v, w, &
920 u_res, v_res, w_res, &
921 p, &
922 f_x, f_y, f_z, &
923 c_xh, msh, xh, &
924 mu_tot, rho, ext_bdf%diffusion_coeffs%x(1), &
925 real(dt, kind=rp), dm_xh%size())
926
927 call rotate_cyc(u_res, v_res, w_res, 1, c_xh)
928 call gs_xh%op(u_res%x, v_res%x, w_res%x, dm_xh%size(), &
929 gs_op_add, event)
930 call device_event_sync(event)
931 call rotate_cyc(u_res, v_res, w_res, 0, c_xh)
932
933 ! Set residual to zero at strong velocity boundaries.
934 call this%bcs_vel_projector%apply(u_res%x, v_res%x, w_res%x, &
935 dm_xh%size())
936
937
938 call profiler_end_region('Velocity_residual', 19)
939
940 if (iter .eq. 1) then
941 call this%proj_vel%pre_solving(u_res%x, v_res%x, w_res%x, &
942 tstep, c_xh, n, dt_controller, 'Velocity')
943 end if
944
945 call this%pc_vel%update()
946
947 call profiler_start_region("Velocity_solve", 4)
948 ksp_results(2:4) = this%ksp_vel%solve_coupled(ax_vel, du, dv, dw, &
949 u_res%x, v_res%x, w_res%x, n, c_xh, &
950 this%bcs_vel_projector, gs_xh, &
951 this%ksp_vel%max_iter)
952 call profiler_end_region("Velocity_solve", 4)
953 if (this%full_stress_formulation) then
954 ksp_results(2)%name = 'Momentum'
955 else
956 ksp_results(2)%name = 'X-Velocity'
957 ksp_results(3)%name = 'Y-Velocity'
958 ksp_results(4)%name = 'Z-Velocity'
959 end if
960
961 if (iter .eq. 1) then
962 call this%proj_vel%post_solving(du%x, dv%x, dw%x, ax_vel, c_xh, &
963 this%bcs_vel_projector, gs_xh, n, tstep, &
964 dt_controller)
965 end if
966
967 if (neko_bcknd_device .eq. 1) then
968 call device_opadd2cm(u%x_d, v%x_d, w%x_d, &
969 du%x_d, dv%x_d, dw%x_d, 1.0_rp, n, msh%gdim)
970 else
971 call opadd2cm(u%x, v%x, w%x, du%x, dv%x, dw%x, 1.0_rp, n, msh%gdim)
972 end if
973
974 call fluid_step_info(time, ksp_results, &
975 this%full_stress_formulation, this%strict_convergence, &
976 this%allow_stabilization, iter)
977
978 end do
979
980 if (this%forced_flow_rate) then
981 ! Horrible mu hack?!
982 call this%vol_flow%adjust( u, v, w, p, u_res, v_res, w_res, p_res, &
983 c_xh, gs_xh, ext_bdf, rho%x(1,1,1,1), mu_tot, &
984 real(dt, kind=rp), time, this%bcs_prs_projector, &
985 this%bcs_vel_projector, ax_vel, ax_prs, this%ksp_prs, &
986 this%ksp_vel, this%pc_prs, this%pc_vel, this%ksp_prs%max_iter, &
987 this%ksp_vel%max_iter)
988 end if
989
990 ! Update mesh velocities for ALE
991 ! We update them here (end of step) for the next step.
992 ! Returns if .not. ale.
993 call this%ale%update_mesh_velocity(c_xh, time)
994
995 end associate
996
997 nullify(bc_i)
998
999 call profiler_end_region('Fluid', 1)
1000 end subroutine fluid_pnpn_step
1001
1004 subroutine fluid_pnpn_setup_bcs(this, user, params)
1005 class(fluid_pnpn_t), target, intent(inout) :: this
1006 type(user_t), target, intent(in) :: user
1007 type(json_file), intent(inout) :: params
1008 integer :: i, n_bcs, zone_index, j, zone_size, global_zone_size, ierr
1009 class(bc_t), pointer :: bc_i
1010 type(json_core) :: core
1011 type(json_value), pointer :: bc_object
1012 type(json_file) :: bc_subdict
1013 logical :: ale_active_local, any_moving_wall, moving_
1014 logical :: found
1015 ! Monitor which boundary zones have been marked
1016 logical, allocatable :: marked_zones(:)
1017 integer, allocatable :: zone_indices(:)
1018 character(len=256) :: error_msg
1019
1020 ! For ALE, we set a flag while reading the BCs
1021 character(len=:), allocatable :: bc_type_str
1022 this%ale%has_moving_boundary = .false.
1023 any_moving_wall = .false.
1024 ale_active_local = .false.
1025 call json_get_or_default(params, 'case.fluid.ale.enabled', &
1026 ale_active_local, .false.)
1027
1028 ! Special PnPn boundary conditions for pressure
1029 call this%bc_prs_surface%init_from_components(this%c_Xh)
1030 call this%bc_sym_surface%init_from_components(this%c_Xh)
1031
1032 ! Populate bcs_vel and bcs_prs based on the case file
1033 if (params%valid_path('case.fluid.boundary_conditions')) then
1034 call params%info('case.fluid.boundary_conditions', n_children = n_bcs)
1035 call params%get_core(core)
1036 call params%get('case.fluid.boundary_conditions', bc_object, found)
1037
1038 !
1039 ! Velocity bcs
1040 !
1041 call this%bcs_vel%init(n_bcs)
1042
1043 allocate(marked_zones(size(this%msh%labeled_zones)))
1044 marked_zones = .false.
1045
1046 do i = 1, n_bcs
1047 ! Create a new json containing just the subdict for this bc
1048 call json_extract_item(core, bc_object, i, bc_subdict)
1049
1050 call json_get_or_lookup(bc_subdict, "zone_indices", zone_indices)
1051
1052 ! Set the ALE flag to true if there is any moving no_slip wall
1053 call json_get(bc_subdict, "type", bc_type_str)
1054 moving_ = .false.
1055 if (trim(bc_type_str) .eq. "no_slip") then
1056 call json_get_or_default(bc_subdict, "moving", moving_, .false.)
1057 end if
1058 if (moving_) then
1059 this%ale%has_moving_boundary = .true.
1060 end if
1061
1062 ! Check that we are not trying to assing a bc to zone, for which one
1063 ! has already been assigned and that the zone has more than 0 size
1064 ! in the mesh.
1065 do j = 1, size(zone_indices)
1066 zone_size = this%msh%labeled_zones(zone_indices(j))%size
1067 call mpi_allreduce(zone_size, global_zone_size, 1, &
1068 mpi_integer, mpi_max, neko_comm, ierr)
1069
1070 if (global_zone_size .eq. 0) then
1071 write(error_msg, '(A, I0, A, A, I0, A)') &
1072 "Zone index ", zone_indices(j), &
1073 " is invalid as this zone has 0 size, meaning it ", &
1074 "is not in the mesh. Check fluid boundary condition ", &
1075 i, "."
1076 call neko_error(error_msg)
1077 end if
1078
1079 if (marked_zones(zone_indices(j))) then
1080 write(error_msg, '(A, I0, A, A, A, A)') &
1081 "Zone with index ", zone_indices(j), &
1082 " has already been assigned a boundary condition. ", &
1083 "Please check your boundary_conditions entry for the ", &
1084 "fluid and make sure that each zone index appears only ", &
1085 "in a single boundary condition."
1086 call neko_error(error_msg)
1087 else
1088 marked_zones(zone_indices(j)) = .true.
1089 end if
1090 end do
1091
1092 bc_i => null()
1093 call velocity_bc_factory(bc_i, this, bc_subdict, this%c_Xh, user)
1094
1095 ! Not all bcs require an allocation for velocity in particular,
1096 ! so we check.
1097 if (associated(bc_i)) then
1098
1099 select type (bc_i)
1100 type is (symmetry_aligned_t)
1101 ! In this case we need to tell the segregated projector where
1102 ! we have the dirichlet dofs component-wise. This is stored
1103 ! in the nested bcs. Of course, we rely on axis-alignment of
1104 ! the geometry.
1105 call this%bcs_vel_projector%mark(bc_i%bc_x, component = 'x')
1106 call this%bcs_vel_projector%mark(bc_i%bc_y, component = 'y')
1107 call this%bcs_vel_projector%mark(bc_i%bc_z, component = 'z')
1108 call this%bcs_vel%append(bc_i)
1109 call this%bc_sym_surface%mark_facets(bc_i%marked_facet)
1110 type is (symmetry_t)
1111 ! In this case we add the bc itself to the projector, which
1112 ! should be coupled.
1113 if (.not. this%full_stress_formulation) then
1114 call neko_error("The symmetry boundary condition " // &
1115 "requires the full stress formulation to be enabled.")
1116 end if
1117 call this%bcs_vel_projector%mark(bc_i)
1118 call this%bcs_vel%append(bc_i)
1119 call this%bc_sym_surface%mark_facets(bc_i%marked_facet)
1120 type is (non_normal_aligned_t)
1121 ! The situation is the same as symmetry.
1122 call this%bcs_vel_projector%mark(bc_i%bc_x, component = 'x')
1123 call this%bcs_vel_projector%mark(bc_i%bc_y, component = 'y')
1124 call this%bcs_vel_projector%mark(bc_i%bc_z, component = 'z')
1125 call this%bcs_vel%append(bc_i)
1126 type is (non_normal_t)
1127 call this%bcs_vel_projector%mark(bc_i)
1128 call this%bcs_vel%append(bc_i)
1129 type is (shear_stress_t)
1130 if (.not. this%full_stress_formulation) then
1131 call neko_error("The shear_stress boundary condition " // &
1132 "requires the full stress formulation to be enabled.")
1133 end if
1134 call this%bcs_vel_projector%mark(bc_i)
1135 call this%bcs_vel%append(bc_i)
1136 type is (wall_model_bc_t)
1137 if (.not. this%full_stress_formulation) then
1138 call neko_error("The wall_model boundary condition " // &
1139 "requires the full stress formulation to be enabled.")
1140 end if
1141 call this%bcs_vel_projector%mark(bc_i)
1142 call this%bcs_vel%append(bc_i)
1143 class default
1144
1145 ! Additionally we mark the special PnPn pressure bc.
1146 if (bc_i%bc_type .eq. bc_dirichlet) then
1147 call this%bc_prs_surface%mark_labeled_zones( &
1148 bc_i%zone_indices)
1149 if (this%full_stress_formulation) then
1150 call this%bcs_vel_projector%mark(bc_i)
1151 else
1152 call this%bcs_vel_projector%mark(bc_i, component = 'x')
1153 call this%bcs_vel_projector%mark(bc_i, component = 'y')
1154 call this%bcs_vel_projector%mark(bc_i, component = 'z')
1155 end if
1156 end if
1157
1158 call this%bcs_vel%append(bc_i)
1159 end select
1160 end if
1161 end do
1162
1163 if (this%ale%active .and. (.not. this%ale%has_moving_boundary)) then
1164 call neko_error("Case file error: ALE is active, " // &
1165 "but no moving wall was found. " // &
1166 "Use type = 'no_slip' with 'moving': true in case file.")
1167 end if
1168
1169 ! Make sure all labeled zones with non-zero size have been marked
1170 do i = 1, size(this%msh%labeled_zones)
1171 if ((this%msh%labeled_zones(i)%size .gt. 0) .and. &
1172 (.not. marked_zones(i))) then
1173 write(error_msg, '(A, I0)') &
1174 "No fluid boundary condition assigned to zone ", i
1175 call neko_error(error_msg)
1176 end if
1177 end do
1178
1179 !
1180 ! Pressure bcs
1181 !
1182 call this%bcs_prs%init(n_bcs)
1183
1184 do i = 1, n_bcs
1185 ! Create a new json containing just the subdict for this bc
1186 call json_extract_item(core, bc_object, i, bc_subdict)
1187 bc_i => null()
1188 call pressure_bc_factory(bc_i, this, bc_subdict, this%c_Xh, user)
1189
1190 ! Not all bcs require an allocation for pressure in particular,
1191 ! so we check.
1192 if (associated(bc_i)) then
1193 call this%bcs_prs%append(bc_i)
1194
1195 ! Mark strong pressure bcs in the projector to force zero change.
1196 if (bc_i%bc_type .eq. bc_dirichlet) then
1197 call this%bcs_prs_projector%mark(bc_i)
1198 end if
1199
1200 end if
1201
1202 end do
1203 else
1204 ! Check that there are no labeled zones, i.e. all are periodic.
1205 do i = 1, size(this%msh%labeled_zones)
1206 if (this%msh%labeled_zones(i)%size .gt. 0) then
1207 call neko_error("No boundary_conditions entry in the case file!")
1208 end if
1209 end do
1210
1211 ! For a pure periodic case, we still need to initilise the bc lists
1212 ! to a zero size to avoid issues with apply() in step()
1213 call this%bcs_vel%init()
1214 call this%bcs_prs%init()
1215
1216 end if
1217
1218 call this%bc_prs_surface%finalize()
1219 call this%bc_sym_surface%finalize()
1220 call this%bcs_vel_projector%finalize(rebuild_mask = .true.)
1221
1222 ! If we have no strong pressure bcs, we will demean the pressure
1223 this%prs_dirichlet = this%bcs_prs_projector%dof_mask%is_set()
1224 call mpi_allreduce(mpi_in_place, this%prs_dirichlet, 1, &
1225 mpi_logical, mpi_lor, neko_comm)
1226
1227
1228 if (allocated(marked_zones)) then
1229 deallocate(marked_zones)
1230 end if
1231
1232 if (allocated(zone_indices)) then
1233 deallocate(zone_indices)
1234 end if
1235
1236 nullify(bc_i, bc_object)
1237
1238 end subroutine fluid_pnpn_setup_bcs
1239
1241 subroutine fluid_pnpn_write_boundary_conditions(this)
1242 use inflow, only : inflow_t
1244 use blasius, only : blasius_t
1246 use dong_outflow, only : dong_outflow_t
1247 use no_slip, only : no_slip_t
1248 class(fluid_pnpn_t), target, intent(inout) :: this
1249 type(dirichlet_t) :: bdry_mask
1250 type(field_t), pointer :: bdry_field
1251 type(file_t) :: bdry_file
1252 integer :: temp_index, i
1253 class(bc_t), pointer :: bci
1254 character(len=LOG_SIZE) :: log_buf
1255
1256 write(log_buf, '(A)') 'Marking using integer keys in bdry0.f00000'
1257 call neko_log%message(log_buf)
1258 write(log_buf, '(A)') 'Condition-value pairs: '
1259 call neko_log%message(log_buf)
1260 write(log_buf, '(A)') ' no_slip (stationary wall) = 1'
1261 call neko_log%message(log_buf)
1262 write(log_buf, '(A)') ' velocity_value = 2'
1263 call neko_log%message(log_buf)
1264 write(log_buf, '(A)') ' outflow, normal_outflow (+dong) = 3'
1265 call neko_log%message(log_buf)
1266 write(log_buf, '(A)') ' symmetry = 4'
1267 call neko_log%message(log_buf)
1268 write(log_buf, '(A)') ' periodic = 6'
1269 call neko_log%message(log_buf)
1270 write(log_buf, '(A)') ' user_velocity = 7'
1271 call neko_log%message(log_buf)
1272 write(log_buf, '(A)') ' user_pressure = 8'
1273 call neko_log%message(log_buf)
1274 write(log_buf, '(A)') ' shear_stress = 9'
1275 call neko_log%message(log_buf)
1276 write(log_buf, '(A)') ' wall_modelling = 10'
1277 call neko_log%message(log_buf)
1278 write(log_buf, '(A)') ' blasius_profile = 11'
1279 call neko_log%message(log_buf)
1280 write(log_buf, '(A)') ' no_slip (moving wall) = 12'
1281 call neko_log%message(log_buf)
1282
1283 call neko_scratch_registry%request_field(bdry_field, temp_index, .true.)
1284
1285
1286
1287 call bdry_mask%init_from_components(this%c_Xh, 6.0_rp)
1288 call bdry_mask%mark_zone(this%msh%periodic)
1289 call bdry_mask%finalize()
1290 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1291 call bdry_mask%free()
1292
1293 do i = 1, this%bcs_prs%size()
1294 bci => this%bcs_prs%get(i)
1295 select type (bc => bci)
1296 type is (zero_dirichlet_t)
1297 call bdry_mask%init_from_components(this%c_Xh, 3.0_rp)
1298 call bdry_mask%mark_facets(bci%marked_facet)
1299 call bdry_mask%finalize()
1300 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1301 call bdry_mask%free()
1302 type is (dong_outflow_t)
1303 call bdry_mask%init_from_components(this%c_Xh, 3.0_rp)
1304 call bdry_mask%mark_facets(bci%marked_facet)
1305 call bdry_mask%finalize()
1306 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1307 call bdry_mask%free()
1308 type is (field_dirichlet_t)
1309 call bdry_mask%init_from_components(this%c_Xh, 8.0_rp)
1310 call bdry_mask%mark_facets(bci%marked_facet)
1311 call bdry_mask%finalize()
1312 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1313 call bdry_mask%free()
1314 end select
1315 end do
1316
1317 do i = 1, this%bcs_vel%size()
1318 bci => this%bcs_vel%get(i)
1319 select type (bc => bci)
1320 type is (no_slip_t)
1321 if (bc%is_moving) then
1322 ! moving wall
1323 call bdry_mask%init_from_components(this%c_Xh, 12.0_rp)
1324 else
1325 ! stationary wall
1326 call bdry_mask%init_from_components(this%c_Xh, 1.0_rp)
1327 end if
1328 call bdry_mask%mark_facets(bci%marked_facet)
1329 call bdry_mask%finalize()
1330 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1331 call bdry_mask%free()
1332 type is (inflow_t)
1333 call bdry_mask%init_from_components(this%c_Xh, 2.0_rp)
1334 call bdry_mask%mark_facets(bci%marked_facet)
1335 call bdry_mask%finalize()
1336 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1337 call bdry_mask%free()
1338 type is (symmetry_aligned_t)
1339 call bdry_mask%init_from_components(this%c_Xh, 4.0_rp)
1340 call bdry_mask%mark_facets(bci%marked_facet)
1341 call bdry_mask%finalize()
1342 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1343 call bdry_mask%free()
1344 type is (symmetry_t)
1345 call bdry_mask%init_from_components(this%c_Xh, 4.0_rp)
1346 call bdry_mask%mark_facets(bci%marked_facet)
1347 call bdry_mask%finalize()
1348 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1349 call bdry_mask%free()
1350 type is (field_dirichlet_vector_t)
1351 call bdry_mask%init_from_components(this%c_Xh, 7.0_rp)
1352 call bdry_mask%mark_facets(bci%marked_facet)
1353 call bdry_mask%finalize()
1354 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1355 call bdry_mask%free()
1356 type is (shear_stress_t)
1357 call bdry_mask%init_from_components(this%c_Xh, 9.0_rp)
1358 call bdry_mask%mark_facets(bci%marked_facet)
1359 call bdry_mask%finalize()
1360 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1361 call bdry_mask%free()
1362 type is (wall_model_bc_t)
1363 call bdry_mask%init_from_components(this%c_Xh, 10.0_rp)
1364 call bdry_mask%mark_facets(bci%marked_facet)
1365 call bdry_mask%finalize()
1366 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1367 call bdry_mask%free()
1368 type is (blasius_t)
1369 call bdry_mask%init_from_components(this%c_Xh, 11.0_rp)
1370 call bdry_mask%mark_facets(bci%marked_facet)
1371 call bdry_mask%finalize()
1372 call bdry_mask%apply_scalar(bdry_field%x, this%dm_Xh%size())
1373 call bdry_mask%free()
1374 end select
1375 end do
1376
1377
1378 call bdry_file%init('bdry.fld')
1379 call bdry_file%write(bdry_field)
1380
1381 call neko_scratch_registry%relinquish_field(temp_index)
1382
1383 nullify(bdry_field, bci)
1384
1385 end subroutine fluid_pnpn_write_boundary_conditions
1386
1387end module fluid_pnpn
double real
Copy data between host and device (or device and device)
Definition device.F90:72
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.
Apply cyclic boundary condition to a vector field.
Subroutines to add advection terms to the RHS of a transport equation.
Definition advection.f90:34
ALE Manager: Handles Mesh Motion.
Defines the full-stress SVV Helmholtz operator.
Base type for an SVV Helmholtz operator.
Defines a Matrix-vector product.
Definition ax.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 a Blasius profile dirichlet condition.
Definition blasius.f90:34
Format-independent checkpoint payloads.
Defines format-independent checkpoint registration and restart state.
Coefficients.
Definition coef.f90:34
Definition comm.F90:1
type(mpi_comm), public neko_comm
MPI communicator.
Definition comm.F90:46
subroutine, public device_opadd2cm(a1_d, a2_d, a3_d, b1_d, b2_d, b3_d, c, n, gdim)
subroutine, public device_opcolv(a1_d, a2_d, a3_d, c_d, gdim, n)
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 host_to_device
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 dong outflow condition.
Dirichlet condition applied in the facet normal direction.
Defines inflow dirichlet conditions.
Defines user dirichlet condition for a scalar field.
subroutine, public field_add2(a, b, n)
Vector addition .
subroutine, public field_copy(a, b, n)
Copy a vector .
Contains the field_serties_t type.
Defines a field.
Definition field.f90:34
Module for file I/O operations.
Definition file.f90:34
Auxiliary routines for fluid solvers.
Definition fluid_aux.f90:34
subroutine, public fluid_step_info(time, ksp_results, full_stress_formulation, strict_convergence, allow_stabilization, iteration)
Prints for prs, velx, vely, velz the following: Number of iterations, start residual,...
Definition fluid_aux.f90:54
Modular version of the Classic Nek5000 Pn/Pn formulation for fluids.
subroutine fluid_pnpn_setup_bcs(this, user, params)
Sets up the boundary condition for the scheme.
subroutine fluid_pnpn_restart(this, chkp)
subroutine fluid_pnpn_write_boundary_conditions(this)
Write a field with boundary condition specifications.
subroutine fluid_pnpn_step(this, time, dt_controller)
Advance fluid simulation in time.
subroutine fluid_pnpn_free(this)
subroutine fluid_pnpn_init(this, msh, lx, params, user, chkp)
Boundary condition factory for pressure.
Defines Gather-scatter operations.
Definition gs_ops.f90:34
integer, parameter, public gs_op_add
Definition gs_ops.f90:36
Defines inflow dirichlet conditions.
Definition inflow.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
Logging routines.
Definition log.f90:34
type(log_t), public neko_log
Global log stream.
Definition log.f90:91
integer, parameter, public log_size
Definition log.f90:46
Collection of vector field operations operating on and . Note that in general the indices and ....
Definition mathops.f90:67
subroutine, public opcolv(a1, a2, a3, c, gdim, n)
Definition mathops.f90:103
subroutine, public opadd2cm(a1, a2, a3, b1, b2, b3, c, n, gdim)
Definition mathops.f90:156
Defines a mesh.
Definition mesh.f90:34
Implements mixed_bc_t.
Definition mixed_bc.f90:31
Build configurations.
integer, parameter neko_bcknd_device
Defines no-slip boundary condition (extends zero_dirichlet)
Definition no_slip.f90:34
Implements non_normal_aligned_t.
Implements non_normal_t.
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
subroutine, public ortho(x, glb_n_points, n)
Othogonalize with regard to vector (1,1,1,1,1,1...,1)^T.
Operators accelerator backends.
subroutine, public device_ortho(x_d, glb_n_points, n)
Othogonalize with regard to vector (1,1,1,1,1,1...,1)^T.
Defines Pressure and velocity residuals in the Pn-Pn formulation.
Definition pnpn_res.f90:34
Profiling interface.
Definition profiler.F90:34
subroutine, public profiler_start_region(name, region_id)
Started a named (name) profiler region.
Definition profiler.F90:79
subroutine, public profiler_end_region(name, region_id)
End the most recently started profiler region.
Definition profiler.F90:116
Project x onto X , the space of old solutions and back again Couple projections for velocity.
Project x onto X, the space of old solutions and back again.
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
Routines to generate the right-hand sides for the convection-diffusion equation. Employs the EXT/BDF ...
Definition rhs_maker.f90:38
Implements scalar_projector_t.
Defines a registry for storing and requesting temporary objects This can be used when you have a func...
type(scratch_registry_t), target, public neko_scratch_registry
Global scratch registry.
Defines a shear stress boundary condition for a vector field. Maintainer: Timofey Mukha.
Implements the source_term_t type and a wrapper source_term_wrapper_t.
Implements symmetry_aligned_t.
Implements symmetry_t.
Definition symmetry.f90:34
Module with things related to the simulation time.
Implements type time_step_controller.
Interfaces for user interaction with NEKO.
Definition user_intf.f90:34
Utilities.
Definition utils.f90:35
subroutine, public neko_type_error(base_type, wrong_type, known_types)
Reports an error allocating a type for a particular base pointer class.
Definition utils.f90:413
Implements boundary condition projectors for vector fields. Two types concrete types are provided: se...
Defines the wall_model_bc_t type. Maintainer: Timofey Mukha.
Defines a zero-valued Dirichlet boundary condition.
Base abstract type for computing the advection operator.
Definition advection.f90:46
Helmholtz operator carrying a non-owning SVV object.
Matrix-vector product for a Helmholtz problem.
Base type for a matrix-vector product providing .
Definition ax.f90:43
Base type for a boundary condition.
Definition bc.f90:73
Blasius profile for inlet (vector valued).
Definition blasius.f90:55
Collection of live simulation data registered for checkpointing.
A named collection of live fields to checkpoint together.
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:135
Generic Dirichlet boundary condition on .
Definition dirichlet.f90:49
Dong outflow condition Follows "A Convective-like Energy-Stable Open Boundary Condition for Simulati...
Dirichlet condition in facet normal direction.
User defined dirichlet condition, for which the user can work with an entire field....
Extension of the user defined dirichlet condition field_dirichlet
Stores a series (sequence) of fields, logically connected to a base field, and arranged according to ...
A wrapper around a polymorphic generic_file_t that handles its init. This is essentially a factory fo...
Definition file.f90:56
Dirichlet condition for inlet (vector valued)
Definition inflow.f90:48
Type for storing initial and final residuals in a Krylov solver.
Definition krylov.f90:57
Base type for mixed boundary conditions that need projector-provided local-basis data on the physical...
Definition mixed_bc.f90:50
Mixed Dirichlet condition constraining the tangential vector components.
Axis-aligned mixed Dirichlet condition in the non-normal direction.
Abstract type to compute pressure residual.
Definition pnpn_res.f90:48
Abstract type to compute velocity residual.
Definition pnpn_res.f90:54
Abstract type to add contributions to F from lagged BD terms.
Definition rhs_maker.f90:59
Abstract type to sum up contributions to kth order extrapolation scheme.
Definition rhs_maker.f90:52
Abstract type to add contributions of kth order OIFS scheme.
Definition rhs_maker.f90:66
Abstract type to compute extrapolated velocity field for the pressure equation.
Definition rhs_maker.f90:46
Projector for scalar boundary conditions.
A shear stress boundary condition.
Symmetry boundary condition constraining the normal vector component.
Definition symmetry.f90:50
Axis-aligned symmetry boundary condition.
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...
A coupled projector for vector fields, suitable for mixed boundary conditions.
A projector for vector fields that acts component-wise.
Abstract type for resolving vector boundary conditions.
A shear stress boundary condition, computing the stress values using a wall model.
Zero-valued Dirichlet boundary condition. Used for no-slip walls, but also for various auxillary cond...