@@ -887,16 +887,22 @@ contains
887887
888888 if (model_eqns == 3 ) call s_initialize_internal_energy_equations(q_cons_ts(1 )%vf)
889889 if (ib) then
890- if (cfl_dt .and. n_start > 0 ) then
891- call s_read_ib_restart_data(n_start)
892- else if (t_step_start > 0 ) then
893- call s_read_ib_restart_data(t_step_start)
894- else
895- ! particle bed generated on first time step
896- call s_generate_particle_beds()
897- end if
898- call s_instantiate_STL_models()
899- call s_reduce_ib_patch_array()
890+ block
891+ type(ib_patch_parameters), allocatable :: particle_bed_ibs(:)
892+
893+ if (cfl_dt .and. n_start > 0 ) then
894+ call s_read_ib_restart_data(n_start)
895+ allocate (particle_bed_ibs(0 ))
896+ else if (t_step_start > 0 ) then
897+ call s_read_ib_restart_data(t_step_start)
898+ allocate (particle_bed_ibs(0 ))
899+ else
900+ call s_generate_particle_beds(particle_bed_ibs)
901+ end if
902+ call s_instantiate_STL_models()
903+ call s_reduce_ib_patch_array(particle_bed_ibs)
904+ deallocate (particle_bed_ibs)
905+ end block
900906 call s_ibm_setup()
901907 if (t_step_start == 0 .or. (cfl_dt .and. n_start == 0 )) then
902908 call s_write_ib_data_file(0 )
@@ -1169,80 +1175,103 @@ contains
11691175
11701176 end subroutine s_read_ib_restart_data
11711177
1172- !> @brief takes the patch_ib struct array that contains all global IB patches and reduces to only contain patches that are in
1173- !! the local computational domain.
1174- subroutine s_reduce_ib_patch_array ()
1178+ !> @brief Merges patch_ib (namelist patches, fixed at num_ib_patches_max_namelist) with particle_bed_ibs (CPU- only, exact size)
1179+ !! and reduces to only the patches in or near the local computational domain. patch_ib is never reallocated; the local subset is
1180+ !! written in - place from the front. particle_bed_ibs is owned by the caller and freed there after this returns.
1181+ subroutine s_reduce_ib_patch_array (particle_bed_ibs )
11751182
1176- type(ib_patch_parameters), allocatable :: patch_ib_gbl(:)
1177- real (wp), dimension (3 ) :: centroid
1178- integer :: i, j
1179- integer :: num_aware_ibs
1180- logical :: is_in_neighborhood, is_local
1183+ type(ib_patch_parameters), intent (in ), dimension (:) :: particle_bed_ibs
1184+ real (wp), dimension (3 ) :: centroid
1185+ integer :: i
1186+ integer :: num_namelist_ibs, num_bed_ibs
11811187
1182- ! do all set up for moving immersed boundaries
1188+ num_namelist_ibs = num_ibs
1189+ num_bed_ibs = size (particle_bed_ibs)
11831190
1191+ ! Check for moving IBs across both namelist and particle bed patches.
11841192 moving_immersed_boundary_flag = .false.
1185- do i = 1 , num_ibs
1193+ do i = 1 , num_namelist_ibs
11861194 if (patch_ib(i)%moving_ibm /= 0 ) then
11871195 moving_immersed_boundary_flag = .true.
11881196 exit
11891197 end if
11901198 end do
1199+ if (.not. moving_immersed_boundary_flag) then
1200+ do i = 1 , num_bed_ibs
1201+ if (particle_bed_ibs(i)%moving_ibm /= 0 ) then
1202+ moving_immersed_boundary_flag = .true.
1203+ exit
1204+ end if
1205+ end do
1206+ end if
11911207
1192- allocate (patch_ib_gbl(num_ibs))
1193- patch_ib_gbl(1 :num_ibs) = patch_ib(1 :num_ibs)
1194- call get_neighbor_bounds() ! make sure the bounds of the neighbors are correctly set up
1195- call s_compute_ib_neighbor_ranks() ! build lookup of all neighbor MPI ranks
1196-
1197- num_gbl_ibs = num_ibs
1198- num_local_ibs = num_ibs
1199- @:PROHIBIT(num_local_ibs > num_local_ibs_max, &
1200- & " Too many IBs on a single processor rank. Modify case file or increase limit of num_local_ibs_max to resolve." )
1201- do i = 1 , num_local_ibs_max
1202- local_ib_patch_ids(i) = i
1203- end do
1208+ call get_neighbor_bounds()
1209+ call s_compute_ib_neighbor_ranks()
12041210
1205- $:GPU_EXIT_DATA(delete= ' [patch_ib]' )
1206- deallocate (patch_ib)
1211+ num_gbl_ibs = num_namelist_ibs + num_bed_ibs
12071212
12081213#ifdef MFC_MPI
12091214 if (num_procs == 1 ) then
1210- ! single- rank: every patch is local; allocate to exact size and copy
1211- allocate (patch_ib(num_gbl_ibs))
1212- patch_ib(1 :num_gbl_ibs) = patch_ib_gbl(1 :num_gbl_ibs)
1213- deallocate (patch_ib_gbl)
1215+ ! single- rank: all patches are local; append particle bed entries directly into patch_ib.
1216+ @:PROHIBIT(num_gbl_ibs > num_ib_patches_max_namelist, &
1217+ & " Total IB count exceeds patch_ib capacity. Increase num_ib_patches_max_namelist." )
1218+ do i = 1 , num_bed_ibs
1219+ patch_ib(num_namelist_ibs + i) = particle_bed_ibs(i)
1220+ patch_ib(num_namelist_ibs + i)%gbl_patch_id = num_namelist_ibs + i
1221+ end do
1222+ num_ibs = num_gbl_ibs
1223+ num_local_ibs = num_gbl_ibs
1224+ do i = 1 , num_gbl_ibs
1225+ local_ib_patch_ids(i) = i
1226+ end do
12141227 else
1215- ! multi- rank: carve out the local neighbourhood subset
1216- num_aware_ibs = min (num_local_ibs_max* (2 * ib_neighborhood_radius + 1 )** num_dims, num_ib_patches_max)
1217- allocate (patch_ib(num_aware_ibs))
1218-
1219- num_local_ibs = 0
1228+ ! multi- rank: compact namelist patches in - place (write_idx <= read_idx, no aliasing), then append local particle beds.
12201229 num_ibs = 0
1221- do i = 1 , num_gbl_ibs
1222- ! catch the edge case where th collision lies just outside the computational domain
1223- is_in_neighborhood = .true.
1224- is_local = .true.
1225- centroid = [patch_ib_gbl(i)%x_centroid, patch_ib_gbl(i)%y_centroid, 0._wp ]
1226- if (num_dims == 3 ) centroid(3 ) = patch_ib_gbl(i)%z_centroid
1227-
1230+ num_local_ibs = 0
1231+ do i = 1 , num_namelist_ibs
1232+ centroid = [patch_ib(i)%x_centroid, patch_ib(i)%y_centroid, 0._wp ]
1233+ if (num_dims == 3 ) centroid(3 ) = patch_ib(i)%z_centroid
12281234 if (f_neighborhood_ranks_own_location(centroid)) then
12291235 num_ibs = num_ibs + 1
1230- patch_ib(num_ibs) = patch_ib_gbl (i)
1236+ patch_ib(num_ibs) = patch_ib (i)
12311237 patch_ib(num_ibs)%gbl_patch_id = i
12321238 if (f_local_rank_owns_location(centroid)) then
12331239 num_local_ibs = num_local_ibs + 1
12341240 local_ib_patch_ids(num_local_ibs) = num_ibs
12351241 end if
12361242 end if
12371243 end do
1238-
1239- deallocate (patch_ib_gbl)
1244+ do i = 1 , num_bed_ibs
1245+ centroid = [particle_bed_ibs(i)%x_centroid, particle_bed_ibs(i)%y_centroid, 0._wp ]
1246+ if (num_dims == 3 ) centroid(3 ) = particle_bed_ibs(i)%z_centroid
1247+ if (f_neighborhood_ranks_own_location(centroid)) then
1248+ num_ibs = num_ibs + 1
1249+ @:PROHIBIT(num_ibs > num_ib_patches_max_namelist, &
1250+ & " Local IB count exceeds patch_ib capacity. Increase num_ib_patches_max_namelist." )
1251+ patch_ib(num_ibs) = particle_bed_ibs(i)
1252+ patch_ib(num_ibs)%gbl_patch_id = num_namelist_ibs + i
1253+ if (f_local_rank_owns_location(centroid)) then
1254+ num_local_ibs = num_local_ibs + 1
1255+ local_ib_patch_ids(num_local_ibs) = num_ibs
1256+ end if
1257+ end if
1258+ end do
1259+ @:PROHIBIT(num_local_ibs > num_local_ibs_max, &
1260+ & " Too many IBs on a single processor rank. Modify case file or increase limit of num_local_ibs_max to resolve." )
12401261 end if
12411262#else
1242- ! no- MPI: every patch is local; allocate to exact size and copy
1243- allocate (patch_ib(num_gbl_ibs))
1244- patch_ib(1 :num_gbl_ibs) = patch_ib_gbl(1 :num_gbl_ibs)
1245- deallocate (patch_ib_gbl)
1263+ ! no- MPI: all patches are local; append particle bed entries directly into patch_ib.
1264+ @:PROHIBIT(num_gbl_ibs > num_ib_patches_max_namelist, &
1265+ & " Total IB count exceeds patch_ib capacity. Increase num_ib_patches_max_namelist." )
1266+ do i = 1 , num_bed_ibs
1267+ patch_ib(num_namelist_ibs + i) = particle_bed_ibs(i)
1268+ patch_ib(num_namelist_ibs + i)%gbl_patch_id = num_namelist_ibs + i
1269+ end do
1270+ num_ibs = num_gbl_ibs
1271+ num_local_ibs = num_gbl_ibs
1272+ do i = 1 , num_gbl_ibs
1273+ local_ib_patch_ids(i) = i
1274+ end do
12461275#endif
12471276
12481277 $:GPU_ENTER_DATA(create= ' [patch_ib]' )
0 commit comments