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
71 use time_state, only : time_state_t
72 use mpi_f08, only : mpi_allreduce, mpi_integer, mpi_sum
74 use logger, only : neko_log, log_size
75
76
77 implicit none
78 private
79
81 ! for the application on a vector field.
82 type, public, extends(bc_t) :: overset_interface_vector_t
83 ! The bc for the first compoent.
84 type(field_dirichlet_t) :: bc_u
85 ! The bc for the second compoent.
86 type(field_dirichlet_t) :: bc_v
87 ! The bc for the third compoent.
88 type(field_dirichlet_t) :: bc_w
92 type(global_interpolation_t) :: interface_interpolator
94 type(mask_t) :: interface_dof_mask
95 type(mask_t) :: domain_element_mask
97 type(vector_t) :: x_dof, y_dof, z_dof
98 type(vector_t) :: x_interface_dof, y_interface_dof, z_interface_dof
99 type(vector_t) :: u_interface, v_interface, w_interface
100 type(vector_series_t) :: u_interface_lag, v_interface_lag, w_interface_lag
101 integer :: iextm_order = 1
103 real(kind=rp) :: relaxation = 1.0_rp
104 integer :: last_tstep = -1
105 type(vector_list_t) :: interface_dof, interface_field
107 type(global_interpolation_settings_t) :: interpolation_settings
108 integer :: n_int_tot = 0
109 logical :: find_interface = .false.
110 logical :: setup = .false.
111 logical :: log = .false.
113 logical :: restart_pending = .false.
114
117 procedure(morph_overset_interface), nopass, pointer :: &
118 morph_interface => null()
119
120 contains
122 procedure, pass(this) :: init => overset_interface_vector_init
124 procedure, pass(this) :: init_from_components => &
127 procedure, pass(this) :: free => overset_interface_vector_free
129 procedure, pass(this) :: finalize => overset_interface_vector_finalize
131 procedure, pass(this) :: apply_scalar => &
134 procedure, pass(this) :: apply_vector => &
137 procedure, pass(this) :: apply_vector_dev => &
140 procedure, pass(this) :: apply_scalar_dev => &
142 procedure, pass(this) :: update => overset_interface_update
144 procedure, pass(this) :: restart_vector => &
146
148 procedure, pass(this), private :: build_masks_ => build_masks_
150 procedure, pass(this), private :: gather_interface_dofs_ => &
153 procedure, pass(this), private :: setup_interpolator_ => &
156 procedure, pass(this), private :: log_interface_error_ => &
159 procedure, pass(this), private :: relax_interface_values_ => &
162
163contains
164
168 subroutine overset_interface_vector_init(this, coef, json)
169 class(overset_interface_vector_t), intent(inout), target :: this
170 type(coef_t), target, intent(in) :: coef
171 type(json_file), intent(inout) ::json
172 real(kind=rp) :: tol, pad, relaxation
173 logical :: log
174
176 call json_get_or_default(json, "interpolation.tolerance", &
177 tol, -1.0_rp)
178 call json_get_or_default(json, "interpolation.padding", &
179 pad, -1.0_rp)
180 call json_get_or_default(json, "order", this%iextm_order, 1)
181 if (this%iextm_order .lt. 1 .or. this%iextm_order .gt. 3) then
182 call neko_error("The order of the IEXTm time scheme must be 1 to 3.")
183 end if
184 call json_get_or_default(json, "relaxation", relaxation, 1.0_rp)
185 if (relaxation .le. 0.0_rp .or. relaxation .gt. 1.0_rp) then
186 call neko_error("The overset relaxation factor must be in (0, 1].")
187 end if
188 call json_get_or_default(json, "log", log, .false.)
189
190 call this%init_from_components(coef, tol, pad, log, relaxation)
191
192 end subroutine overset_interface_vector_init
193
201 pad, log, relaxation)
202 class(overset_interface_vector_t), intent(inout), target :: this
203 type(coef_t), intent(in) :: coef
204 real(kind=rp), intent(in), optional :: tol, pad, relaxation
205 logical, intent(in), optional :: log
206
208 call this%init_base(coef)
209
210 this%bc_type = bc_dirichlet
211 this%relaxation = 1.0_rp
212 this%last_tstep = -1
213 this%restart_pending = .false.
214
216 if (present(tol)) then
217 if (tol .gt. 0.0_rp) this%interpolation_settings%tolerance = tol
218 end if
219 if (present(pad)) then
220 if (pad .gt. 0.0_rp) this%interpolation_settings%padding = pad
221 end if
222 if (present(log)) then
223 this%log = log
224 end if
225 if (present(relaxation)) then
226 if (relaxation .le. 0.0_rp .or. relaxation .gt. 1.0_rp) then
227 call neko_error("The overset relaxation factor must be in (0, 1].")
228 end if
229 this%relaxation = relaxation
230 end if
231
232 call this%bc_u%init_from_components(coef, "u")
233 call this%bc_v%init_from_components(coef, "v")
234 call this%bc_w%init_from_components(coef, "w")
235
236 call this%field_list%init(3)
237 call this%field_list%assign_to_field(1, this%bc_u%field_bc)
238 call this%field_list%assign_to_field(2, this%bc_v%field_bc)
239 call this%field_list%assign_to_field(3, this%bc_w%field_bc)
240
242 call this%x_dof%init(this%dof%size(), 'x')
243 call this%y_dof%init(this%dof%size(), 'y')
244 call this%z_dof%init(this%dof%size(), 'z')
245
248 if (neko_bcknd_device .eq. 1) then
249 ! copy
250 call device_copy(this%x_dof%x_d, this%dof%x%x_d, this%dof%size())
251 call device_copy(this%y_dof%x_d, this%dof%y%x_d, this%dof%size())
252 call device_copy(this%z_dof%x_d, this%dof%z%x_d, this%dof%size())
253 ! synchronize
254 call this%x_dof%copy_from(device_to_host, sync = .false.)
255 call this%y_dof%copy_from(device_to_host, sync = .false.)
256 call this%z_dof%copy_from(device_to_host, sync = .true.)
257 else
258 call copy(this%x_dof%x, this%dof%x%x, this%dof%size())
259 call copy(this%y_dof%x, this%dof%y%x, this%dof%size())
260 call copy(this%z_dof%x, this%dof%z%x, this%dof%size())
261 end if
262
264
268 class(overset_interface_vector_t), target, intent(inout) :: this
269
270 call this%bc_u%free()
271 call this%bc_v%free()
272 call this%bc_w%free()
273
274 call this%field_list%free()
275 call this%interface_dof%free()
276 call this%interface_field%free()
277
278 call this%x_dof%free()
279 call this%y_dof%free()
280 call this%z_dof%free()
281
282 call this%x_interface_dof%free()
283 call this%y_interface_dof%free()
284 call this%z_interface_dof%free()
285 call this%u_interface%free()
286 call this%v_interface%free()
287 call this%w_interface%free()
288 call this%u_interface_lag%free()
289 call this%v_interface_lag%free()
290 call this%w_interface_lag%free()
291 call this%interface_interpolator%free()
292 call this%interface_dof_mask%free()
293 call this%domain_element_mask%free()
294 call this%free_base()
295
296 this%restart_pending = .false.
297
298 !if (associated(this%update_)) then
299 ! nullify(this%update_)
300 !end if
301 end subroutine overset_interface_vector_free
302
309 subroutine overset_interface_vector_restart(this, u, v, w, ulag, vlag, &
310 wlag)
311 class(overset_interface_vector_t), intent(inout) :: this
312 type(field_t), intent(in) :: u, v, w
313 type(field_series_t), intent(in) :: ulag, vlag, wlag
314 integer :: i, n_previous
315
316 call this%u_interface_lag%reset()
317 call this%v_interface_lag%reset()
318 call this%w_interface_lag%reset()
319
320 n_previous = min(this%iextm_order - 1, ulag%size())
321
322 ! Insert older snapshots in reverse field-series order. Each update moves
323 ! the previously gathered (older) snapshot into the lag series.
324 do i = n_previous, 1, -1
325 call vector_masked_gather_copy(this%u_interface, &
326 ulag%lf(i)%x(:,1,1,1), this%interface_dof_mask, &
327 ulag%lf(i)%dof%size())
328 call vector_masked_gather_copy(this%v_interface, &
329 vlag%lf(i)%x(:,1,1,1), this%interface_dof_mask, &
330 vlag%lf(i)%dof%size())
331 call vector_masked_gather_copy(this%w_interface, &
332 wlag%lf(i)%x(:,1,1,1), this%interface_dof_mask, &
333 wlag%lf(i)%dof%size())
334
335 call this%u_interface_lag%update()
336 call this%v_interface_lag%update()
337 call this%w_interface_lag%update()
338 end do
339
340 ! Keep the most recent accepted value in the base vectors. The first
341 ! regular update after restart will shift it into lag position one.
342 call vector_masked_gather_copy(this%u_interface, &
343 u%x(:,1,1,1), this%interface_dof_mask, u%dof%size())
344 call vector_masked_gather_copy(this%v_interface, &
345 v%x(:,1,1,1), this%interface_dof_mask, v%dof%size())
346 call vector_masked_gather_copy(this%w_interface, &
347 w%x(:,1,1,1), this%interface_dof_mask, w%dof%size())
348
349 this%restart_pending = .true.
351
356 subroutine overset_interface_vector_apply_scalar(this, x, n, time, strong)
357 class(overset_interface_vector_t), intent(inout) :: this
358 integer, intent(in) :: n
359 real(kind=rp), intent(inout), dimension(n) :: x
360 type(time_state_t), intent(in), optional :: time
361 logical, intent(in), optional :: strong
362
363 call neko_error("overset_interface_vector cannot apply scalar BCs.&
364 & Use overset_interface_vector::apply_vector instead!")
365
367
371 subroutine overset_interface_vector_apply_scalar_dev(this, x_d, time, &
372 strong, strm)
373 class(overset_interface_vector_t), intent(inout), target :: this
374 type(c_ptr), intent(inout) :: x_d
375 type(time_state_t), intent(in), optional :: time
376 logical, intent(in), optional :: strong
377 type(c_ptr), intent(inout) :: strm
378
379 call neko_error("overset_interface_vector cannot apply scalar BCs.&
380 & Use overset_interface_vector::apply_vector instead!")
381
383
390 subroutine overset_interface_vector_apply_vector(this, x, y, z, n, time, &
391 strong)
392 class(overset_interface_vector_t), intent(inout) :: this
393 integer, intent(in) :: n
394 real(kind=rp), intent(inout), dimension(n) :: x
395 real(kind=rp), intent(inout), dimension(n) :: y
396 real(kind=rp), intent(inout), dimension(n) :: z
397 type(time_state_t), intent(in), optional :: time
398 logical, intent(in), optional :: strong
399 logical :: strong_
400
401 if (present(strong)) then
402 strong_ = strong
403 else
404 strong_ = .true.
405 end if
406
407 if (strong_) then
408
409 ! We can send any of the 3 bcs we have as argument, since they are all
410 ! the same boundary.
411 !$omp single
412 if (.not. this%updated) then
413 call this%update(time)
414 this%updated = .true.
415 end if
416 !$omp end single
417
419 call masked_copy_0(x, this%bc_u%field_bc%x, this%msk, n, this%msk(0))
420 call masked_copy_0(y, this%bc_v%field_bc%x, this%msk, n, this%msk(0))
421 call masked_copy_0(z, this%bc_w%field_bc%x, this%msk, n, this%msk(0))
422 end if
423
425
432 subroutine overset_interface_vector_apply_vector_dev(this, x_d, y_d, z_d, &
433 time, strong, strm)
434 class(overset_interface_vector_t), intent(inout), target :: this
435 type(c_ptr), intent(inout) :: x_d
436 type(c_ptr), intent(inout) :: y_d
437 type(c_ptr), intent(inout) :: z_d
438 type(time_state_t), intent(in), optional :: time
439 logical, intent(in), optional :: strong
440 type(c_ptr), intent(inout) :: strm
441 logical :: strong_
442
443 if (present(strong)) then
444 strong_ = strong
445 else
446 strong_ = .true.
447 end if
448
449 if (strong_) then
450 !$omp single
451 if (.not. this%updated) then
452 call this%update(time)
453 this%updated = .true.
454 end if
455 !$omp end single
456
457 if (this%msk(0) .gt. 0) then
458 call device_masked_copy_0(x_d, this%bc_u%field_bc%x_d, &
459 this%bc_u%msk_d, this%bc_u%dof%size(), this%msk(0), &
460 strm) ! adperez: change the masks used here
461 call device_masked_copy_0(y_d, this%bc_v%field_bc%x_d, &
462 this%bc_v%msk_d, this%bc_v%dof%size(), this%msk(0), strm)
463 call device_masked_copy_0(z_d, this%bc_w%field_bc%x_d, &
464 this%bc_w%msk_d, this%bc_w%dof%size(), this%msk(0), strm)
465 end if
466 end if
467
469
472 class(overset_interface_vector_t), target, intent(inout) :: this
473
475 call this%finalize_base()
476
477 call this%bc_u%mark_facets(this%marked_facet)
478 call this%bc_v%mark_facets(this%marked_facet)
479 call this%bc_w%mark_facets(this%marked_facet)
480
481 call this%bc_u%finalize()
482 call this%bc_v%finalize()
483 call this%bc_w%finalize()
484
486 call this%build_masks_()
487
489 call this%x_interface_dof%init(this%interface_dof_mask%size(), &
490 'x_interface')
491 call this%y_interface_dof%init(this%interface_dof_mask%size(), &
492 'y_interface')
493 call this%z_interface_dof%init(this%interface_dof_mask%size(), &
494 'z_interface')
495 call this%gather_interface_dofs_()
496
498 call this%setup_interpolator_()
499
501 call this%u_interface%init(this%interface_dof_mask%size(), 'u_interface')
502 call this%v_interface%init(this%interface_dof_mask%size(), 'v_interface')
503 call this%w_interface%init(this%interface_dof_mask%size(), 'w_interface')
504
506 call this%interface_dof%init(3)
507 call this%interface_dof%assign_to_vector(1, this%x_interface_dof)
508 call this%interface_dof%assign_to_vector(2, this%y_interface_dof)
509 call this%interface_dof%assign_to_vector(3, this%z_interface_dof)
510
511 call this%interface_field%init(3)
512 call this%interface_field%assign_to_vector(1, this%u_interface)
513 call this%interface_field%assign_to_vector(2, this%v_interface)
514 call this%interface_field%assign_to_vector(3, this%w_interface)
515
517 call this%u_interface_lag%init(this%u_interface, this%iextm_order)
518 call this%v_interface_lag%init(this%v_interface, this%iextm_order)
519 call this%w_interface_lag%init(this%w_interface, this%iextm_order)
520
521 call mpi_allreduce(this%u_interface%size(), this%n_int_tot, 1, mpi_integer, &
522 mpi_sum, neko_global_comm)
523
524
526
528 subroutine overset_interface_update(this, time)
529 class(overset_interface_vector_t), intent(inout) :: this
530 type(time_state_t), intent(in) :: time
531 type(field_t), pointer :: u, v, w
532 type(iextm_time_scheme_t) :: time_scheme
533 integer :: nhist, ihist
534 real(kind=rp) :: iextm_coeffs(4)
535 logical :: new_tstep
536
537
539 call this%morph_interface(this%interface_dof, this%interface_field, &
540 this%interface_dof_mask, time, this%name, &
541 this%find_interface)
542
544 ! not implemented for now
545 ! if (substep .eq. 1) then
546 ! call this%extrapolate()
547 ! end if
548
550 if (this%find_interface) then
551
552 ! sync
553 call this%x_interface_dof%copy_from(device_to_host, sync = .false.)
554 call this%y_interface_dof%copy_from(device_to_host, sync = .false.)
555 call this%z_interface_dof%copy_from(device_to_host, sync = .true.)
556
557 call this%interface_interpolator%find_points(this%x_interface_dof%x, &
558 this%y_interface_dof%x, this%z_interface_dof%x, &
559 this%x_interface_dof%size())
560 this%find_interface = .false.
561
562 end if
563
565 u => neko_registry%get_field("u")
566 v => neko_registry%get_field("v")
567 w => neko_registry%get_field("w")
568
569 ! The current accepted interface value is restored locally from the
570 ! checkpoint, so cross-domain interpolation is unnecessary once.
571 if (.not. this%restart_pending) then
572 call this%interface_interpolator%evaluate_masked(this%u_interface%x, &
573 u%x, this%domain_element_mask, .false.)
574 call this%interface_interpolator%evaluate_masked(this%v_interface%x, &
575 v%x, this%domain_element_mask, .false.)
576 call this%interface_interpolator%evaluate_masked(this%w_interface%x, &
577 w%x, this%domain_element_mask, .false.)
578
579 if (this%log) then
580 call this%log_interface_error_(u, v, w)
581 end if
582 end if
583
584
585 new_tstep = time%tstep .ne. this%last_tstep
586
588 if (new_tstep) then
589 ! Update the last steps
590 this%last_tstep = time%tstep
591
592 ! Update the lag arrays with the value just got from the last step
593 call this%u_interface_lag%update()
594 call this%v_interface_lag%update()
595 call this%w_interface_lag%update()
596
597 ! Get the coefficients for the extrapolation
598 nhist = min(this%u_interface_lag%filled_size(), this%iextm_order)
599 call time_scheme%compute_coeffs(iextm_coeffs, &
600 real(time%dtlag, kind=rp), nhist)
601
602 ! Perform the extrapolation using the lag arrays
603 call vector_cmult2(this%u_interface, this%u_interface_lag%lv(1), &
604 iextm_coeffs(1))
605 call vector_cmult2(this%v_interface, this%v_interface_lag%lv(1), &
606 iextm_coeffs(1))
607 call vector_cmult2(this%w_interface, this%w_interface_lag%lv(1), &
608 iextm_coeffs(1))
609 do ihist = 2, nhist
610 call vector_add2s2(this%u_interface, &
611 this%u_interface_lag%lv(ihist), iextm_coeffs(ihist))
612 call vector_add2s2(this%v_interface, &
613 this%v_interface_lag%lv(ihist), iextm_coeffs(ihist))
614 call vector_add2s2(this%w_interface, &
615 this%w_interface_lag%lv(ihist), iextm_coeffs(ihist))
616 end do
617
618 this%restart_pending = .false.
619
620 end if
621
622 ! Preserve the IEXT prediction on the first pass of every physical
623 ! timestep. Relax only subsequent Schwarz corrections at the same tstep.
624 if (.not. new_tstep) call this%relax_interface_values_()
625
627 call vector_masked_scatter_copy(this%bc_u%field_bc%x(:,1,1,1), &
628 this%u_interface, &
629 this%interface_dof_mask, this%bc_u%dof%size())
630 call vector_masked_scatter_copy(this%bc_v%field_bc%x(:,1,1,1), &
631 this%v_interface, &
632 this%interface_dof_mask, this%bc_v%dof%size())
633 call vector_masked_scatter_copy(this%bc_w%field_bc%x(:,1,1,1), &
634 this%w_interface, &
635 this%interface_dof_mask, this%bc_w%dof%size())
636
637
638 end subroutine overset_interface_update
639
646 subroutine relax_interface_values_(this)
647 class(overset_interface_vector_t), intent(inout) :: this
648 type(vector_t), pointer :: previous
649 integer :: ind(1)
650 logical :: clear_scratch = .false.
651
652 ! A factor of one recovers the original, unrelaxed Schwarz iteration.
653 if (this%relaxation .ge. 1.0_rp) return
654
655 ! Reuse one scratch vector to hold the preceding iterate component.
656 call neko_scratch_registry%request_vector(previous, ind(1), &
657 this%u_interface%size(), clear_scratch)
658
659 ! Relax the new x-velocity donor data against the preceding iterate.
660 call vector_masked_gather_copy(previous, this%bc_u%field_bc%x(:,1,1,1), &
661 this%interface_dof_mask, this%bc_u%dof%size())
662 call vector_cmult(this%u_interface, this%relaxation)
663 call vector_add2s2(this%u_interface, previous, &
664 1.0_rp - this%relaxation)
665
666 ! Relax the new y-velocity donor data against the preceding iterate.
667 call vector_masked_gather_copy(previous, this%bc_v%field_bc%x(:,1,1,1), &
668 this%interface_dof_mask, this%bc_v%dof%size())
669 call vector_cmult(this%v_interface, this%relaxation)
670 call vector_add2s2(this%v_interface, previous, &
671 1.0_rp - this%relaxation)
672
673 ! Relax the new z-velocity donor data against the preceding iterate.
674 call vector_masked_gather_copy(previous, this%bc_w%field_bc%x(:,1,1,1), &
675 this%interface_dof_mask, this%bc_w%dof%size())
676 call vector_cmult(this%w_interface, this%relaxation)
677 call vector_add2s2(this%w_interface, previous, &
678 1.0_rp - this%relaxation)
679
680 ! Return the temporary storage to the scratch registry.
681 call neko_scratch_registry%relinquish(ind)
682
683 end subroutine relax_interface_values_
684
686 subroutine log_interface_error_(this, u, v, w)
687 class(overset_interface_vector_t), intent(inout) :: this
688 type(field_t), pointer, intent(in) :: u, v, w
689 real(kind=rp) :: u_int_norm, v_int_norm, w_int_norm
690 type(vector_t), pointer :: error
691 integer :: ind(1)
692 logical :: clear_scratch = .false.
693 character(len=256) :: log_buf
694
695 call neko_scratch_registry%request_vector(error, ind(1), this%u_interface%size(), &
696 clear_scratch)
697
699 call vector_masked_gather_copy(error, u%x(:,1,1,1), this%interface_dof_mask, &
700 this%dof%size())
701 call vector_add2s2(error, this%u_interface, -1.0_rp)
702 u_int_norm = sqrt(vector_glsc2(error, error)) / sqrt(real(this%n_int_tot, kind=rp))
703
704 call vector_masked_gather_copy(error, v%x(:,1,1,1), this%interface_dof_mask, &
705 this%dof%size())
706 call vector_add2s2(error, this%v_interface, -1.0_rp)
707 v_int_norm = sqrt(vector_glsc2(error, error)) / sqrt(real(this%n_int_tot, kind=rp))
708
709 call vector_masked_gather_copy(error, w%x(:,1,1,1), this%interface_dof_mask, &
710 this%dof%size())
711 call vector_add2s2(error, this%w_interface, -1.0_rp)
712 w_int_norm = sqrt(vector_glsc2(error, error)) / sqrt(real(this%n_int_tot, kind=rp))
713
714 call neko_scratch_registry%relinquish(ind)
715
717 write(log_buf, '(A12,A3,A10,1x,A1,E15.7,A1,E15.7,A1,E15.7,A1)') &
718 'Interface BC', ' | ', 'L2 Error: ', '(', &
719 u_int_norm, ',', v_int_norm, ',', w_int_norm, ')'
720 call neko_log%message(log_buf)
721
722 end subroutine log_interface_error_
723
724 !===================
725 ! Helper subroutines
726 !===================
727
729 subroutine build_masks_(this)
730 class(overset_interface_vector_t), intent(inout) :: this
731 type(mask_t) :: temp_mask
732 logical, allocatable :: found(:)
733 integer :: i, j, k, e, new_size, nelems
734 integer :: lx, ly, lz
735 integer :: nonlinear_idx(4), linear_idx
736 type(stack_i4_t) :: stack
737
739 call this%interface_dof_mask%init(this%msk(1:this%msk(0)), this%msk(0))
740
743 lx = this%Xh%lx
744 ly = this%Xh%ly
745 lz = this%Xh%lz
746 allocate(found(this%msh%nelv))
747 found = .false.
748 !! Find sem elements that contain the boundary points
749 do i = 1, this%msk(0)
750 linear_idx = this%msk(i)
751 nonlinear_idx = nonlinear_index(linear_idx, lx, ly, lz)
752 found(nonlinear_idx(4)) = .true.
753 end do
754 !! fill the stack containing the gll indices
755 nelems = 0
756 call stack%init()
757 do e = 1, this%msh%nelv
758 if (found(e)) then
759 nelems = nelems + 1
760 do k = 1, this%Xh%lz
761 do j = 1, this%Xh%ly
762 do i = 1, this%Xh%lx
763 linear_idx = linear_index(i, j, k, e, lx, ly, lz)
764 call stack%push(linear_idx)
765 end do
766 end do
767 end do
768 end if
769 end do
770 deallocate(found)
771 call temp_mask%init(stack%array(), stack%size())
772 call stack%free()
773
775 call this%domain_element_mask%invert_mask(temp_mask, this%dof%size())
776
777 call temp_mask%free()
778
779 end subroutine build_masks_
780
782 subroutine gather_interface_dofs_(this)
783 class(overset_interface_vector_t), intent(inout) :: this
784
786 call vector_masked_gather_copy(this%x_interface_dof, &
787 this%dof%x%x(:,1,1,1), &
788 this%interface_dof_mask, &
789 this%dof%size())
790 call vector_masked_gather_copy(this%y_interface_dof, &
791 this%dof%y%x(:,1,1,1), &
792 this%interface_dof_mask, &
793 this%dof%size())
794 call vector_masked_gather_copy(this%z_interface_dof, &
795 this%dof%z%x(:,1,1,1), &
796 this%interface_dof_mask, &
797 this%dof%size())
799 call this%x_interface_dof%copy_from(device_to_host, sync = .false.)
800 call this%y_interface_dof%copy_from(device_to_host, sync = .false.)
801 call this%z_interface_dof%copy_from(device_to_host, sync = .true.)
802
803 end subroutine gather_interface_dofs_
804
805
807 subroutine setup_interpolator_(this)
808 class(overset_interface_vector_t), intent(inout) :: this
809
811 call this%interface_interpolator%init(this%dof, &
813 tol=this%interpolation_settings%tolerance, &
814 pad=this%interpolation_settings%padding, &
815 mask=this%domain_element_mask)
816
818 call this%interface_interpolator%find_points(this%x_interface_dof%x, &
819 this%y_interface_dof%x, &
820 this%z_interface_dof%x, &
821 this%x_interface_dof%size())
822
823 end subroutine setup_interpolator_
824
__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:91
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:295
subroutine, public masked_copy_0(a, b, mask, n, n_mask)
Copy a masked vector .
Definition math.f90:316
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.
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:288
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:326
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:135
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...