Skip to content

Commit d03ddb2

Browse files
committed
feat(amr): support acoustic sources under dynamic regrid - source support stays coarse (tags suppressed, candidate boxes clipped clear, internal assert); golden 2FC423D3
1 parent bb38235 commit d03ddb2

7 files changed

Lines changed: 314 additions & 13 deletions

File tree

src/simulation/m_acoustic_src.fpp

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,17 @@ module m_acoustic_src
1313
use m_variables_conversion
1414
use m_helper_basic
1515
use m_constants
16+
use m_mpi_common, only: s_mpi_allreduce_integer_min, s_mpi_allreduce_integer_max
1617

1718
implicit none
1819

19-
private; public :: s_initialize_acoustic_src, s_precalculate_acoustic_spatial_sources, s_acoustic_src_calculations
20+
private; public :: s_initialize_acoustic_src, s_precalculate_acoustic_spatial_sources, s_acoustic_src_calculations, &
21+
& acoustic_supp_lo, acoustic_supp_hi
2022

21-
integer, allocatable, dimension(:) :: pulse, support
23+
!> Global (level-0 index space) bounding box of each source's spatial support, reduced over ranks. The AMR dynamic regrid keeps
24+
!! fine blocks clear of these (the source acts on the coarse grid only). Allocated/filled only when amr with acoustic_source.
25+
integer, allocatable, dimension(:,:) :: acoustic_supp_lo, acoustic_supp_hi !< (1:3, 1:num_source)
26+
integer, allocatable, dimension(:) :: pulse, support
2227
$:GPU_DECLARE(create='[pulse, support]')
2328
2429
logical, allocatable, dimension(:) :: dipole
@@ -120,6 +125,9 @@ contains
120125
@:ALLOCATE(mom_src(1:num_vels, 0:m, 0:n, 0:p))
121126
@:ALLOCATE(E_src(0:m, 0:n, 0:p))
122127
128+
! host-only helper for the AMR regrid's source-exclusion clipping (filled by the precompute)
129+
if (amr) allocate (acoustic_supp_lo(1:3,1:num_source), acoustic_supp_hi(1:3,1:num_source))
130+
123131
end subroutine s_initialize_acoustic_src
124132

125133
!> Compute mass, momentum, and energy acoustic source terms and add to the RHS
@@ -394,6 +402,7 @@ contains
394402
integer :: j, k, l, ai
395403
integer :: count
396404
integer :: dim
405+
integer :: sidx_supp(3), lo_loc, hi_loc
397406
real(wp) :: source_spatial, angle, xyz_to_r_ratios(3)
398407
real(wp), parameter :: threshold = 1.e-10_wp
399408

@@ -472,6 +481,22 @@ contains
472481
& // 'the source acts on the coarse grid only - move the source or the block apart')
473482
end if
474483
end do
484+
485+
! global support bounding box (all ranks agree): the dynamic regrid suppresses tags
486+
! and clips candidate boxes against it so fine blocks never cover the source
487+
sidx_supp = 0
488+
sidx_supp(1) = start_idx(1)
489+
if (n_glb > 0) sidx_supp(2) = start_idx(2)
490+
if (p_glb > 0) sidx_supp(3) = start_idx(3)
491+
do j = 1, 3
492+
lo_loc = huge(1); hi_loc = -huge(1)
493+
do k = 1, count
494+
lo_loc = min(lo_loc, int(source_spatials(ai)%coord(j, k)) + sidx_supp(j))
495+
hi_loc = max(hi_loc, int(source_spatials(ai)%coord(j, k)) + sidx_supp(j))
496+
end do
497+
call s_mpi_allreduce_integer_min(lo_loc, acoustic_supp_lo(j, ai))
498+
call s_mpi_allreduce_integer_max(hi_loc, acoustic_supp_hi(j, ai))
499+
end do
475500
end if
476501

477502
if (count > 0) then

src/simulation/m_amr.fpp

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ module m_amr
2424
use m_ibm, only: s_ibm_alloc_fine, s_ibm_setup_fine, s_ibm_swap_to_fine, s_ibm_restore_from_fine, s_ibm_correct_state, &
2525
& s_update_mib, moving_immersed_boundary_flag, num_gps
2626
use m_hypoelastic, only: s_hypoelastic_update_fd_coeffs
27+
use m_acoustic_src, only: acoustic_supp_lo, acoustic_supp_hi
2728

2829
implicit none
2930

@@ -1391,6 +1392,62 @@ contains
13911392
!! amr_buf-padded extents come within buff_size (guaranteeing no fine-fine adjacency: separated boxes stay >= buff_size apart,
13921393
!! nearby ones collapse to a single box == the legacy bounding box). Boxes are the raw tagged extents; the caller pads, clamps
13931394
!! and size-caps each one.
1395+
!> True iff global level-0 cell (gi, gj, gk) lies inside any acoustic source support bbox.
1396+
pure logical function f_in_acoustic_support(gi, gj, gk) result(insup)
1397+
1398+
integer, intent(in) :: gi, gj, gk
1399+
integer :: s
1400+
1401+
insup = .false.
1402+
do s = 1, num_source
1403+
if (gi >= acoustic_supp_lo(1, s) .and. gi <= acoustic_supp_hi(1, s) .and. (n_glb == 0 .or. (gj >= acoustic_supp_lo(2, &
1404+
& s) .and. gj <= acoustic_supp_hi(2, s))) .and. (p_glb == 0 .or. (gk >= acoustic_supp_lo(3, &
1405+
& s) .and. gk <= acoustic_supp_hi(3, s)))) then
1406+
insup = .true.; return
1407+
end if
1408+
end do
1409+
1410+
end function f_in_acoustic_support
1411+
1412+
!> Clip a candidate regrid box (global indices) so it does not overlap any acoustic source support bbox: per overlapping source,
1413+
!! remove the overlap along the single axis/side that keeps the largest remaining extent (deterministic: lower axis, then begin
1414+
!! side, wins ties). Clipping only shrinks the box and may empty it (hi < lo); the caller drops empties.
1415+
impure subroutine s_amr_clip_box_from_sources(lo, hi)
1416+
1417+
integer, intent(inout) :: lo(3), hi(3)
1418+
integer :: s, d, best_d, best_side, best_ext, ext_l, ext_r
1419+
logical :: ovl
1420+
1421+
do s = 1, num_source
1422+
if (hi(1) < lo(1) .or. hi(2) < lo(2) .or. hi(3) < lo(3)) return ! emptied by an earlier clip
1423+
ovl = lo(1) <= acoustic_supp_hi(1, s) .and. hi(1) >= acoustic_supp_lo(1, s)
1424+
if (n_glb > 0) ovl = ovl .and. lo(2) <= acoustic_supp_hi(2, s) .and. hi(2) >= acoustic_supp_lo(2, s)
1425+
if (p_glb > 0) ovl = ovl .and. lo(3) <= acoustic_supp_hi(3, s) .and. hi(3) >= acoustic_supp_lo(3, s)
1426+
if (.not. ovl) cycle
1427+
best_d = 1; best_side = 1; best_ext = -1
1428+
do d = 1, num_dims
1429+
ext_l = acoustic_supp_lo(d, s) - lo(d) ! cells kept by [lo(d), supp_lo-1]
1430+
ext_r = hi(d) - acoustic_supp_hi(d, s) ! cells kept by [supp_hi+1, hi(d)]
1431+
if (ext_l > best_ext) then; best_ext = ext_l; best_d = d; best_side = 1; end if
1432+
if (ext_r > best_ext) then; best_ext = ext_r; best_d = d; best_side = 2; end if
1433+
end do
1434+
if (best_side == 1) then
1435+
hi(best_d) = acoustic_supp_lo(best_d, s) - 1
1436+
else
1437+
lo(best_d) = acoustic_supp_hi(best_d, s) + 1
1438+
end if
1439+
end do
1440+
! safety net: clipping removed every overlap by construction - anything left is a bug
1441+
do s = 1, num_source
1442+
if (hi(1) < lo(1) .or. hi(2) < lo(2) .or. hi(3) < lo(3)) return
1443+
ovl = lo(1) <= acoustic_supp_hi(1, s) .and. hi(1) >= acoustic_supp_lo(1, s)
1444+
if (n_glb > 0) ovl = ovl .and. lo(2) <= acoustic_supp_hi(2, s) .and. hi(2) >= acoustic_supp_lo(2, s)
1445+
if (p_glb > 0) ovl = ovl .and. lo(3) <= acoustic_supp_hi(3, s) .and. hi(3) >= acoustic_supp_lo(3, s)
1446+
if (ovl) call s_mpi_abort('amr regrid: acoustic source exclusion clip failed (internal error)')
1447+
end do
1448+
1449+
end subroutine s_amr_clip_box_from_sources
1450+
13941451
impure subroutine s_amr_cluster(tag_grid, boxes, nboxes)
13951452

13961453
logical, intent(in) :: tag_grid(0:,0:,0:)
@@ -1541,6 +1598,11 @@ contains
15411598
if (p_glb > 0) g = max(g, abs(f_amr_rho_tot(q_cons_base, ci, cj, ck + 1) - f_amr_rho_tot(q_cons_base, ci, &
15421599
& cj, ck - 1)))
15431600
if (g/(2._wp*r0) > amr_tag_eps) tag_grid(ci, cj, ck) = .true.
1601+
! the acoustic source support stays coarse (its spatials are coarse cell
1602+
! indices): suppress tags there so the clusterer splits around the source
1603+
if (acoustic_source .and. tag_grid(ci, cj, ck)) then
1604+
if (f_in_acoustic_support(ci + sidx(1), cj + sidx(2), ck + sidx(3))) tag_grid(ci, cj, ck) = .false.
1605+
end if
15441606
end do
15451607
end do
15461608
end do
@@ -1569,6 +1631,9 @@ contains
15691631
else
15701632
lo(3) = 0; hi(3) = 0
15711633
end if
1634+
! keep candidate boxes clear of every acoustic source support (the source acts on the
1635+
! coarse grid only); clipping only shrinks, so boxes stay disjoint - empties drop below
1636+
if (acoustic_source) call s_amr_clip_box_from_sources(lo, hi)
15721637
if (hi(1) < lo(1) .or. hi(2) < lo(2) .or. hi(3) < lo(3)) cycle ! confined to the domain margin
15731638
k = k + 1; boxes(k)%lo = lo; boxes(k)%hi = hi
15741639
end do

src/simulation/m_checker.fpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,9 @@ contains
117117
@:PROHIBIT(hybrid_weno, "amr is incompatible with hybrid_weno (unvalidated combination)")
118118
@:PROHIBIT(hybrid_riemann, "amr is incompatible with hybrid_riemann (unvalidated combination)")
119119
! acoustic sources act on the coarse grid only (their spatial support is precomputed as
120-
! coarse cell indices); a startup check aborts if the support overlaps the static block.
121-
! Dynamic regrid stays gated: new blocks could appear anywhere, including on the source.
122-
@:PROHIBIT(acoustic_source .and. amr_regrid_int > 0, &
123-
& "amr with acoustic_source requires a static block (amr_regrid_int = 0): the source support is precomputed on the coarse grid and must not overlap a fine block")
120+
! coarse cell indices). A startup check aborts if the support overlaps the user-placed
121+
! initial block; the dynamic regrid keeps its own boxes clear of the support (tags are
122+
! suppressed over it and candidate boxes are clipped), so the source region stays coarse.
124123
@:PROHIBIT(any(amr_block_beg(1:num_dims) < 0), "amr_block_beg must be >= 0")
125124
@:PROHIBIT(amr_block_end(1) > m_glb .or. (num_dims >= 2 .and. amr_block_end(2) > n_glb) .or. (num_dims >= 3 &
126125
& .and. amr_block_end(3) > p_glb), "amr_block_end must be <= global cell max per axis")

tests/2FC423D3/golden-metadata.txt

Lines changed: 193 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)