Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
31 changes: 18 additions & 13 deletions docs/documentation/case.md
Original file line number Diff line number Diff line change
Expand Up @@ -1201,15 +1201,15 @@ This boundary condition can be used for subsonic inflow (`bc_[x,y,z]%[beg,end]`
| # | Name | Dim. | Smooth | Description |
| ---: | :----: | :---: | :---: | :--- |
| 1 | Line segment | 1 | N | Requires `x_centroid` and `length_x`. |
| 2 | Circle | 2 | Y | Requires `[x,y]_centroid` and `radius`. |
| 3 | Rectangle | 2 | N | Coordinate-aligned. Requires `[x,y]_centroid` and `length_[x,y]`. |
| 2 | Circle | 2 & 3 | Y | Requires `[x,y]_centroid` and `radius`. In 3D, equivalent to 10 (cylinder) if a `length_[x,y,z]` is set and to 8 (sphere) otherwise. |
| 3 | Rectangle | 2 & 3 | N | Coordinate-aligned. Requires `[x,y]_centroid` and `length_[x,y]`. In 3D, equivalent to 9 (cuboid). |
| 4 | Sweep line | 2 | Y | Not coordinate aligned. Requires `[x,y]_centroid` and `normal(i)`. |
| 5 | Ellipse | 2 | Y | Requires `[x,y]_centroid` and `radii(i)`. |
| 6 | N/A | N/A | N/A | No longer exists. Empty. |
| 7 | N/A | N/A | N/A | No longer exists. Empty. |
| 8 | Sphere | 3 | Y | Requires `[x,y,z]_centroid` and `radius` |
| 9 | Cuboid | 3 | N | Coordinate-aligned. Requires `[x,y,z]_centroid` and `length_[x,y,z]`. |
| 10 | Cylinder | 3 | Y | Requires `[x,y,z]_centroid`, `radius`, and `length_[x,y,z]`. |
| 8 | Sphere | 2 & 3 | Y | Requires `[x,y,z]_centroid` and `radius`. In 2D, equivalent to 2 (circle). |
| 9 | Cuboid | 2 & 3 | N | Coordinate-aligned. Requires `[x,y,z]_centroid` and `length_[x,y,z]`. In 2D, equivalent to 3 (rectangle). |
| 10 | Cylinder | 2 & 3 | Y | Requires `[x,y,z]_centroid`, `radius`, and exactly one of `length_[x,y,z]`. In 2D, equivalent to 2 (circle). |
| 11 | Sweep plane | 3 | Y | Not coordinate-aligned. Requires `x[y,z]_centroid` and `normal(i)`. |
| 12 | Ellipsoid | 3 | Y | Requires `[x,y,z]_centroid` and `radii(i)`. |
| 13 | 2D modal (Fourier) | 2 | Y | Requires `x_centroid`, `y_centroid`, `radius`. Optional: `fourier_cos(n)`, `fourier_sin(n)` (n=1..10), `modal_clip_r_to_min`, `modal_r_min`, `modal_use_exp_form`. |
Expand Down Expand Up @@ -1242,14 +1242,19 @@ Boundary is at polar angle \f$\theta = \mathrm{atan2}(y - y_{\mathrm{centroid}},

### Immersed Boundary Patch Types {#immersed-boundary-patch-types}

| # | Name | Dim. |
| ---: | :----: | :--- |
| 2 | 2D Circle | 2 |
| 3 | 2D Rectangle | 2 |
| 4 | 2D Airfoil | 2 |
| 8 | 3D Sphere | 3 |
| 10 | 3D Cylinder | 3 |
| 11 | 3D Airfoil | 3 |
| # | Name | Dim. |
| ---: | :----: | :--- |
| 2 | Circle / Sphere / Cylinder | 2 & 3 |
| 3 | Rectangle / Cuboid | 2 & 3 |
| 4 | Airfoil | 2 & 3 |
| 5 | Model (STL/OBJ) | 2 & 3 |
| 8 | 3D Sphere (alias of 2) | 3 |
| 9 | 3D Cuboid (alias of 3) | 3 |
| 10 | 3D Cylinder (alias of 2) | 3 |
| 11 | 3D Airfoil (alias of 4) | 3 |
| 12 | 3D Model (alias of 5) | 3 |

Geometry IDs are dimension-agnostic: in 3D, geometry 2 produces a cylinder when exactly one `length_[x,y,z]` is set and a sphere otherwise, and the legacy 3D-specific IDs (8-12) remain supported as aliases.

### Acoustic Supports {#acoustic-supports}

Expand Down
34 changes: 32 additions & 2 deletions src/common/m_helper_basic.fpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ module m_helper_basic
implicit none

private
public :: f_approx_equal, f_approx_in_array, f_is_default, f_all_default, f_is_integer, s_configure_coordinate_bounds, &
& s_update_cell_bounds
public :: f_approx_equal, f_approx_in_array, f_is_default, f_all_default, f_is_integer, f_canonical_geometry, &
& s_configure_coordinate_bounds, s_update_cell_bounds

contains

Expand Down Expand Up @@ -98,6 +98,36 @@ contains

end function f_all_default

!> Maps the dimension-agnostic patch geometry IDs and their legacy 2D/3D counterparts to the canonical ID for the grid
!! dimensionality, so all downstream dispatch (checks, patch application, IBM) sees one value.
!! @param geometry geometry ID as read from the case file
!! @param three_d true for 3D grids (p > 0)
!! @param has_length true if any of the patch's length_[x,y,z] is set
!! @param ib true for patch_ib IDs (also maps airfoils and models)
integer elemental function f_canonical_geometry(geometry, three_d, has_length, ib) result(canon)

integer, intent(in) :: geometry
logical, intent(in) :: three_d, has_length, ib

canon = geometry
if (three_d) then
select case (geometry)
case (2); canon = merge(10, 8, has_length) ! circle -> cylinder if extruded, sphere otherwise
case (3); canon = 9 ! rectangle -> cuboid
case (4); if (ib) canon = 11 ! airfoil -> 3D airfoil
case (5); if (ib) canon = 12 ! model -> 3D model
end select
else
select case (geometry)
case (8, 10); canon = 2 ! sphere/cylinder -> circle
case (9); canon = 3 ! cuboid -> rectangle
case (11); if (ib) canon = 4 ! 3D airfoil -> airfoil
case (12); if (ib) canon = 5 ! 3D model -> model
end select
end if

end function f_canonical_geometry

!> Checks if a real(wp) variable is an integer.
logical elemental function f_is_integer(var) result(res)

Expand Down
125 changes: 38 additions & 87 deletions src/pre_process/m_check_ib_patches.fpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,20 +40,12 @@ contains
@:PROHIBIT(patch_ib(i)%geometry == dflt_int, "IB patch undefined. patch_ib("//trim(iStr)//")%geometry must be set.")

! Constraints on the geometric initial condition patch parameters
if (patch_ib(i)%geometry == 2) then
if (patch_ib(i)%geometry == 2 .or. patch_ib(i)%geometry == 8 .or. patch_ib(i)%geometry == 10) then
Comment thread
Riship749 marked this conversation as resolved.
call s_check_circle_ib_patch_geometry(i)
else if (patch_ib(i)%geometry == 3) then
else if (patch_ib(i)%geometry == 3 .or. patch_ib(i)%geometry == 9) then
call s_check_rectangle_ib_patch_geometry(i)
else if (patch_ib(i)%geometry == 8) then
call s_check_sphere_ib_patch_geometry(i)
else if (patch_ib(i)%geometry == 9) then
call s_check_cuboid_ib_patch_geometry(i)
else if (patch_ib(i)%geometry == 4) then
else if (patch_ib(i)%geometry == 4 .or. patch_ib(i)%geometry == 11) then
call s_check_airfoil_ib_patch_geometry(i)
else if (patch_ib(i)%geometry == 11) then
call s_check_3d_airfoil_ib_patch_geometry(i)
else if (patch_ib(i)%geometry == 10) then
call s_check_cylinder_ib_patch_geometry(i)
else if (patch_ib(i)%geometry == 5 .or. patch_ib(i)%geometry == 12) then
call s_check_model_ib_patch_geometry(i)
else if (patch_ib(i)%geometry == 6) then
Expand All @@ -80,8 +72,25 @@ contains

call s_int_to_str(patch_id, iStr)

@:PROHIBIT(n == 0 .or. p > 0 .or. patch_ib(patch_id)%radius <= 0._wp .or. f_is_default(patch_ib(patch_id)%x_centroid) &
& .or. f_is_default(patch_ib(patch_id)%y_centroid), 'in circle IB patch ' // trim(iStr))
@:PROHIBIT(n == 0 .or. patch_ib(patch_id)%radius <= 0._wp .or. f_is_default(patch_ib(patch_id)%x_centroid) &
& .or. f_is_default(patch_ib(patch_id)%y_centroid), 'in circle/sphere/cylinder IB patch ' // trim(iStr))

! Spheres and cylinders (3D) additionally require a z-centroid
if (p > 0) then
@:PROHIBIT(f_is_default(patch_ib(patch_id)%z_centroid), 'in 3D sphere/cylinder IB patch ' // trim(iStr))
end if

! Cylinders are extruded along exactly one positive length
if (patch_ib(patch_id)%geometry == 10) then
@:PROHIBIT(count([patch_ib(patch_id)%length_x > 0._wp, patch_ib(patch_id)%length_y > 0._wp, &
& patch_ib(patch_id)%length_z > 0._wp]) /= 1, &
& 'in cylinder IB patch ' // trim(iStr) &
& // ': exactly one of length_x, length_y, or length_z must be defined and positive')
@:PROHIBIT((.not. f_is_default(patch_ib(patch_id)%length_x) .and. patch_ib(patch_id)%length_x <= 0._wp) &
& .or. (.not. f_is_default(patch_ib(patch_id)%length_y) .and. patch_ib(patch_id)%length_y <= 0._wp) &
& .or. (.not. f_is_default(patch_ib(patch_id)%length_z) .and. patch_ib(patch_id)%length_z <= 0._wp), &
& 'in cylinder IB patch ' // trim(iStr) // ': the defined lengths must be greater than zero')
end if

end subroutine s_check_circle_ib_patch_geometry

Expand All @@ -107,32 +116,19 @@ contains

call s_int_to_str(patch_id, iStr)

@:PROHIBIT(n == 0 .or. p > 0 .or. patch_ib(patch_id)%airfoil_id <= 0 &
& .or. ib_airfoil(patch_ib(patch_id)%airfoil_id)%c <= 0._wp &
@:PROHIBIT(n == 0 .or. patch_ib(patch_id)%airfoil_id <= 0 .or. ib_airfoil(patch_ib(patch_id)%airfoil_id)%c <= 0._wp &
& .or. ib_airfoil(patch_ib(patch_id)%airfoil_id)%p <= 0._wp &
& .or. ib_airfoil(patch_ib(patch_id)%airfoil_id)%t <= 0._wp &
& .or. ib_airfoil(patch_ib(patch_id)%airfoil_id)%m <= 0._wp .or. f_is_default(patch_ib(patch_id)%x_centroid) &
& .or. f_is_default(patch_ib(patch_id)%y_centroid), 'in airfoil IB patch ' // trim(iStr))

end subroutine s_check_airfoil_ib_patch_geometry

!> Verify that the geometric parameters of the 3D airfoil patch have been consistently inputted.

impure subroutine s_check_3d_airfoil_ib_patch_geometry(patch_id)

integer, intent(in) :: patch_id
! Additional checks strictly for 3D airfoils
if (p > 0) then
@:PROHIBIT(f_is_default(patch_ib(patch_id)%z_centroid) .or. f_is_default(patch_ib(patch_id)%length_z), &
& 'in 3D airfoil IB patch ' // trim(iStr))
end if

call s_int_to_str(patch_id, iStr)

@:PROHIBIT(n == 0 .or. p == 0 .or. patch_ib(patch_id)%airfoil_id <= 0 &
& .or. ib_airfoil(patch_ib(patch_id)%airfoil_id)%c <= 0._wp &
& .or. ib_airfoil(patch_ib(patch_id)%airfoil_id)%p <= 0._wp &
& .or. ib_airfoil(patch_ib(patch_id)%airfoil_id)%t <= 0._wp &
& .or. ib_airfoil(patch_ib(patch_id)%airfoil_id)%m <= 0._wp .or. f_is_default(patch_ib(patch_id)%x_centroid) &
& .or. f_is_default(patch_ib(patch_id)%y_centroid) .or. f_is_default(patch_ib(patch_id)%z_centroid) &
& .or. f_is_default(patch_ib(patch_id)%length_z), 'in 3d airfoil IB patch ' // trim(iStr))

end subroutine s_check_3d_airfoil_ib_patch_geometry
end subroutine s_check_airfoil_ib_patch_geometry

!> Verify that the geometric parameters of the rectangle patch have been consistently inputted.

Expand All @@ -142,62 +138,17 @@ contains

call s_int_to_str(patch_id, iStr)

@:PROHIBIT(n == 0 .or. p > 0 .or. f_is_default(patch_ib(patch_id)%x_centroid) &
& .or. f_is_default(patch_ib(patch_id)%y_centroid) .or. patch_ib(patch_id)%length_x <= 0._wp &
& .or. patch_ib(patch_id)%length_y <= 0._wp, 'in rectangle IB patch ' // trim(iStr))

end subroutine s_check_rectangle_ib_patch_geometry

!> Verify that the geometric parameters of the sphere patch have been consistently inputted.

impure subroutine s_check_sphere_ib_patch_geometry(patch_id)

integer, intent(in) :: patch_id

call s_int_to_str(patch_id, iStr)

@:PROHIBIT(n == 0 .or. p == 0 .or. f_is_default(patch_ib(patch_id)%x_centroid) &
& .or. f_is_default(patch_ib(patch_id)%y_centroid) .or. f_is_default(patch_ib(patch_id)%z_centroid) &
& .or. patch_ib(patch_id)%radius <= 0._wp, 'in sphere IB patch ' // trim(iStr))

end subroutine s_check_sphere_ib_patch_geometry

!> Verify that the geometric parameters of the cuboid patch have been consistently inputted.

impure subroutine s_check_cuboid_ib_patch_geometry(patch_id)

integer, intent(in) :: patch_id

call s_int_to_str(patch_id, iStr)

@:PROHIBIT(n == 0 .or. p == 0 .or. f_is_default(patch_ib(patch_id)%x_centroid) &
& .or. f_is_default(patch_ib(patch_id)%y_centroid) .or. f_is_default(patch_ib(patch_id)%z_centroid) &
& .or. patch_ib(patch_id)%length_x <= 0._wp .or. patch_ib(patch_id)%length_y <= 0._wp &
& .or. patch_ib(patch_id)%length_z <= 0._wp, 'in cuboid IB patch ' // trim(iStr))
@:PROHIBIT(n == 0 .or. f_is_default(patch_ib(patch_id)%x_centroid) .or. f_is_default(patch_ib(patch_id)%y_centroid) &
& .or. patch_ib(patch_id)%length_x <= 0._wp .or. patch_ib(patch_id)%length_y <= 0._wp, &
& 'in rectangle/cuboid IB patch ' // trim(iStr))

end subroutine s_check_cuboid_ib_patch_geometry
! If the simulation is 3D, also mandate Z lengths and centroids
if (p > 0) then
@:PROHIBIT(f_is_default(patch_ib(patch_id)%z_centroid) .or. patch_ib(patch_id)%length_z <= 0._wp, &
& 'in 3D cuboid IB patch ' // trim(iStr))
end if

!> Verify that the geometric parameters of the cylinder patch have been consistently inputted.

impure subroutine s_check_cylinder_ib_patch_geometry(patch_id)

integer, intent(in) :: patch_id

call s_int_to_str(patch_id, iStr)

@:PROHIBIT(p == 0 .or. f_is_default(patch_ib(patch_id)%x_centroid) .or. f_is_default(patch_ib(patch_id)%y_centroid) &
& .or. f_is_default(patch_ib(patch_id)%z_centroid) .or. (patch_ib(patch_id)%length_x <= 0._wp &
& .and. patch_ib(patch_id)%length_y <= 0._wp .and. patch_ib(patch_id)%length_z <= 0._wp) &
& .or. patch_ib(patch_id)%radius <= 0._wp, 'in cylinder IB patch ' // trim(iStr))

@:PROHIBIT((patch_ib(patch_id)%length_x > 0._wp .and. ((.not. f_is_default(patch_ib(patch_id)%length_y)) &
& .or. (.not. f_is_default(patch_ib(patch_id)%length_z)))) .or. (patch_ib(patch_id)%length_y > 0._wp &
& .and. ((.not. f_is_default(patch_ib(patch_id)%length_x)) &
& .or. (.not. f_is_default(patch_ib(patch_id)%length_z)))) .or. (patch_ib(patch_id)%length_z > 0._wp &
& .and. ((.not. f_is_default(patch_ib(patch_id)%length_x)) &
& .or. (.not. f_is_default(patch_ib(patch_id)%length_y)))), 'in cylinder IB patch ' // trim(iStr))

end subroutine s_check_cylinder_ib_patch_geometry
end subroutine s_check_rectangle_ib_patch_geometry

!> Verify that the geometric parameters of the model patch have been consistently inputted.

Expand Down
Loading
Loading