Neko 1.99.9
A portable framework for high-order spectral element flow simulations
Loading...
Searching...
No Matches
overset_interface_vector.f90
Go to the documentation of this file.
1! Copyright (c) 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 comm, only : neko_global_comm
37 use registry, only : neko_registry
38 use num_types, only : rp
39 use coefs, only : coef_t
40 use dirichlet, only : dirichlet_t
43 use mask, only : mask_t
44 use dofmap, only : dofmap_t
45 use bc, only : bc_t, bc_dirichlet
46 use bc_list, only : bc_list_t
47 use utils, only : split_string
48 use field, only : field_t
50 use field_list, only : field_list_t
51 use math, only : masked_copy_0, copy
53 use dofmap, only : dofmap_t
54 use vector, only : vector_t
55 use vector_list, only : vector_list_t
61 use vector_math, only : vector_copy
65 use stack, only : stack_i4_t
66 use json_module, only : json_file
68 use field_list, only : field_list_t
70 use, intrinsic :: iso_c_binding, only : c_ptr, c_size_t
72 use time_state, only : time_state_t
73 use mpi_f08, only : mpi_allreduce, mpi_integer, mpi_sum
75 use logger, only : neko_log, log_size
76
77
78 implicit none
79 private
80
82 ! for the application on a vector field.
83 type, public, extends(bc_t) :: overset_interface_vector_t
84 ! The bc for the first compoent.
85 type(field_dirichlet_t) :: bc_u
86 ! The bc for the second compoent.
87 type(field_dirichlet_t) :: bc_v
88 ! The bc for the third compoent.
89 type(field_dirichlet_t) :: bc_w
93 type(global_interpolation_t) :: interface_interpolator
95 type(mask_t) :: interface_dof_mask
96 type(mask_t) :: domain_element_mask
98 type(vector_t) :: x_dof, y_dof, z_dof
99 type(vector_t) :: x_interface_dof, y_interface_dof, z_interface_dof
100 type(vector_t) :: u_interface, v_interface, w_interface
101 type(vector_series_t) :: u_interface_lag, v_interface_lag, w_interface_lag
102 integer :: iextm_order = 1
104 real(kind=rp) :: relaxation = 1.0_rp
105 integer :: last_tstep = -1
106 type(vector_list_t) :: interface_dof, interface_field
108 type(global_interpolation_settings_t) :: interpolation_settings
109 integer :: n_int_tot = 0
110 logical :: find_interface = .false.
111 logical :: setup = .false.
112 logical :: log = .false.
114 logical :: restart_pending = .false.
115
118 procedure(morph_overset_interface), nopass, pointer :: &
119 morph_interface => null()
120
121 contains
123 procedure, pass(this) :: init => overset_interface_vector_init
125 procedure, pass(this) :: init_from_components => &
128 procedure, pass(this) :: free => overset_interface_vector_free
130 procedure, pass(this) :: finalize => overset_interface_vector_finalize
132 procedure, pass(this) :: apply_scalar => &
135 procedure, pass(this) :: apply_vector => &
138 procedure, pass(this) :: apply_vector_dev => &
141 procedure, pass(this) :: apply_scalar_dev => &
143 procedure, pass(this) :: update => overset_interface_update
145 procedure, pass(this) :: restart_vector => &
147
149 procedure, pass(this), private :: build_masks_ => build_masks_
151 procedure, pass(this), private :: gather_interface_dofs_ => &
154 procedure, pass(this), private :: setup_interpolator_ => &
157 procedure, pass(this), private :: log_interface_error_ => &
160 procedure, pass(this), private :: relax_interface_values_ => &
163
164contains
165
169 subroutine overset_interface_vector_init(this, coef, json)
170 class(overset_interface_vector_t), intent(inout), target :: this
171 type(coef_t), target, intent(in) :: coef
172 type(json_file), intent(inout) ::json
173 real(kind=rp) :: tol, pad, relaxation
174 logical :: log
175
177 call json_get_or_default(json, "interpolation.tolerance", &
178 tol, -1.0_rp)
179 call json_get_or_default(json, "interpolation.padding", &
180 pad, -1.0_rp)
181 call json_get_or_default(json, "order", this%iextm_order, 1)
182 if (this%iextm_order .lt. 1 .or. this%iextm_order .gt. 3) then
183 call neko_error("The order of the IEXTm time scheme must be 1 to 3.")
184 end if
185 call json_get_or_default(json, "relaxation", relaxation, 1.0_rp)
186 if (relaxation .le. 0.0_rp .or. relaxation .gt. 1.0_rp) then
187 call neko_error("The overset relaxation factor must be in (0, 1].")
188 end if
189 call json_get_or_default(json, "log", log, .false.)
190
191 call this%init_from_components(coef, tol, pad, log, relaxation)
192
193 end subroutine overset_interface_vector_init
194
202 pad, log, relaxation)
203 class(overset_interface_vector_t), intent(inout), target :: this
204 type(coef_t), intent(in) :: coef
205 real(kind=rp), intent(in), optional :: tol, pad, relaxation
206 logical, intent(in), optional :: log
207
209 call this%init_base(coef)
210
211 this%bc_type = bc_dirichlet
212 this%relaxation = 1.0_rp
213 this%last_tstep = -1
214 this%restart_pending = .false.
215
217 if (present(tol)) then
218 if (tol .gt. 0.0_rp) this%interpolation_settings%tolerance = tol
219 end if
220 if (present(pad)) then
221 if (pad .gt. 0.0_rp) this%interpolation_settings%padding = pad
222 end if
223 if (present(log)) then
224 this%log = log
225 end if
226 if (present(relaxation)) then
227 if (relaxation .le. 0.0_rp .or. relaxation .gt. 1.0_rp) then
228 call neko_error("The overset relaxation factor must be in (0, 1].")
229 end if
230 this%relaxation = relaxation
231 end if
232
233 call this%bc_u%init_from_components(coef, "u")
234 call this%bc_v%init_from_components(coef, "v")
235 call this%bc_w%init_from_components(coef, "w")
236
237 call this%field_list%init(3)
238 call this%field_list%assign_to_field(1, this%bc_u%field_bc)
239 call this%field_list%assign_to_field(2, this%bc_v%field_bc)
240 call this%field_list%assign_to_field(3, this%bc_w%field_bc)
241
243 call this%x_dof%init(this%dof%size(), 'x')
244 call this%y_dof%init(this%dof%size(), 'y')
245 call this%z_dof%init(this%dof%size(), 'z')
246
249 if (neko_bcknd_device .eq. 1) then
250 ! copy
251 call device_copy(this%x_dof%x_d, this%dof%x%x_d, this%dof%size())
252 call device_copy(this%y_dof%x_d, this%dof%y%x_d, this%dof%size())
253 call device_copy(this%z_dof%x_d, this%dof%z%x_d, this%dof%size())
254 ! synchronize
255 call this%x_dof%copy_from(device_to_host, sync = .false.)
256 call this%y_dof%copy_from(device_to_host, sync = .false.)
257 call this%z_dof%copy_from(device_to_host, sync = .true.)
258 else
259 call copy(this%x_dof%x, this%dof%x%x, this%dof%size())
260 call copy(this%y_dof%x, this%dof%y%x, this%dof%size())
261 call copy(this%z_dof%x, this%dof%z%x, this%dof%size())
262 end if
263
265
269 class(overset_interface_vector_t), target, intent(inout) :: this
270
271 call this%bc_u%free()
272 call this%bc_v%free()
273 call this%bc_w%free()
274
275 call this%field_list%free()
276 call this%interface_dof%free()
277 call this%interface_field%free()
278
279 call this%x_dof%free()
280 call this%y_dof%free()
281 call this%z_dof%free()
282
283 call this%x_interface_dof%free()
284 call this%y_interface_dof%free()
285 call this%z_interface_dof%free()
286 call this%u_interface%free()
287 call this%v_interface%free()
288 call this%w_interface%free()
289 call this%u_interface_lag%free()
290 call this%v_interface_lag%free()
291 call this%w_interface_lag%free()
292 call this%interface_interpolator%free()
293 call this%interface_dof_mask%free()
294 call this%domain_element_mask%free()
295 call this%free_base()
296
297 this%restart_pending = .false.
298
299 !if (associated(this%update_)) then
300 ! nullify(this%update_)
301 !end if
302 end subroutine overset_interface_vector_free
303
310 subroutine overset_interface_vector_restart(this, u, v, w, ulag, vlag, &
311 wlag)
312 class(overset_interface_vector_t), intent(inout) :: this
313 type(field_t), intent(in) :: u, v, w
314 type(field_series_t), intent(in) :: ulag, vlag, wlag
315 integer :: i, n_previous
316
317 call this%u_interface_lag%reset()
318 call this%v_interface_lag%reset()
319 call this%w_interface_lag%reset()
320
321 n_previous = min(this%iextm_order - 1, ulag%size())
322
323 ! Insert older snapshots in reverse field-series order. Each update moves
324 ! the previously gathered (older) snapshot into the lag series.
325 do i = n_previous, 1, -1
326 call vector_masked_gather_copy(this%u_interface, &
327 ulag%lf(i)%x(:,1,1,1), this%interface_dof_mask, &
328 ulag%lf(i)%dof%size())
329 call vector_masked_gather_copy(this%v_interface, &
330 vlag%lf(i)%x(:,1,1,1), this%interface_dof_mask, &
331 vlag%lf(i)%dof%size())
332 call vector_masked_gather_copy(this%w_interface, &
333 wlag%lf(i)%x(:,1,1,1), this%interface_dof_mask, &
334 wlag%lf(i)%dof%size())
335
336 call this%u_interface_lag%update()
337 call this%v_interface_lag%update()
338 call this%w_interface_lag%update()
339 end do
340
341 ! Keep the most recent accepted value in the base vectors. The first
342 ! regular update after restart will shift it into lag position one.
343 call vector_masked_gather_copy(this%u_interface, &
344 u%x(:,1,1,1), this%interface_dof_mask, u%dof%size())
345 call vector_masked_gather_copy(this%v_interface, &
346 v%x(:,1,1,1), this%interface_dof_mask, v%dof%size())
347 call vector_masked_gather_copy(this%w_interface, &
348 w%x(:,1,1,1), this%interface_dof_mask, w%dof%size())
349
350 this%restart_pending = .true.
352
357 subroutine overset_interface_vector_apply_scalar(this, x, n, time, strong)
358 class(overset_interface_vector_t), intent(inout) :: this
359 integer, intent(in) :: n
360 real(kind=rp), intent(inout), dimension(n) :: x
361 type(time_state_t), intent(in), optional :: time
362 logical, intent(in), optional :: strong
363
364 call neko_error("overset_interface_vector cannot apply scalar BCs.&
365 & Use overset_interface_vector::apply_vector instead!")
366
368
372 subroutine overset_interface_vector_apply_scalar_dev(this, x_d, time, &
373 strong, strm)
374 class(overset_interface_vector_t), intent(inout), target :: this
375 type(c_ptr), intent(inout) :: x_d
376 type(time_state_t), intent(in), optional :: time
377 logical, intent(in), optional :: strong
378 type(c_ptr), intent(inout) :: strm
379
380 call neko_error("overset_interface_vector cannot apply scalar BCs.&
381 & Use overset_interface_vector::apply_vector instead!")
382
384
391 subroutine overset_interface_vector_apply_vector(this, x, y, z, n, time, &
392 strong)
393 class(overset_interface_vector_t), intent(inout) :: this
394 integer, intent(in) :: n
395 real(kind=rp), intent(inout), dimension(n) :: x
396 real(kind=rp), intent(inout), dimension(n) :: y
397 real(kind=rp), intent(inout), dimension(n) :: z
398 type(time_state_t), intent(in), optional :: time
399 logical, intent(in), optional :: strong
400 logical :: strong_
401
402 if (present(strong)) then
403 strong_ = strong
404 else
405 strong_ = .true.
406 end if
407
408 if (strong_) then
409 call profiler_start_region('Overset vector apply')
410
411 ! We can send any of the 3 bcs we have as argument, since they are all
412 ! the same boundary.
413 !$omp single
414 if (.not. this%updated) then
415 call this%update(time)
416 this%updated = .true.
417 end if
418 !$omp end single
419
421 call masked_copy_0(x, this%bc_u%field_bc%x, this%msk, n, this%msk(0))
422 call masked_copy_0(y, this%bc_v%field_bc%x, this%msk, n, this%msk(0))
423 call masked_copy_0(z, this%bc_w%field_bc%x, this%msk, n, this%msk(0))
424 call profiler_end_region('Overset vector apply')
425 end if
426
428
435 subroutine overset_interface_vector_apply_vector_dev(this, x_d, y_d, z_d, &
436 time, strong, strm)
437 class(overset_interface_vector_t), intent(inout), target :: this
438 type(c_ptr), intent(inout) :: x_d
439 type(c_ptr), intent(inout) :: y_d
440 type(c_ptr), intent(inout) :: z_d
441 type(time_state_t), intent(in), optional :: time
442 logical, intent(in), optional :: strong
443 type(c_ptr), intent(inout) :: strm
444 logical :: strong_
445
446 if (present(strong)) then
447 strong_ = strong
448 else
449 strong_ = .true.
450 end if
451
452 if (strong_) then
453 call profiler_start_region('Overset vector apply')
454 !$omp single
455 if (.not. this%updated) then
456 call this%update(time)
457 this%updated = .true.
458 end if
459 !$omp end single
460
461 if (this%msk(0) .gt. 0) then
462 call device_masked_copy_0(x_d, this%bc_u%field_bc%x_d, &
463 this%bc_u%msk_d, this%bc_u%dof%size(), this%msk(0), &
464 strm) ! adperez: change the masks used here
465 call device_masked_copy_0(y_d, this%bc_v%field_bc%x_d, &
466 this%bc_v%msk_d, this%bc_v%dof%size(), this%msk(0), strm)
467 call device_masked_copy_0(z_d, this%bc_w%field_bc%x_d, &
468 this%bc_w%msk_d, this%bc_w%dof%size(), this%msk(0), strm)
469 end if
470 call profiler_end_region('Overset vector apply')
471 end if
472
474
477 class(overset_interface_vector_t), target, intent(inout) :: this
478
480 call this%finalize_base()
481
482 call this%bc_u%mark_facets(this%marked_facet)
483 call this%bc_v%mark_facets(this%marked_facet)
484 call this%bc_w%mark_facets(this%marked_facet)
485
486 call this%bc_u%finalize()
487 call this%bc_v%finalize()
488 call this%bc_w%finalize()
489
491 call this%build_masks_()
492
494 call this%x_interface_dof%init(this%interface_dof_mask%size(), &
495 'x_interface')
496 call this%y_interface_dof%init(this%interface_dof_mask%size(), &
497 'y_interface')
498 call this%z_interface_dof%init(this%interface_dof_mask%size(), &
499 'z_interface')
500 call this%gather_interface_dofs_()
501
503 call this%setup_interpolator_()
504
506 call this%u_interface%init(this%interface_dof_mask%size(), 'u_interface')
507 call this%v_interface%init(this%interface_dof_mask%size(), 'v_interface')
508 call this%w_interface%init(this%interface_dof_mask%size(), 'w_interface')
509
511 call this%interface_dof%init(3)
512 call this%interface_dof%assign_to_vector(1, this%x_interface_dof)
513 call this%interface_dof%assign_to_vector(2, this%y_interface_dof)
514 call this%interface_dof%assign_to_vector(3, this%z_interface_dof)
515
516 call this%interface_field%init(3)
517 call this%interface_field%assign_to_vector(1, this%u_interface)
518 call this%interface_field%assign_to_vector(2, this%v_interface)
519 call this%interface_field%assign_to_vector(3, this%w_interface)
520
522 call this%u_interface_lag%init(this%u_interface, this%iextm_order)
523 call this%v_interface_lag%init(this%v_interface, this%iextm_order)
524 call this%w_interface_lag%init(this%w_interface, this%iextm_order)
525
526 call mpi_allreduce(this%u_interface%size(), this%n_int_tot, 1, mpi_integer, &
527 mpi_sum, neko_global_comm)
528
529
531
533 subroutine overset_interface_update(this, time)
534 class(overset_interface_vector_t), intent(inout) :: this
535 type(time_state_t), intent(in) :: time
536 type(field_t), pointer :: u, v, w
537 type(iextm_time_scheme_t) :: time_scheme
538 integer :: nhist, ihist
539 real(kind=rp) :: iextm_coeffs(4)
540 logical :: new_tstep
541
542
543 call profiler_start_region('Overset vector update')
544
546 call this%morph_interface(this%interface_dof, this%interface_field, &
547 this%interface_dof_mask, time, this%name, &
548 this%find_interface)
549
551 ! not implemented for now
552 ! if (substep .eq. 1) then
553 ! call this%extrapolate()
554 ! end if
555
556 call profiler_start_region('Overset vector interp')
557
559 if (this%find_interface) then
560
561 ! sync
562 call this%x_interface_dof%copy_from(device_to_host, sync = .false.)
563 call this%y_interface_dof%copy_from(device_to_host, sync = .false.)
564 call this%z_interface_dof%copy_from(device_to_host, sync = .true.)
565
566 call this%interface_interpolator%find_points(this%x_interface_dof%x, &
567 this%y_interface_dof%x, this%z_interface_dof%x, &
568 this%x_interface_dof%size())
569 this%find_interface = .false.
570
571 end if
572
574 u => neko_registry%get_field("u")
575 v => neko_registry%get_field("v")
576 w => neko_registry%get_field("w")
577
578 ! The current accepted interface value is restored locally from the
579 ! checkpoint, so cross-domain interpolation is unnecessary once.
580 if (.not. this%restart_pending) then
581 call this%interface_interpolator%evaluate_masked(this%u_interface%x, &
582 u%x, this%domain_element_mask, .false.)
583 call this%interface_interpolator%evaluate_masked(this%v_interface%x, &
584 v%x, this%domain_element_mask, .false.)
585 call this%interface_interpolator%evaluate_masked(this%w_interface%x, &
586 w%x, this%domain_element_mask, .false.)
587 end if
588
589 call profiler_end_region('Overset vector interp')
590
591 if (.not. this%restart_pending) then
592 if (this%log) then
593 call this%log_interface_error_(u, v, w)
594 end if
595 end if
596
597
598 new_tstep = time%tstep .ne. this%last_tstep
599
601 if (new_tstep) then
602 call profiler_start_region('Overset vector extrap')
603 ! Update the last steps
604 this%last_tstep = time%tstep
605
606 ! Update the lag arrays with the value just got from the last step
607 call this%u_interface_lag%update()
608 call this%v_interface_lag%update()
609 call this%w_interface_lag%update()
610
611 ! Get the coefficients for the extrapolation
612 nhist = min(this%u_interface_lag%filled_size(), this%iextm_order)
613 call time_scheme%compute_coeffs(iextm_coeffs, &
614 real(time%dtlag, kind=rp), nhist)
615
616 ! Perform the extrapolation using the lag arrays
617 call vector_cmult2(this%u_interface, this%u_interface_lag%lv(1), &
618 iextm_coeffs(1))
619 call vector_cmult2(this%v_interface, this%v_interface_lag%lv(1), &
620 iextm_coeffs(1))
621 call vector_cmult2(this%w_interface, this%w_interface_lag%lv(1), &
622 iextm_coeffs(1))
623 do ihist = 2, nhist
624 call vector_add2s2(this%u_interface, &
625 this%u_interface_lag%lv(ihist), iextm_coeffs(ihist))
626 call vector_add2s2(this%v_interface, &
627 this%v_interface_lag%lv(ihist), iextm_coeffs(ihist))
628 call vector_add2s2(this%w_interface, &
629 this%w_interface_lag%lv(ihist), iextm_coeffs(ihist))
630 end do
631
632 this%restart_pending = .false.
633 call profiler_end_region('Overset vector extrap')
634
635 end if
636
637 ! Preserve the IEXT prediction on the first pass of every physical
638 ! timestep. Relax only subsequent Schwarz corrections at the same tstep.
639 if (.not. new_tstep) call this%relax_interface_values_()
640
642 call vector_masked_scatter_copy(this%bc_u%field_bc%x(:,1,1,1), &
643 this%u_interface, &
644 this%interface_dof_mask, this%bc_u%dof%size())
645 call vector_masked_scatter_copy(this%bc_v%field_bc%x(:,1,1,1), &
646 this%v_interface, &
647 this%interface_dof_mask, this%bc_v%dof%size())
648 call vector_masked_scatter_copy(this%bc_w%field_bc%x(:,1,1,1), &
649 this%w_interface, &
650 this%interface_dof_mask, this%bc_w%dof%size())
651
652 call profiler_end_region('Overset vector update')
653
654 end subroutine overset_interface_update
655
662 subroutine relax_interface_values_(this)
663 class(overset_interface_vector_t), intent(inout) :: this
664 type(vector_t), pointer :: previous
665 integer :: ind(1)
666 logical :: clear_scratch = .false.
667
668 ! A factor of one recovers the original, unrelaxed Schwarz iteration.
669 if (this%relaxation .ge. 1.0_rp) return
670
671 ! Reuse one scratch vector to hold the preceding iterate component.
672 call neko_scratch_registry%request_vector(previous, ind(1), &
673 this%u_interface%size(), clear_scratch)
674
675 ! Relax the new x-velocity donor data against the preceding iterate.
676 call vector_masked_gather_copy(previous, this%bc_u%field_bc%x(:,1,1,1), &
677 this%interface_dof_mask, this%bc_u%dof%size())
678 call vector_cmult(this%u_interface, this%relaxation)
679 call vector_add2s2(this%u_interface, previous, &
680 1.0_rp - this%relaxation)
681
682 ! Relax the new y-velocity donor data against the preceding iterate.
683 call vector_masked_gather_copy(previous, this%bc_v%field_bc%x(:,1,1,1), &
684 this%interface_dof_mask, this%bc_v%dof%size())
685 call vector_cmult(this%v_interface, this%relaxation)
686 call vector_add2s2(this%v_interface, previous, &
687 1.0_rp - this%relaxation)
688
689 ! Relax the new z-velocity donor data against the preceding iterate.
690 call vector_masked_gather_copy(previous, this%bc_w%field_bc%x(:,1,1,1), &
691 this%interface_dof_mask, this%bc_w%dof%size())
692 call vector_cmult(this%w_interface, this%relaxation)
693 call vector_add2s2(this%w_interface, previous, &
694 1.0_rp - this%relaxation)
695
696 ! Return the temporary storage to the scratch registry.
697 call neko_scratch_registry%relinquish(ind)
698
699 end subroutine relax_interface_values_
700
702 subroutine log_interface_error_(this, u, v, w)
703 class(overset_interface_vector_t), intent(inout) :: this
704 type(field_t), pointer, intent(in) :: u, v, w
705 real(kind=rp) :: u_int_norm, v_int_norm, w_int_norm
706 type(vector_t), pointer :: error
707 integer :: ind(1)
708 logical :: clear_scratch = .false.
709 character(len=256) :: log_buf
710
711 call neko_scratch_registry%request_vector(error, ind(1), this%u_interface%size(), &
712 clear_scratch)
713
715 call vector_masked_gather_copy(error, u%x(:,1,1,1), this%interface_dof_mask, &
716 this%dof%size())
717 call vector_add2s2(error, this%u_interface, -1.0_rp)
718 u_int_norm = sqrt(vector_glsc2(error, error)) / sqrt(real(this%n_int_tot, kind=rp))
719
720 call vector_masked_gather_copy(error, v%x(:,1,1,1), this%interface_dof_mask, &
721 this%dof%size())
722 call vector_add2s2(error, this%v_interface, -1.0_rp)
723 v_int_norm = sqrt(vector_glsc2(error, error)) / sqrt(real(this%n_int_tot, kind=rp))
724
725 call vector_masked_gather_copy(error, w%x(:,1,1,1), this%interface_dof_mask, &
726 this%dof%size())
727 call vector_add2s2(error, this%w_interface, -1.0_rp)
728 w_int_norm = sqrt(vector_glsc2(error, error)) / sqrt(real(this%n_int_tot, kind=rp))
729
730 call neko_scratch_registry%relinquish(ind)
731
733 write(log_buf, '(A12,A3,A10,1x,A1,E15.7,A1,E15.7,A1,E15.7,A1)') &
734 'Interface BC', ' | ', 'L2 Error: ', '(', &
735 u_int_norm, ',', v_int_norm, ',', w_int_norm, ')'
736 call neko_log%message(log_buf)
737
738 end subroutine log_interface_error_
739
740 !===================
741 ! Helper subroutines
742 !===================
743
745 subroutine build_masks_(this)
746 class(overset_interface_vector_t), intent(inout) :: this
747 type(mask_t) :: temp_mask
748 logical, allocatable :: found(:)
749 integer :: i, j, k, e, new_size, nelems
750 integer :: lx, ly, lz
751 integer :: nonlinear_idx(4), linear_idx
752 type(stack_i4_t) :: stack
753
755 call this%interface_dof_mask%init(this%msk(1:this%msk(0)), this%msk(0))
756
759 lx = this%Xh%lx
760 ly = this%Xh%ly
761 lz = this%Xh%lz
762 allocate(found(this%msh%nelv))
763 found = .false.
764 !! Find sem elements that contain the boundary points
765 do i = 1, this%msk(0)
766 linear_idx = this%msk(i)
767 nonlinear_idx = nonlinear_index(linear_idx, lx, ly, lz)
768 found(nonlinear_idx(4)) = .true.
769 end do
770 !! fill the stack containing the gll indices
771 nelems = 0
772 call stack%init()
773 do e = 1, this%msh%nelv
774 if (found(e)) then
775 nelems = nelems + 1
776 do k = 1, this%Xh%lz
777 do j = 1, this%Xh%ly
778 do i = 1, this%Xh%lx
779 linear_idx = linear_index(i, j, k, e, lx, ly, lz)
780 call stack%push(linear_idx)
781 end do
782 end do
783 end do
784 end if
785 end do
786 deallocate(found)
787 call temp_mask%init(stack%array(), stack%size())
788 call stack%free()
789
791 call this%domain_element_mask%invert_mask(temp_mask, this%dof%size())
792
793 call temp_mask%free()
794
795 end subroutine build_masks_
796
798 subroutine gather_interface_dofs_(this)
799 class(overset_interface_vector_t), intent(inout) :: this
800
802 call vector_masked_gather_copy(this%x_interface_dof, &
803 this%dof%x%x(:,1,1,1), &
804 this%interface_dof_mask, &
805 this%dof%size())
806 call vector_masked_gather_copy(this%y_interface_dof, &
807 this%dof%y%x(:,1,1,1), &
808 this%interface_dof_mask, &
809 this%dof%size())
810 call vector_masked_gather_copy(this%z_interface_dof, &
811 this%dof%z%x(:,1,1,1), &
812 this%interface_dof_mask, &
813 this%dof%size())
815 call this%x_interface_dof%copy_from(device_to_host, sync = .false.)
816 call this%y_interface_dof%copy_from(device_to_host, sync = .false.)
817 call this%z_interface_dof%copy_from(device_to_host, sync = .true.)
818
819 end subroutine gather_interface_dofs_
820
821
823 subroutine setup_interpolator_(this)
824 class(overset_interface_vector_t), intent(inout) :: this
825
827 call this%interface_interpolator%init(this%dof, &
829 tol=this%interpolation_settings%tolerance, &
830 pad=this%interpolation_settings%padding, &
831 mask=this%domain_element_mask)
832
834 call this%interface_interpolator%find_points(this%x_interface_dof%x, &
835 this%y_interface_dof%x, &
836 this%z_interface_dof%x, &
837 this%x_interface_dof%size())
838
839 end subroutine setup_interpolator_
840
__inline__ __device__ void nonlinear_index(const int idx, const int lx, int *index)
Definition bc_utils.h:44
double real
Abstract interface defining a dirichlet condition on a list of fields.
Retrieves a parameter by name or assigns a provided default value. In the latter case also adds the m...
User callback for overset-interface morphing and boundary-value updates.
Defines a list of bc_t.
Definition bc_list.f90:34
Defines a boundary condition.
Definition bc.f90:34
integer, parameter, public bc_dirichlet
Supported boundary condition types. The values are set in order of precedence for global resolution....
Definition bc.f90:67
Coefficients.
Definition coef.f90:34
Definition comm.F90:1
type(mpi_comm), public neko_global_comm
Definition comm.F90:47
subroutine, public device_copy(a_d, b_d, n, strm)
Copy a vector .
subroutine, public device_masked_copy_0(a_d, b_d, mask_d, n, n_mask, strm)
Copy a masked vector .
Device abstraction, common interface for various accelerators.
Definition device.F90:34
integer, parameter, public host_to_device
Definition device.F90:48
integer, parameter, public device_to_host
Definition device.F90:48
Defines a dirichlet boundary condition.
Definition dirichlet.f90:34
Defines a mapping of the degrees of freedom.
Definition dofmap.f90:35
Defines user dirichlet condition for a scalar field.
Contains the field_serties_t type.
Defines a field.
Definition field.f90:34
Implements global_interpolation given a dofmap.
Utilities for retrieving parameters from the case files.
Logging routines.
Definition log.f90:34
type(log_t), public neko_log
Global log stream.
Definition log.f90:92
integer, parameter, public log_size
Definition log.f90:46
Object for handling masks in Neko.
Definition mask.f90:34
Definition math.F90:60
subroutine, public copy(a, b, n)
Copy a vector .
Definition math.F90:305
subroutine, public masked_copy_0(a, b, mask, n, n_mask)
Copy a masked vector .
Definition math.F90:326
Build configurations.
integer, parameter neko_bcknd_device
integer, parameter, public rp
Global precision used in computations.
Definition num_types.f90:14
Defines overset interface vector boundary conditions.
subroutine relax_interface_values_(this)
Under-relax a Schwarz correction using the previously applied interface. For each velocity component,...
subroutine overset_interface_vector_init_from_components(this, coef, tol, pad, log, relaxation)
Constructor from components.
subroutine overset_interface_vector_apply_scalar_dev(this, x_d, time, strong, strm)
No-op apply scalar (device).
subroutine overset_interface_vector_free(this)
Destructor. Currently unused as is, all field_dirichlet attributes are freed in fluid_scheme_incompre...
subroutine overset_interface_vector_restart(this, u, v, w, ulag, vlag, wlag)
Restore interface history from checkpointed solution fields. Values are inserted from oldest to newes...
subroutine overset_interface_vector_apply_vector_dev(this, x_d, y_d, z_d, time, strong, strm)
Apply the boundary condition to a vector field on the device.
subroutine overset_interface_vector_apply_scalar(this, x, n, time, strong)
No-op apply scalar.
subroutine overset_interface_vector_finalize(this)
Finalize by building the mask arrays and propagating to underlying bcs.
subroutine overset_interface_vector_init(this, coef, json)
Constructor.
subroutine overset_interface_vector_apply_vector(this, x, y, z, n, time, strong)
Apply the boundary condition to a vector field.
Defines overset interface scalar boundary conditions.
subroutine overset_interface_update(this, time)
Update values at the overset interface.
subroutine gather_interface_dofs_(this)
Gather interface dofs.
subroutine log_interface_error_(this, s)
Log interface RMSE for the scalar field.
subroutine setup_interpolator_(this)
Set up the global interpolator.
subroutine build_masks_(this)
Build masks.
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
Defines a registry for storing solution fields.
Definition registry.f90:34
type(registry_t), target, public neko_registry
Global field registry.
Definition registry.f90:158
Defines a registry for storing and requesting temporary objects This can be used when you have a func...
type(scratch_registry_t), target, public neko_scratch_registry
Global scratch registry.
Implements a dynamic stack ADT.
Definition stack.f90:49
Base class for time integration schemes.
Module with things related to the simulation time.
Utilities.
Definition utils.f90:35
character(len=100) function, dimension(:), allocatable, public split_string(string, delimiter)
Split a string based on delimiter (tokenizer) OBS: very hacky, this should really be improved,...
Definition utils.f90:290
pure integer function, public linear_index(i, j, k, l, lx, ly, lz)
Compute the address of a (i,j,k,l) array with sizes (1:lx, 1:ly, 1:lz, :)
Definition utils.f90:328
subroutine, public vector_copy(a, b, n)
Copy a vector .
subroutine, public vector_cmult(a, c, n)
Multiplication by constant c .
subroutine, public vector_masked_gather_copy(a, b, mask, n)
Gather a vector to reduced contigous array .
real(kind=rp) function, public vector_glsc2(a, b, n)
subroutine, public vector_add2s2(a, b, c1, n)
Vector addition with scalar multiplication (multiplication on second argument)
subroutine, public vector_masked_scatter_copy(a, b, mask, n)
Scatter a contiguous vector into an array .
subroutine, public vector_cmult2(a, b, c, n)
Multiplication by constant c .
Contains the vector_series_t type.
Defines a vector.
Definition vector.f90:34
Base type for a boundary condition.
Definition bc.f90:73
A list of allocatable `bc_t`. Follows the standard interface of lists.
Definition bc_list.f90:49
Coefficients defined on a given (mesh, ) tuple. Arrays use indices (i,j,k,e): element e,...
Definition coef.f90:136
Generic Dirichlet boundary condition on .
Definition dirichlet.f90:49
User defined dirichlet condition, for which the user can work with an entire field....
field_list_t, To be able to group fields together
Stores a series (sequence) of fields, logically connected to a base field, and arranged according to ...
Implements the settings helper data container for global interpolation.
Implements global interpolation for arbitrary points in the domain.
Explicit interface extrapolation scheme for overset grids.
Type for consistently handling masks in Neko. This type encapsulates the mask array and its associate...
Definition mask.f90:51
Extension of the user defined dirichlet condition overset_interface
Integer based stack.
Definition stack.f90:77
A struct that contains all info about the time, expand as needed.
vector_list_t, To be able to group vectors together
Stores a series (sequence) of vectors, logically connected to a base vector, and arranged according t...