Skip to content

Commit 944aa2f

Browse files
danieljvickersDaniel VickersDaniel Vickerswilfonba
authored
Analytic mibm velocities and airfoil centroid (#1111)
Co-authored-by: Daniel Vickers <danieljvickers@login12.frontier.olcf.ornl.gov> Co-authored-by: Daniel Vickers <danieljvickers@login09.frontier.olcf.ornl.gov> Co-authored-by: Ben Wilfong <48168887+wilfonba@users.noreply.github.com>
1 parent 6264d3f commit 944aa2f

File tree

11 files changed

+261
-64
lines changed

11 files changed

+261
-64
lines changed

examples/2D_ibm_ellipse/case.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@
8181
"patch_icpp(1)%pres": 1.0e00,
8282
"patch_icpp(1)%alpha_rho(1)": 1.0e00,
8383
"patch_icpp(1)%alpha(1)": 1.0e00,
84-
# Patch: Cylinder Immersed Boundary
84+
# Patch: Ellipse Immersed Boundary
8585
"patch_ib(1)%geometry": 6,
8686
"patch_ib(1)%x_centroid": 1.5e-03,
8787
"patch_ib(1)%y_centroid": 3.0e-03,

src/common/include/case.fpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,8 @@
66
#:def analytical()
77

88
#:enddef
9+
10+
! For moving immersed boundaries in simulation
11+
#:def mib_analytical()
12+
13+
#:enddef

src/common/m_compute_levelset.fpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ contains
9494
do j = 0, n
9595
xy_local = [x_cc(i) - center(1), y_cc(j) - center(2), 0._wp] ! get coordinate frame centered on IB
9696
xy_local = matmul(inverse_rotation, xy_local) ! rotate the frame into the IB's coordinate
97+
xy_local = xy_local - patch_ib(ib_patch_id)%centroid_offset ! airfoils are a patch that require a centroid offset
9798
9899
if (xy_local(2) >= 0._wp) then
99100
! finds the location on the airfoil grid with the minimum distance (closest)
@@ -189,6 +190,7 @@ contains
189190
190191
xyz_local = [x_cc(i) - center(1), y_cc(j) - center(2), z_cc(l) - center(3)] ! get coordinate frame centered on IB
191192
xyz_local = matmul(inverse_rotation, xyz_local) ! rotate the frame into the IB's coordinates
193+
xyz_local = xyz_local - patch_ib(ib_patch_id)%centroid_offset ! airfoils are a patch that require a centroid offset
192194

193195
if (xyz_local(2) >= center(2)) then
194196
do k = 1, Np

src/common/m_derived_types.fpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ module m_derived_types
296296
!! is specified through its x-, y- and z-coordinates, respectively.
297297
real(wp) :: step_x_centroid, step_y_centroid, step_z_centroid !<
298298
!! Centroid locations of intermediate steps in the time_stepper module
299+
real(wp), dimension(1:3) :: centroid_offset ! offset of center of mass from computed cell center for odd-shaped IBs
299300

300301
real(wp), dimension(1:3) :: angles
301302
real(wp), dimension(1:3) :: step_angles

src/common/m_ib_patches.fpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ contains
279279
do i = 0, m
280280
xy_local = [x_cc(i) - center(1), y_cc(j) - center(2), 0._wp] ! get coordinate frame centered on IB
281281
xy_local = matmul(inverse_rotation, xy_local) ! rotate the frame into the IB's coordinates
282+
xy_local = xy_local - patch_ib(patch_id)%centroid_offset ! airfoils are a patch that require a centroid offset
282283
283284
if (xy_local(1) >= 0._wp .and. xy_local(1) <= ca_in) then
284285
xa = xy_local(1)/ca_in
@@ -433,6 +434,7 @@ contains
433434
do i = 0, m
434435
xyz_local = [x_cc(i) - center(1), y_cc(j) - center(2), z_cc(l) - center(3)] ! get coordinate frame centered on IB
435436
xyz_local = matmul(inverse_rotation, xyz_local) ! rotate the frame into the IB's coordinates
437+
xyz_local = xyz_local - patch_ib(patch_id)%centroid_offset ! airfoils are a patch that require a centroid offset
436438

437439
if (xyz_local(3) >= z_min .and. xyz_local(3) <= z_max) then
438440

src/pre_process/m_global_parameters.fpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,6 +572,7 @@ contains
572572
patch_ib(i)%angular_vel(:) = 0._wp
573573
patch_ib(i)%mass = dflt_real
574574
patch_ib(i)%moment = dflt_real
575+
patch_ib(i)%centroid_offset(:) = 0._wp
575576

576577
! sets values of a rotation matrix which can be used when calculating rotations
577578
patch_ib(i)%rotation_matrix = 0._wp

src/simulation/m_ibm.fpp

Lines changed: 96 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -95,13 +95,15 @@ contains
9595
integer :: i, j, k
9696
integer :: max_num_gps, max_num_inner_gps
9797

98+
! do all set up for moving immersed boundaries
9899
moving_immersed_boundary_flag = .false.
99100
do i = 1, num_ibs
100101
if (patch_ib(i)%moving_ibm /= 0) then
101102
call s_compute_moment_of_inertia(i, patch_ib(i)%angular_vel)
102103
moving_immersed_boundary_flag = .true.
103104
end if
104105
call s_update_ib_rotation_matrix(i)
106+
call s_compute_centroid_offset(i)
105107
end do
106108
$:GPU_ENTER_DATA(copyin='[patch_ib]')
107109

@@ -1012,24 +1014,35 @@ contains
10121014
! compute the surface integrals of the IB via a volume integraion method described in
10131015
! "A coupled IBM/Euler-Lagrange framework for simulating shock-induced particle size segregation"
10141016
! by Archana Sridhar and Jesse Capecelatro
1015-
subroutine s_compute_ib_forces(q_prim_vf, dynamic_viscosity)
1017+
subroutine s_compute_ib_forces(q_prim_vf, fluid_pp)
10161018
10171019
! real(wp), dimension(idwbuff(1)%beg:idwbuff(1)%end, &
10181020
! idwbuff(2)%beg:idwbuff(2)%end, &
10191021
! idwbuff(3)%beg:idwbuff(3)%end), intent(in) :: pressure
10201022
type(scalar_field), dimension(1:sys_size), intent(in) :: q_prim_vf
1021-
real(wp), intent(in) :: dynamic_viscosity
1023+
type(physical_parameters), dimension(1:num_fluids), intent(in) :: fluid_pp
10221024
1023-
integer :: gp_id, i, j, k, l, q, ib_idx
1025+
integer :: gp_id, i, j, k, l, q, ib_idx, fluid_idx
10241026
real(wp), dimension(num_ibs, 3) :: forces, torques
10251027
real(wp), dimension(1:3, 1:3) :: viscous_stress_div, viscous_stress_div_1, viscous_stress_div_2, viscous_cross_1, viscous_cross_2 ! viscous stress tensor with temp vectors to hold divergence calculations
10261028
real(wp), dimension(1:3) :: local_force_contribution, radial_vector, local_torque_contribution, vel
1027-
real(wp) :: cell_volume, dx, dy, dz
1029+
real(wp) :: cell_volume, dx, dy, dz, dynamic_viscosity
1030+
real(wp), dimension(1:num_fluids) :: dynamic_viscosities
10281031
10291032
forces = 0._wp
10301033
torques = 0._wp
10311034
1032-
$:GPU_PARALLEL_LOOP(private='[ib_idx,radial_vector,local_force_contribution,cell_volume,local_torque_contribution, viscous_stress_div, viscous_stress_div_1, viscous_stress_div_2, viscous_cross_1, viscous_cross_2, dx, dy, dz]', copy='[forces,torques]', copyin='[ib_markers,patch_ib,dynamic_viscosity]', collapse=3)
1035+
if (viscous) then
1036+
do fluid_idx = 1, num_fluids
1037+
if (fluid_pp(fluid_idx)%Re(1) /= 0._wp) then
1038+
dynamic_viscosities(fluid_idx) = 1._wp/fluid_pp(fluid_idx)%Re(1)
1039+
else
1040+
dynamic_viscosities(fluid_idx) = 0._wp
1041+
end if
1042+
end do
1043+
end if
1044+
1045+
$:GPU_PARALLEL_LOOP(private='[ib_idx,fluid_idx, radial_vector,local_force_contribution,cell_volume,local_torque_contribution, dynamic_viscosity, viscous_stress_div, viscous_stress_div_1, viscous_stress_div_2, viscous_cross_1, viscous_cross_2, dx, dy, dz]', copy='[forces,torques]', copyin='[ib_markers,patch_ib,dynamic_viscosities]', collapse=3)
10331046
do i = 0, m
10341047
do j = 0, n
10351048
do k = 0, p
@@ -1044,26 +1057,33 @@ contains
10441057
dx = x_cc(i + 1) - x_cc(i)
10451058
dy = y_cc(j + 1) - y_cc(j)
10461059
1047-
! Get the pressure contribution to force via a finite difference to compute the 2D components of the gradient of the pressure and cell volume
1048-
local_force_contribution(1) = -1._wp*(q_prim_vf(E_idx)%sf(i + 1, j, k) - q_prim_vf(E_idx)%sf(i - 1, j, k))/(2._wp*dx) ! force is the negative pressure gradient
1049-
local_force_contribution(2) = -1._wp*(q_prim_vf(E_idx)%sf(i, j + 1, k) - q_prim_vf(E_idx)%sf(i, j - 1, k))/(2._wp*dy)
1050-
cell_volume = abs(dx*dy)
1051-
! add the 3D component of the pressure gradient, if we are working in 3 dimensions
1052-
if (num_dims == 3) then
1053-
dz = z_cc(k + 1) - z_cc(k)
1054-
local_force_contribution(3) = -1._wp*(q_prim_vf(E_idx)%sf(i, j, k + 1) - q_prim_vf(E_idx)%sf(i, j, k - 1))/(2._wp*dz)
1055-
cell_volume = abs(cell_volume*dz)
1056-
else
1057-
local_force_contribution(3) = 0._wp
1058-
end if
1060+
local_force_contribution(:) = 0._wp
1061+
do fluid_idx = 0, num_fluids - 1
1062+
! Get the pressure contribution to force via a finite difference to compute the 2D components of the gradient of the pressure and cell volume
1063+
local_force_contribution(1) = local_force_contribution(1) - (q_prim_vf(E_idx + fluid_idx)%sf(i + 1, j, k) - q_prim_vf(E_idx + fluid_idx)%sf(i - 1, j, k))/(2._wp*dx) ! force is the negative pressure gradient
1064+
local_force_contribution(2) = local_force_contribution(2) - (q_prim_vf(E_idx + fluid_idx)%sf(i, j + 1, k) - q_prim_vf(E_idx + fluid_idx)%sf(i, j - 1, k))/(2._wp*dy)
1065+
cell_volume = abs(dx*dy)
1066+
! add the 3D component of the pressure gradient, if we are working in 3 dimensions
1067+
if (num_dims == 3) then
1068+
dz = z_cc(k + 1) - z_cc(k)
1069+
local_force_contribution(3) = local_force_contribution(3) - (q_prim_vf(E_idx + fluid_idx)%sf(i, j, k + 1) - q_prim_vf(E_idx + fluid_idx)%sf(i, j, k - 1))/(2._wp*dz)
1070+
cell_volume = abs(cell_volume*dz)
1071+
end if
1072+
end do
10591073
10601074
! Update the force values atomically to prevent race conditions
10611075
call s_cross_product(radial_vector, local_force_contribution, local_torque_contribution)
10621076
10631077
! get the viscous stress and add its contribution if that is considered
10641078
! TODO :: This is really bad code
1065-
! if (.false.) then
10661079
if (viscous) then
1080+
! compute the volume-weighted local dynamic viscosity
1081+
dynamic_viscosity = 0._wp
1082+
do fluid_idx = 1, num_fluids
1083+
! local dynamic viscosity is the dynamic viscosity of the fluid times alpha of the fluid
1084+
dynamic_viscosity = dynamic_viscosity + (q_prim_vf(fluid_idx + advxb - 1)%sf(i, j, k)*dynamic_viscosities(fluid_idx))
1085+
end do
1086+
10671087
! get the linear force component first
10681088
call s_compute_viscous_stress_tensor(viscous_stress_div_1, q_prim_vf, dynamic_viscosity, i - 1, j, k)
10691089
call s_compute_viscous_stress_tensor(viscous_stress_div_2, q_prim_vf, dynamic_viscosity, i + 1, j, k)
@@ -1150,6 +1170,64 @@ contains
11501170
11511171
end subroutine s_finalize_ibm_module
11521172
1173+
!> Computes the center of mass for IB patch types where we are unable to determine their center of mass analytically.
1174+
!> These patches include things like NACA airfoils and STL models
1175+
subroutine s_compute_centroid_offset(ib_marker)
1176+
1177+
integer, intent(in) :: ib_marker
1178+
1179+
integer :: i, j, k, num_cells, num_cells_local
1180+
real(wp), dimension(1:3) :: center_of_mass, center_of_mass_local
1181+
1182+
! Offset only needs to be computes for specific geometries
1183+
if (patch_ib(ib_marker)%geometry == 4 .or. &
1184+
patch_ib(ib_marker)%geometry == 5 .or. &
1185+
patch_ib(ib_marker)%geometry == 11 .or. &
1186+
patch_ib(ib_marker)%geometry == 12) then
1187+
1188+
center_of_mass_local = [0._wp, 0._wp, 0._wp]
1189+
num_cells_local = 0
1190+
1191+
! get the summed mass distribution and number of cells to divide by
1192+
do i = 0, m
1193+
do j = 0, n
1194+
do k = 0, p
1195+
if (ib_markers%sf(i, j, k) == ib_marker) then
1196+
num_cells_local = num_cells_local + 1
1197+
center_of_mass_local = center_of_mass_local + [x_cc(i), y_cc(j), 0._wp]
1198+
if (num_dims == 3) center_of_mass_local(3) = center_of_mass_local(3) + z_cc(k)
1199+
end if
1200+
end do
1201+
end do
1202+
end do
1203+
1204+
! reduce the mass contribution over all MPI ranks and compute COM
1205+
call s_mpi_allreduce_integer_sum(num_cells_local, num_cells)
1206+
if (num_cells /= 0) then
1207+
call s_mpi_allreduce_sum(center_of_mass_local(1), center_of_mass(1))
1208+
call s_mpi_allreduce_sum(center_of_mass_local(2), center_of_mass(2))
1209+
call s_mpi_allreduce_sum(center_of_mass_local(3), center_of_mass(3))
1210+
center_of_mass = center_of_mass/real(num_cells, wp)
1211+
else
1212+
patch_ib(ib_marker)%centroid_offset = [0._wp, 0._wp, 0._wp]
1213+
return
1214+
end if
1215+
1216+
! assign the centroid offset as a vector pointing from the true COM to the "centroid" in the input file and replace the current centroid
1217+
patch_ib(ib_marker)%centroid_offset = [patch_ib(ib_marker)%x_centroid, patch_ib(ib_marker)%y_centroid, patch_ib(ib_marker)%z_centroid] &
1218+
- center_of_mass
1219+
patch_ib(ib_marker)%x_centroid = center_of_mass(1)
1220+
patch_ib(ib_marker)%y_centroid = center_of_mass(2)
1221+
patch_ib(ib_marker)%z_centroid = center_of_mass(3)
1222+
1223+
! rotate the centroid offset back into the local coords of the IB
1224+
patch_ib(ib_marker)%centroid_offset = matmul(patch_ib(ib_marker)%rotation_matrix_inverse, patch_ib(ib_marker)%centroid_offset)
1225+
else
1226+
patch_ib(ib_marker)%centroid_offset(:) = [0._wp, 0._wp, 0._wp]
1227+
end if
1228+
1229+
end subroutine s_compute_centroid_offset
1230+
11531231
subroutine s_compute_moment_of_inertia(ib_marker, axis)
11541232
11551233
real(wp), dimension(3), intent(in) :: axis !< the axis about which we compute the moment. Only required in 3D.

0 commit comments

Comments
 (0)