Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
scalar_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!
34
36 use num_types, only : rp, dp
38 rhs_maker_ext_fctry, rhs_maker_bdf_fctry, rhs_maker_oifs_fctry
41 use checkpoint, only : chkp_t
42 use field, only : field_t
44 use mesh, only : mesh_t
45 use coefs, only : coef_t
48 use gather_scatter, only : gs_t, gs_op_add, gs_op_min, gs_op_max
49 use scalar_residual, only : scalar_residual_t, scalar_residual_factory
50 use ax_product, only : ax_t, ax_helm_allocator
51 use ax_helm_svv, only : ax_helm_svv_t
54 use krylov, only : ksp_monitor_t
57 use projection, only : projection_t
58 use math, only : col2, add2s2
62 use advection, only : advection_t, advection_factory
65 use json_module, only : json_file, json_core, json_value
66 use user_intf, only : user_t
69 use time_state, only : time_state_t
71 use bc, only : bc_t, bc_dirichlet
72 use comm, only : neko_comm
73 use mpi_f08, only : mpi_allreduce, mpi_integer, mpi_max
74 implicit none
75 private
76
77
78 type, public, extends(scalar_scheme_t) :: scalar_pnpn_t
79
81 type(field_t) :: s_res
82
84 type(field_t) :: ds
85
87 class(ax_t), allocatable :: ax
88
90 type(projection_t) :: proj_s
91
93 type(scalar_bc_projector_t) :: bc_projector
94
96 class(advection_t), allocatable :: adv
97
98 ! Time interpolation scheme
99 logical :: oifs
100
101 ! Advection terms for the oifs method
102 type(field_t) :: advs
103
105 class(scalar_residual_t), allocatable :: res
106
108 class(rhs_maker_ext_t), allocatable :: makeext
109
111 class(rhs_maker_bdf_t), allocatable :: makebdf
112
114 class(rhs_maker_oifs_t), allocatable :: makeoifs
115
117 type(field_t) :: abx1, abx2
118
120 type(field_series_t), pointer :: ulag => null()
121 type(field_series_t), pointer :: vlag => null()
122 type(field_series_t), pointer :: wlag => null()
123
124 contains
126 procedure, pass(this) :: init => scalar_pnpn_init
128 procedure, pass(this) :: restart => scalar_pnpn_restart
130 procedure, pass(this) :: register_checkpoint => &
133 procedure, pass(this) :: free => scalar_pnpn_free
135 procedure, pass(this) :: step => scalar_pnpn_step
137 procedure, pass(this) :: apply_strong_bcs => scalar_scheme_apply_strong_bcs
139 procedure, pass(this) :: setup_bcs_ => scalar_pnpn_setup_bcs_
140 end type scalar_pnpn_t
141
142 interface
143
150 module subroutine scalar_pnpn_bc_factory(object, scheme, json, coef, user)
151 class(bc_t), pointer, intent(inout) :: object
152 type(scalar_pnpn_t), intent(in) :: scheme
153 type(json_file), intent(inout) :: json
154 type(coef_t), target, intent(in) :: coef
155 type(user_t), intent(in) :: user
156 end subroutine scalar_pnpn_bc_factory
157 end interface
158
159 interface
160
163 module subroutine scalar_pnpn_bc_allocator(object, type_name)
164 class(bc_t), pointer, intent(inout) :: object
165 character(len=*), intent(in) :: type_name
166 end subroutine scalar_pnpn_bc_allocator
167 end interface
168
169 !
170 ! Machinery for injecting user-defined types
171 !
172
176 abstract interface
177 subroutine scalar_pnpn_bc_allocate(obj)
178 import bc_t
179 class(bc_t), pointer, intent(inout) :: obj
180 end subroutine scalar_pnpn_bc_allocate
181 end interface
182
183 interface
184
187 module subroutine register_scalar_pnpn_bc(type_name, allocator)
188 character(len=*), intent(in) :: type_name
189 procedure(scalar_pnpn_bc_allocate), pointer, intent(in) :: allocator
190 end subroutine register_scalar_pnpn_bc
191 end interface
192
194 type scalar_pnpn_bc_allocator_entry
195 character(len=NEKO_TYPENAME_LEN) :: type_name
196 procedure(scalar_pnpn_bc_allocate), pointer, nopass :: allocator => null()
197 end type scalar_pnpn_bc_allocator_entry
198
200 type(scalar_pnpn_bc_allocator_entry), allocatable, private :: &
201 scalar_pnpn_bc_registry(:)
202
204 integer, private :: scalar_pnpn_bc_registry_size = 0
205
206 public :: scalar_pnpn_bc_allocator, scalar_pnpn_bc_allocate, &
207 register_scalar_pnpn_bc
208
209contains
210
223 subroutine scalar_pnpn_init(this, msh, coef, gs, params, numerics_params, &
224 user, chkp, ulag, vlag, wlag, time_scheme, rho)
225 class(scalar_pnpn_t), target, intent(inout) :: this
226 type(mesh_t), target, intent(in) :: msh
227 type(coef_t), target, intent(in) :: coef
228 type(gs_t), target, intent(inout) :: gs
229 type(json_file), target, intent(inout) :: params
230 type(json_file), target, intent(inout) :: numerics_params
231 type(user_t), target, intent(in) :: user
232 type(chkp_t), target, intent(inout) :: chkp
233 type(field_series_t), target, intent(in) :: ulag, vlag, wlag
234 type(time_scheme_controller_t), target, intent(in) :: time_scheme
235 type(field_t), target, intent(in) :: rho
236 integer :: i
237 class(bc_t), pointer :: bc_i
238 character(len=15), parameter :: scheme = 'Modular (Pn/Pn)'
239 logical :: advection
240 real(kind=dp), pointer :: tlag(:), dtlag(:)
241
242 call this%free()
243
244 ! Initiliaze base type.
245 call this%scheme_init(msh, coef, gs, params, scheme, user, rho)
246
247 ! Setup backend dependent Ax routines
248 if (this%svv_enabled) then
249 call ax_helm_allocator(this%ax, type_name = "standard_svv")
250 select type (operator => this%ax)
251 class is (ax_helm_svv_t)
252 operator%svv => this%svv
253 end select
254 else if (this%c_Xh%geo_compression) then
255 call ax_helm_allocator(this%ax, type_name = "standard_compr")
256 else
257 call ax_helm_allocator(this%ax, type_name = "standard")
258 end if
259
260 ! Setup backend dependent scalar residual routines
261 call scalar_residual_factory(this%res)
262
263 ! Setup backend dependent summation of extrapolation scheme
264 call rhs_maker_ext_fctry(this%makeext)
265
266 ! Setup backend dependent contributions to F from lagged BD terms
267 call rhs_maker_bdf_fctry(this%makebdf)
268
269 ! Setup backend dependent contributions of the OIFS scheme
270 call rhs_maker_oifs_fctry(this%makeoifs)
271
272 ! Initialize variables specific to this plan
273 associate(xh_lx => this%Xh%lx, xh_ly => this%Xh%ly, xh_lz => this%Xh%lz, &
274 dm_xh => this%dm_Xh, nelv => this%msh%nelv)
275
276 call this%s_res%init(dm_xh, "s_res")
277
278 call this%abx1%init(dm_xh, trim(this%name) // "_abx1")
279
280 call this%abx2%init(dm_xh, trim(this%name) // "_abx2")
281
282 call this%advs%init(dm_xh, "advs")
283
284 call this%ds%init(dm_xh, 'ds')
285
286 end associate
287
288 ! Set up boundary conditions
289 call this%setup_bcs_(user)
290
291 do i = 1, this%bcs%size()
292 if (this%bcs%bc_type(i) .eq. bc_dirichlet) then
293 bc_i => this%bcs%get(i)
294 call this%bc_projector%mark(bc_i)
295 end if
296 end do
297
298 ! Initialize projection space
299 call this%proj_s%init(this%dm_Xh%size(), this%projection_dim, &
300 this%projection_activ_step)
301
302 ! Determine the time-interpolation scheme
303 call json_get_or_default(numerics_params, 'oifs', this%oifs, .false.)
304 ! Point to case checkpoint
305 this%chkp => chkp
306 ! Initialize advection factory
307 call json_get_or_default(params, 'advection', advection, .true.)
308 ! OIFS integrates the advection term. With advection disabled, fall back to
309 ! the standard BDF history assembly.
310 this%oifs = this%oifs .and. advection
311
312 this%ulag => ulag
313 this%vlag => vlag
314 this%wlag => wlag
315
316 call chkp%get_time_history(tlag, dtlag)
317 call advection_factory(this%adv, numerics_params, this%c_Xh, &
318 ulag, vlag, wlag, dtlag, &
319 tlag, time_scheme, .not. advection, &
320 this%slag)
321 end subroutine scalar_pnpn_init
322
324 subroutine scalar_pnpn_register_checkpoint(this, chkp)
325 class(scalar_pnpn_t), target, intent(inout) :: this
326 type(chkp_t), intent(inout) :: chkp
327 type(checkpoint_payload_t), pointer :: payload
328
329 payload => chkp%add_payload("scalars/" // trim(this%name))
330 call payload%add_field(this%s)
331 call payload%add_series(this%slag)
332 call payload%add_field(this%abx1)
333 call payload%add_field(this%abx2)
334
335 end subroutine scalar_pnpn_register_checkpoint
336
337 ! Restarts the scalar from a checkpoint
338 subroutine scalar_pnpn_restart(this, chkp)
339 class(scalar_pnpn_t), target, intent(inout) :: this
340 type(chkp_t), intent(inout) :: chkp
341 integer :: i, n
342 class(bc_t), pointer :: bc_i
343 logical :: interpolated
344
345 n = this%s%dof%size()
346
347 ! Lag fields are restored through the checkpoint's fsp mechanism
348
349 ! The restored fields are continuous unless the checkpoint was written
350 ! on another mesh or at another polynomial order and was interpolated
351 ! on the way in. Only then do the copies of a node shared between
352 ! elements need averaging: scale by the inverse multiplicity, then sum
353 ! the copies with a gather-scatter. On a plain restart that is the
354 ! identity in exact arithmetic but not in floating point, and would put
355 ! about one ulp of error on every shared node. Same guard as the fluid.
356 interpolated = allocated(chkp%previous_mesh%elements) .or. &
357 chkp%previous_Xh%lx .ne. this%Xh%lx
358
359 if (interpolated) then
360 call col2(this%s%x, this%c_Xh%mult, n)
361 call col2(this%slag%lf(1)%x, this%c_Xh%mult, n)
362 call col2(this%slag%lf(2)%x, this%c_Xh%mult, n)
363 end if
364 if (neko_bcknd_device .eq. 1) then
365 call device_memcpy(this%s%x, this%s%x_d, &
366 n, host_to_device, sync = .false.)
367 call device_memcpy(this%slag%lf(1)%x, this%slag%lf(1)%x_d, &
368 n, host_to_device, sync = .false.)
369 call device_memcpy(this%slag%lf(2)%x, this%slag%lf(2)%x_d, &
370 n, host_to_device, sync = .false.)
371 call device_memcpy(this%abx1%x, this%abx1%x_d, &
372 n, host_to_device, sync = .false.)
373 call device_memcpy(this%abx2%x, this%abx2%x_d, &
374 n, host_to_device, sync = .false.)
375 call device_memcpy(this%advs%x, this%advs%x_d, &
376 n, host_to_device, sync = .false.)
377 end if
378
379 if (interpolated) then
380 call this%gs_Xh%op(this%s, gs_op_add)
381 call this%gs_Xh%op(this%slag%lf(1), gs_op_add)
382 call this%gs_Xh%op(this%slag%lf(2), gs_op_add)
383 end if
384
385 ! Restore scalar bcs that need it. This is a no op in most bcs.
386 do i = 1, this%bcs%size()
387 bc_i => this%bcs%get(i)
388 call bc_i%restart(this%s, this%slag)
389 end do
390
391 nullify(bc_i)
392
393 end subroutine scalar_pnpn_restart
394
395 subroutine scalar_pnpn_free(this)
396 class(scalar_pnpn_t), intent(inout) :: this
397
398 ! Release operator references before scheme_free deallocates their targets.
399 if (allocated(this%Ax)) then
400 call this%Ax%free()
401 deallocate(this%Ax)
402 end if
403
404 !Deallocate scalar field
405 call this%scheme_free()
406
407 call this%bc_projector%free()
408 call this%proj_s%free()
409
410 call this%s_res%free()
411
412 call this%ds%free()
413
414 call this%abx1%free()
415 call this%abx2%free()
416
417 call this%advs%free()
418
419 if (allocated(this%adv)) then
420 call this%adv%free()
421 deallocate(this%adv)
422 end if
423
424 nullify(this%ulag)
425 nullify(this%vlag)
426 nullify(this%wlag)
427
428 if (allocated(this%res)) then
429 deallocate(this%res)
430 end if
431
432 if (allocated(this%makeext)) then
433 deallocate(this%makeext)
434 end if
435
436 if (allocated(this%makebdf)) then
437 deallocate(this%makebdf)
438 end if
439
440 if (allocated(this%makeoifs)) then
441 deallocate(this%makeoifs)
442 end if
443
444 end subroutine scalar_pnpn_free
445
446 subroutine scalar_pnpn_step(this, time, ext_bdf, dt_controller, &
447 ksp_results)
448 class(scalar_pnpn_t), intent(inout) :: this
449 type(time_state_t), intent(in) :: time
450 type(time_scheme_controller_t), intent(in) :: ext_bdf
451 type(time_step_controller_t), intent(in) :: dt_controller
452 type(ksp_monitor_t), intent(inout) :: ksp_results
453 type(field_t), pointer :: rho_cp
454 integer :: rho_cp_index
455 ! Number of degrees of freedom
456 integer :: n
457
458 if (this%freeze) return
459
460 n = this%dm_Xh%size()
461 call neko_scratch_registry%request_field(rho_cp, rho_cp_index, .false.)
462
463 call profiler_start_region(trim(this%name), 2)
464 associate(u => this%u, v => this%v, w => this%w, s => this%s, &
465 cp => this%cp, rho => this%rho, lambda_tot => this%lambda_tot, &
466 ds => this%ds, &
467 s_res => this%s_res, &
468 ax => this%Ax, f_xh => this%f_Xh, xh => this%Xh, &
469 c_xh => this%c_Xh, dm_xh => this%dm_Xh, gs_xh => this%gs_Xh, &
470 slag => this%slag, oifs => this%oifs, &
471 projection_dim => this%projection_dim, &
472 msh => this%msh, res => this%res, makeoifs => this%makeoifs, &
473 makeext => this%makeext, makebdf => this%makebdf, &
474 t => time%t, tstep => time%tstep, dt => time%dt)
475
476 ! Logs extra information if the log level is NEKO_LOG_DEBUG or above.
477 call print_debug(this)
478
479 ! Update material properties and their pointwise product.
480 call this%update_material_properties(time)
481 call field_col3(rho_cp, rho, cp, n)
482
483 ! Update the SVV coefficient if SVV is enabled.
484 if (this%svv_enabled) then
485 call this%svv%update(rho_cp, tstep)
486 end if
487
488 ! Compute the source terms that are extrapolated in time below
489 call this%source_term%compute(time, extrapolate = .true.)
490
491 if (oifs) then
492 ! The fluid step has already advanced u, v, and w to the new time.
493 ! Its first lag fields contain the velocity at tlag(1), which is the
494 ! latest time represented by the OIFS interpolation history.
495 call this%adv%compute_scalar(this%ulag%lf(1), this%vlag%lf(1), &
496 this%wlag%lf(1), s, this%advs, &
497 xh, this%c_Xh, dm_xh%size())
498 else
499 ! Add the advection operators to the right-hand side.
500 call this%adv%compute_scalar(u, v, w, s, f_xh, &
501 xh, this%c_Xh, dm_xh%size())
502 end if
503
504 ! Scale the volumetric source and advection terms by rho * cp.
505 call field_col2(f_xh, rho_cp, n)
506
507 ! Add weak boundary fluxes without scaling them by rho * cp.
508 call this%bcs%apply_scalar(f_xh%x, n, time, .false.)
509
510 ! Extrapolate the already scaled explicit right-hand side.
511 call makeext%compute_scalar(this%abx1, this%abx2, f_xh%x, &
512 ext_bdf%advection_coeffs%x, n)
513
514 if (oifs) then
515 call makeoifs%compute_scalar(this%advs%x, f_xh%x, &
516 rho_cp, real(dt, kind=rp), n)
517 else
518
519 ! Add the RHS contributions coming from the BDF scheme.
520 call makebdf%compute_scalar(slag, f_xh%x, s, c_xh%B, &
521 rho_cp, real(dt, kind=rp), ext_bdf%diffusion_coeffs%x, &
522 ext_bdf%ndiff, n)
523 end if
524
525 ! Source terms that must not be extrapolated in time are added as
526 ! computed, weighted by the mass matrix and rho * cp like the
527 ! extrapolated terms above.
528 call this%source_term%compute(time, extrapolate = .false., &
529 scale = rho_cp)
530
531 call slag%update()
532
534 call this%apply_strong_bcs(time)
535
536 ! Compute scalar residual.
537 call profiler_start_region(trim(this%name) // '_residual', 20)
538 call res%compute(ax, s, s_res, f_xh, c_xh, msh, xh, lambda_tot, &
539 rho_cp, ext_bdf%diffusion_coeffs%x(1), &
540 real(dt, kind=rp), dm_xh%size())
541
542 call gs_xh%op(s_res, gs_op_add)
543
544 ! Zero-out residual at Dirichlet nodes before solving.
545 call this%bc_projector%apply(s_res%x, dm_xh%size())
546
547 call profiler_end_region(trim(this%name) // '_residual', 20)
548
549 call this%proj_s%pre_solving(s_res%x, tstep, c_xh, n, dt_controller)
550
551 call this%pc%update()
552 call profiler_start_region(trim(this%name) // '_solve', 21)
553 ksp_results = this%ksp%solve(ax, ds, s_res%x, n, &
554 c_xh, this%bc_projector, gs_xh)
555 ksp_results%name = trim(this%name)
556 call profiler_end_region(trim(this%name) // '_solve', 21)
557
558 call this%proj_s%post_solving(ds%x, ax, c_xh, this%bc_projector, gs_xh, &
559 n, tstep, dt_controller)
560
561 ! Update the solution
562 if (neko_bcknd_device .eq. 1) then
563 call device_add2s2(s%x_d, ds%x_d, 1.0_rp, n)
564 else
565 call add2s2(s%x, ds%x, 1.0_rp, n)
566 end if
567
568 end associate
569 call neko_scratch_registry%relinquish_field(rho_cp_index)
570 call profiler_end_region(trim(this%name), 2)
571 end subroutine scalar_pnpn_step
572
573 subroutine print_debug(this)
574 class(scalar_pnpn_t), intent(inout) :: this
575 character(len=LOG_SIZE) :: log_buf
576
577 ! The norms are global reductions, so skip them unless they are logged.
578 if (neko_log%level() .lt. neko_log_debug) return
579
580 write(log_buf, '(A, A, E15.7, A, E15.7, A, E15.7)') 'Scalar debug', &
581 ' l2norm s', field_glsc2(this%s, this%s), &
582 ' slag1', field_glsc2(this%slag%lf(1), this%slag%lf(1)), &
583 ' slag2', field_glsc2(this%slag%lf(2), this%slag%lf(2))
584 call neko_log%message(log_buf, lvl = neko_log_debug)
585 write(log_buf, '(A, A, E15.7, A, E15.7)') 'Scalar debug2', &
586 ' l2norm abx1', field_glsc2(this%abx1, this%abx1), &
587 ' abx2', field_glsc2(this%abx2, this%abx2)
588 call neko_log%message(log_buf, lvl = neko_log_debug)
589 end subroutine print_debug
590
593 subroutine scalar_pnpn_setup_bcs_(this, user)
594 class(scalar_pnpn_t), target, intent(inout) :: this
595 type(user_t), target, intent(in) :: user
596 integer :: i, j, n_bcs, zone_size, global_zone_size, ierr
597 type(json_core) :: core
598 type(json_value), pointer :: bc_object
599 type(json_file) :: bc_subdict
600 class(bc_t), pointer :: bc_i
601 logical :: found
602 ! Monitor which boundary zones have been marked
603 logical, allocatable :: marked_zones(:)
604 integer, allocatable :: zone_indices(:)
605 character(len=256) :: error_msg
606
607 if (this%params%valid_path('boundary_conditions')) then
608 call this%params%info('boundary_conditions', &
609 n_children = n_bcs)
610 call this%params%get_core(core)
611 call this%params%get('boundary_conditions', bc_object, found)
612
613 call this%bcs%init(n_bcs)
614
615 allocate(marked_zones(size(this%msh%labeled_zones)))
616 marked_zones = .false.
617
618 do i = 1, n_bcs
619 ! Create a new json containing just the subdict for this bc
620 call json_extract_item(core, bc_object, i, bc_subdict)
621
622 ! Check that we are not trying to assing a bc to zone, for which one
623 ! has already been assigned and that the zone has more than 0 size
624 ! in the mesh.
625 call json_get(bc_subdict, "zone_indices", zone_indices)
626
627 do j = 1, size(zone_indices)
628 zone_size = this%msh%labeled_zones(zone_indices(j))%size
629 call mpi_allreduce(zone_size, global_zone_size, 1, &
630 mpi_integer, mpi_max, neko_comm, ierr)
631
632 if (global_zone_size .eq. 0) then
633 write(error_msg, '(A, I0, A, A, I0, A)') &
634 "Zone index ", zone_indices(j), &
635 " is invalid as this zone has 0 size, meaning it ", &
636 "does not exist in the mesh. Check scalar boundary ", &
637 "condition ", i, "."
638 call neko_error(error_msg)
639 error stop
640 end if
641
642 if (marked_zones(zone_indices(j))) then
643 write(error_msg, '(A, I0, A, A, A, A)')&
644 "Zone with index ", zone_indices(j), &
645 " has already been assigned a boundary condition. ", &
646 "Please check your boundary_conditions entry for the ", &
647 "scalar and make sure that each zone index appears only ",&
648 "in a single boundary condition."
649 call neko_error(error_msg)
650 error stop
651 else
652 marked_zones(zone_indices(j)) = .true.
653 end if
654 end do
655
656 bc_i => null()
657
658 call scalar_pnpn_bc_factory(bc_i, this, bc_subdict, this%c_Xh, user)
659 call this%bcs%append(bc_i)
660 end do
661
662 ! Make sure all labeled zones with non-zero size have been marked
663 do i = 1, size(this%msh%labeled_zones)
664 if ((this%msh%labeled_zones(i)%size .gt. 0) .and. &
665 (.not. marked_zones(i))) then
666 write(error_msg, '(A, I0)') &
667 "No scalar boundary condition assigned to zone ", i
668 call neko_error(error_msg)
669 error stop
670 end if
671 end do
672 else
673 ! Check that there are no labeled zones, i.e. all are periodic.
674 do i = 1, size(this%msh%labeled_zones)
675 if (this%msh%labeled_zones(i)%size .gt. 0) then
676 write(error_msg, '(A, A)') &
677 "No boundary_conditions entry in the case file for scalar ", &
678 this%s%name
679 call neko_error(error_msg)
680 error stop
681 end if
682 end do
683
684 ! For a pure periodic case, we still need to initilise the bc lists
685 ! to a zero size to avoid issues with apply() in step()
686 call this%bcs%init()
687
688 end if
689 end subroutine scalar_pnpn_setup_bcs_
690
693 subroutine scalar_scheme_apply_strong_bcs(this, time)
694 class(scalar_pnpn_t), intent(inout) :: this
695 type(time_state_t), intent(in) :: time
696
697 integer :: i
698 class(bc_t), pointer :: bc_i
699 bc_i => null()
700
701 ! First apply call, sets the Dirichlet value, let's call it d.
702 call this%bcs%apply(this%s, time = time, strong = .true.)
703 ! If we now have local nodes sharing the same global node, and with
704 ! some nodes not masked as Dirichlet, the node which *is* masked
705 ! will have the value d, and the the other ones just some value u.
706 ! Take a nodewise minimum between the local nodes.
707 ! Now, all local nodes store m = min(d, u)
708 call this%gs_Xh%op(this%s, gs_op_min, glb_cmd_event)
709 call device_event_sync(glb_cmd_event)
710
711 ! Second apply call, so Dirichlet nodes again store d, the rest still store
712 ! m, where m < d by construction.
713 call this%bcs%apply(this%s, time = time, strong = .true.)
714 ! Now apply a max, which guarantees that d wins and gets stored in all the
715 ! local nodes.
716 call this%gs_Xh%op(this%s, gs_op_max, glb_cmd_event)
717 call device_event_sync(glb_cmd_event)
718
719 ! Reset updated flags
720 do i = 1, this%bcs%size()
721 bc_i => this%bcs%get(i)
722 bc_i%updated = .false.
723 end do
724 nullify(bc_i)
725
726 end subroutine scalar_scheme_apply_strong_bcs
727
728
729end module scalar_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.
Subroutines to add advection terms to the RHS of a transport equation.
Definition advection.f90:34
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
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_add2s2(a_d, b_d, c1, n, strm)
Vector addition with scalar multiplication (multiplication on first argument)
subroutine, public device_col2(a_d, b_d, n, strm)
Vector multiplication .
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
Dirichlet condition applied in the facet normal direction.
subroutine, public field_col2(a, b, n)
Vector multiplication .
real(kind=rp) function, public field_glsc2(a, b, n)
subroutine, public field_col3(a, b, c, n)
Vector multiplication with 3 vectors .
Contains the field_serties_t type.
Defines a field.
Definition field.f90:34
Gather-scatter.
Utilities for retrieving parameters from the case files.
Implements the base abstract type for Krylov solvers plus helper types.
Definition krylov.f90:34
Logging routines.
Definition log.f90:34
integer, parameter, public neko_log_debug
Debug.
Definition log.f90:56
type(log_t), public neko_log
Global log stream.
Definition log.f90:92
integer, parameter, public log_size
Definition log.f90:46
Definition math.f90:60
subroutine, public col2(a, b, n)
Vector multiplication .
Definition math.f90:1085
subroutine, public add2s2(a, b, c1, n)
Vector addition with scalar multiplication (multiplication on second argument)
Definition math.f90:1037
Defines a mesh.
Definition mesh.f90:34
Build configurations.
integer, parameter neko_bcknd_device
integer, parameter, public dp
Definition num_types.f90:10
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:14
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.
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.
Contains the scalar_pnpn_t type.
subroutine scalar_pnpn_step(this, time, ext_bdf, dt_controller, ksp_results)
subroutine scalar_pnpn_setup_bcs_(this, user)
Initialize boundary conditions.
subroutine scalar_scheme_apply_strong_bcs(this, time)
Apply strong boundary conditions.
subroutine scalar_pnpn_restart(this, chkp)
subroutine scalar_pnpn_register_checkpoint(this, chkp)
Register this scalar scheme with the checkpoint.
subroutine scalar_pnpn_init(this, msh, coef, gs, params, numerics_params, user, chkp, ulag, vlag, wlag, time_scheme, rho)
Constructor.
subroutine scalar_pnpn_free(this)
Defines the residual for the scalar transport equation.
Contains the scalar_scheme_t type.
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.
Compound scheme for the advection and diffusion operators in a transport equation.
Base class for time integration schemes.
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
integer, parameter, public neko_typename_len
Definition utils.f90:44
Base abstract type for computing the advection operator.
Definition advection.f90:46
Helmholtz operator carrying a non-owning SVV object.
Base type for a matrix-vector product providing .
Definition ax.f90:44
Base type for a boundary condition.
Definition bc.f90:73
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:136
Dirichlet condition in facet normal direction.
Stores a series (sequence) of fields, logically connected to a base field, and arranged according to ...
Gather-scatter kernel.
Type for storing initial and final residuals in a Krylov solver.
Definition krylov.f90:57
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
Projector for scalar boundary conditions.
Abstract type to compute scalar residual.
Base type for a scalar advection-diffusion solver.
Implements the logic to compute the time coefficients for the advection and diffusion operators in a ...
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...