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