Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/documentation/case.md
Original file line number Diff line number Diff line change
Expand Up @@ -431,13 +431,14 @@ A particle cloud is a compact specification of a bed of identical circular (2D)
| `cloud_geometry` | Integer | Shape of the cloud region. |
| `shell_inner_radius` | Real | Inner radius for hemisphere-shell clouds (`cloud_geometry = 2`). |
| `shell_outer_radius` | Real | Outer radius for hemisphere-shell clouds (`cloud_geometry = 2`). |
| `shell_axis` | Integer | Axis the hemisphere-shell cloud opens toward (`cloud_geometry = 2`). |
| `moving_ibm` | Integer | Motion flag applied to every particle (see `patch_ib(j)%%moving_ibm`). |
| `seed` | Integer | Random seed for reproducible placement (used by `packing_method = 1`). |
| `packing_method` | Integer | Algorithm used to place the particles. |

- `cloud_geometry` selects the cloud region:
- `1` (box) uses `x[y,z]_centroid` and `length_x[y,z]` to define the region.
- `2` uses `x[y,z]_centroid`, `shell_inner_radius`, and `shell_outer_radius` to define a half-annulus in 2D and a hemisphere shell in 3D. Particle centres are sampled between `shell_inner_radius + radius` and `shell_outer_radius - radius`, and the flat plane is kept clear by one particle radius. The flat face is fixed at `y_centroid` in 2D and `z_centroid` in 3D; the filled region opens toward positive `y` in 2D and positive `z` in 3D. The full shell extent (`x[y,z]_centroid +/- shell_outer_radius` on the open side, and one particle radius of clearance on the flat-face side) must lie inside the computational domain; a hemisphere shell also requires at least two dimensions (`n > 0`).
- `2` uses `x[y,z]_centroid`, `shell_inner_radius`, `shell_outer_radius`, and `shell_axis` to define a half-annulus in 2D and a hemisphere shell in 3D. Particle centres are sampled between `shell_inner_radius + radius` and `shell_outer_radius - radius`, and the flat plane is kept clear by one particle radius. `shell_axis` (`1`=x, `2`=y, `3`=z; default `3`) selects which axis the shell opens toward from its flat face at that axis's centroid; in 2D there is no z-axis, so any value other than `1` opens toward `+y` (matching the fixed behavior before `shell_axis` existed). The open axis needs one particle radius of clearance on its flat-face side and the full `shell_outer_radius` on its open side; the other axis (2D) or two axes (3D) need the full shell extent (`centroid +/- shell_outer_radius`) inside the domain. A hemisphere shell also requires at least two dimensions (`n > 0`).
- `packing_method` selects how the `num_particles` are positioned within the cloud region:
- `1` (rejection sampling) draws random positions and rejects any that violate `min_spacing`, producing a disordered bed. `seed` makes the placement reproducible.
- `2` (lattice) places the particles on the optimally dense lattice for the geometry — a triangular lattice in 2D and a face-centered cubic lattice in 3D. The lattice spacing is derived from the particle density (`num_particles` over the region area/volume); if that spacing is below the required `2*radius + min_spacing`, the region is too dense and the run aborts.
Expand Down
4 changes: 2 additions & 2 deletions src/common/m_constants.fpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ module m_constants
integer, parameter :: num_stl_models_max = 10
!> Maximum number of immersed boundary patches (legacy, not used for patch_ib sizing)
!> Fixed capacity of patch_ib (namelist patches + local particle bed subset after reduction)
integer, parameter :: num_local_ibs_max = 2000 !< Maximum number of immersed boundary patches (patch_ib)
integer, parameter :: num_ib_patches_max_namelist = 54000
integer, parameter :: num_local_ibs_max = 8000 !< Maximum number of immersed boundary patches (patch_ib)
integer, parameter :: num_ib_patches_max_namelist = 216000
integer, parameter :: num_particle_clouds_max = 10 !< Maximum number of particle bed patch specifications
integer, parameter :: num_bc_patches_max = 10 !< Maximum number of boundary condition patches
integer, parameter :: max_2d_fourier_modes = 10 !< Max Fourier mode index for 2D modal patch (geometry 13)
Expand Down
1 change: 1 addition & 0 deletions src/common/m_derived_types.fpp
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,7 @@ module m_derived_types
integer :: moving_ibm !< Motion flag: 0=static, 1=moving (forces), 2=forced path
integer :: seed !< Random seed for reproducible placement
integer :: cloud_geometry !< Cloud region geometry: 1=box, 2=hemisphere shell
integer :: shell_axis !< Axis the hemisphere shell opens toward: 1=x, 2=y, 3=z (2D ignores 3)
integer :: packing_method !< Packing algorithm: 1=rejection sampling, 2=lattice
integer :: periodic !< Periodic overlap flag for box rejection packing: 0=off, 1=on
end type particle_cloud_parameters
Expand Down
13 changes: 9 additions & 4 deletions src/common/m_finite_differences.fpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,17 @@ contains
real(wp), dimension(-local_buff_size:q + local_buff_size), intent(in) :: s_cc
integer :: i !< Generic loop iterator

! Coefficients always extend at least fd_number_in beyond the interior on each side, so a stencil centered on a
! ghost-adjacent cell (e.g. an immersed boundary near a domain boundary) has a real coefficient to read instead of
! reading past the caller's allocation. offset_s, when given, widens this further (never narrows it) for callers
! that need more than fd_number_in of margin.

if (present(offset_s)) then
lB = -offset_s%beg
lE = q + offset_s%end
lB = -max(fd_number_in, offset_s%beg)
lE = q + max(fd_number_in, offset_s%end)
else
lB = 0
lE = q
lB = -fd_number_in
lE = q + fd_number_in
end if

! Computing the 1st order finite-difference coefficients
Expand Down
10 changes: 6 additions & 4 deletions src/post_process/m_derived_variables.fpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,18 +32,20 @@ contains
allocate (fd%gm_rho_sf(-offset_x%beg:m + offset_x%end,-offset_y%beg:n + offset_y%end,-offset_z%beg:p + offset_z%end))
end if

! Allocate FD coefficients (up to 4th order; higher orders need extension)
! Allocate FD coefficients (up to 4th order; higher orders need extension). s_compute_finite_difference_coefficients
! always extends at least fd_number beyond the interior on each side, widened further by offset_x/y/z when those
! are larger (multi-block Silo ghost zones); the allocation must cover whichever bound ends up wider.

if (omega_wrt(2) .or. omega_wrt(3) .or. qm_wrt .or. schlieren_wrt .or. liutex_wrt) then
allocate (fd%fd_coeff_x(-fd_number:fd_number,-offset_x%beg:m + offset_x%end))
allocate (fd%fd_coeff_x(-fd_number:fd_number,-max(fd_number, offset_x%beg):m + max(fd_number, offset_x%end)))
end if

if (omega_wrt(1) .or. omega_wrt(3) .or. qm_wrt .or. liutex_wrt .or. (n > 0 .and. schlieren_wrt)) then
allocate (fd%fd_coeff_y(-fd_number:fd_number,-offset_y%beg:n + offset_y%end))
allocate (fd%fd_coeff_y(-fd_number:fd_number,-max(fd_number, offset_y%beg):n + max(fd_number, offset_y%end)))
end if

if (omega_wrt(1) .or. omega_wrt(2) .or. qm_wrt .or. liutex_wrt .or. (p > 0 .and. schlieren_wrt)) then
allocate (fd%fd_coeff_z(-fd_number:fd_number,-offset_z%beg:p + offset_z%end))
allocate (fd%fd_coeff_z(-fd_number:fd_number,-max(fd_number, offset_z%beg):p + max(fd_number, offset_z%end)))
end if

end subroutine s_initialize_derived_variables_module
Expand Down
7 changes: 4 additions & 3 deletions src/simulation/m_bubbles_EL.fpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,18 +185,19 @@ contains

if (lag_params%vel_model > 0 .and. lag_params%pressure_force) then
@:ALLOCATE(grad_p_x(0:m, 0:n, 0:p))
@:ALLOCATE(fd_coeff_x_pgrad(-fd_number:fd_number, 0:m))
! s_compute_finite_difference_coefficients always extends fd_number beyond the interior on each side
@:ALLOCATE(fd_coeff_x_pgrad(-fd_number:fd_number,-fd_number:m + fd_number))
call s_compute_finite_difference_coefficients(m, x_cc, fd_coeff_x_pgrad, buff_size, fd_number, fd_order)
$:GPU_UPDATE(device='[fd_coeff_x_pgrad]')
if (n > 0) then
@:ALLOCATE(grad_p_y(0:m, 0:n, 0:p))
@:ALLOCATE(fd_coeff_y_pgrad(-fd_number:fd_number, 0:n))
@:ALLOCATE(fd_coeff_y_pgrad(-fd_number:fd_number,-fd_number:n + fd_number))
call s_compute_finite_difference_coefficients(n, y_cc, fd_coeff_y_pgrad, buff_size, fd_number, fd_order)
$:GPU_UPDATE(device='[fd_coeff_y_pgrad]')
end if
if (p > 0) then
@:ALLOCATE(grad_p_z(0:m, 0:n, 0:p))
@:ALLOCATE(fd_coeff_z_pgrad(-fd_number:fd_number, 0:p))
@:ALLOCATE(fd_coeff_z_pgrad(-fd_number:fd_number,-fd_number:p + fd_number))
call s_compute_finite_difference_coefficients(p, z_cc, fd_coeff_z_pgrad, buff_size, fd_number, fd_order)
$:GPU_UPDATE(device='[fd_coeff_z_pgrad]')
end if
Expand Down
Loading
Loading