Skip to content

Commit 1deb65a

Browse files
Moved ray tracing to only include cell centers, making it consistent with all other IB methods, and replaced it with a standard deterministic ray selection algorithm.
1 parent 3071dbd commit 1deb65a

2 files changed

Lines changed: 56 additions & 62 deletions

File tree

src/common/m_model.fpp

Lines changed: 51 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,14 @@ contains
578578

579579
end function f_model_is_inside
580580

581-
impure function f_model_is_inside_flat(ntrs, trs_v, trs_n, pid, point, spacing, spc) result(fraction)
581+
!> This procedure, given a cell center will determine if a point exists instide a surface
582+
!! @param ntrs Number of triangles in the model
583+
!! @param trs_v Model vertices of each triangle
584+
!! @param trs_n Model normal vectors of each triangle
585+
!! @param pid Patch ID od this model
586+
!! @param point Point to test.
587+
!! @return fraction The perfentage of candidate rays cast indicate that we are inside the model
588+
impure function f_model_is_inside_flat(ntrs, trs_v, trs_n, pid, point) result(fraction)
582589

583590
$:GPU_ROUTINE(parallelism='[seq]')
584591

@@ -587,47 +594,49 @@ contains
587594
real(wp), dimension(:, :, :), intent(in) :: trs_n
588595
integer, intent(in) :: pid
589596
real(wp), dimension(1:3), intent(in) :: point
590-
real(wp), dimension(1:3), intent(in) :: spacing
591-
integer, intent(in) :: spc
592597

593598
real(wp) :: fraction
594-
real(wp) :: origin(1:3), dir(1:3), dir_mag
595599
type(t_ray) :: ray
596600
type(t_triangle) :: tri
597-
integer :: i, j, k, nInOrOut, nHits
598-
integer :: rand_seed
601+
integer :: i, j, k, q, nInOrOut, nHits
599602

600-
rand_seed = int(point(1)*73856093._wp) + &
601-
int(point(2)*19349663._wp) + &
602-
int(point(3)*83492791._wp)
603-
if (rand_seed == 0) rand_seed = 1
604-
605-
! generate our random collection of rays
603+
! cast 26 rays from the point and count the number at leave the boundary
606604
nInOrOut = 0
607-
do i = 1, spc
608-
! Generate one ray at a time — no arrays needed
609-
do k = 1, 3
610-
origin(k) = point(k) + (f_model_random_number(rand_seed) - 0.5_wp)*spacing(k)
611-
dir(k) = point(k) + f_model_random_number(rand_seed) - 0.5_wp
612-
end do
613-
dir_mag = sqrt(dir(1)*dir(1) + dir(2)*dir(2) + dir(3)*dir(3))
614-
dir(:) = dir(:)/dir_mag
615-
616-
ray%o = origin
617-
ray%d = dir
618-
619-
nHits = 0
620-
do j = 1, ntrs
621-
tri%v(:, :) = trs_v(:, :, j, pid)
622-
tri%n(:) = trs_n(:, j, pid)
623-
if (f_intersects_triangle(ray, tri)) then
624-
nHits = nHits + 1
625-
end if
605+
do i = -1, 1
606+
do j = -1, 1
607+
do k = -1, 1
608+
if (i /= 0 .or. j /= 0 .or. k /= 0) then
609+
! We cannot get inersections if the ray is exactly in line with triangle plane
610+
if (p == 0 .and. k == 0) cycle
611+
612+
! generate the ray
613+
ray%o = point
614+
ray%d(:) = [real(i, wp), real(j, wp), real(k, wp)]
615+
ray%d = ray%d/sqrt(real(abs(i) + abs(j) + abs(k), wp))
616+
617+
! count the number of intersections
618+
nHits = 0
619+
do q = 1, ntrs
620+
tri%v(:, :) = trs_v(:, :, q, pid)
621+
tri%n(:) = trs_n(:, q, pid)
622+
if (f_intersects_triangle(ray, tri)) then
623+
nHits = nHits + 1
624+
end if
625+
end do
626+
! if the ray intersected an odd number of times, we must be inside
627+
nInOrOut = nInOrOut + mod(nHits, 2)
628+
end if
629+
end do
626630
end do
627-
nInOrOut = nInOrOut + mod(nHits, 2)
628631
end do
629632

630-
fraction = real(nInOrOut)/real(spc)
633+
if (p == 0) then
634+
! in 2D, we skipped 8 rays
635+
fraction = real(nInOrOut)/18._wp
636+
else
637+
fraction = real(nInOrOut)/26._wp
638+
end if
639+
631640
end function f_model_is_inside_flat
632641

633642
! From https://www.scratchapixel.com/lessons/3e-basic-rendering/ray-tracing-rendering-a-triangle/ray-triangle-intersection-geometric-solution.html
@@ -846,7 +855,7 @@ contains
846855
real(wp) :: dist_min, dist_proj, dist_v, dist_e, t
847856
real(wp) :: v1(1:3), v2(1:3), v3(1:3)
848857
real(wp) :: e0(1:3), e1(1:3), pv(1:3)
849-
real(wp) :: n(1:3), proj(1:3), normals(1:3), norm_vec(1:3)
858+
real(wp) :: n(1:3), proj(1:3), norm_vec(1:3)
850859
real(wp) :: d, ndot, denom, norm_mag
851860
real(wp) :: u, v_bary, w
852861
real(wp) :: l00, l01, l11, l20, l21
@@ -884,6 +893,7 @@ contains
884893

885894
denom = l00*l11 - l01*l01
886895

896+
! compute the barycentric coordinates of the projection in the triangle
887897
if (abs(denom) > 0._wp) then
888898
v_bary = (l11*l20 - l01*l21)/denom
889899
w = (l00*l21 - l01*l20)/denom
@@ -897,8 +907,8 @@ contains
897907
! If projection is inside triangle
898908
if (u >= 0._wp .and. v_bary >= 0._wp .and. w >= 0._wp) then
899909
dist_proj = sqrt((point(1) - proj(1))**2 + &
900-
(point(2) - proj(2))**2 + &
901-
(point(3) - proj(3))**2)
910+
(point(2) - proj(2))**2 + &
911+
(point(3) - proj(3))**2)
902912

903913
if (dist_proj < dist_min) then
904914
dist_min = dist_proj
@@ -927,7 +937,7 @@ contains
927937
dist_min = dist_e
928938
norm_vec(:) = point(:) - verts(:, j)
929939
norm_mag = sqrt(dot_product(norm_vec, norm_vec))
930-
if (norm_mag > 0._wp) norm_vec = norm_vec / norm_mag
940+
if (norm_mag > 0._wp) norm_vec = norm_vec/norm_mag
931941
normals(:) = norm_vec(:)
932942
end if
933943
else if (t < 0._wp) then
@@ -939,7 +949,7 @@ contains
939949
dist_min = dist_v
940950
norm_vec(:) = point(:) - verts(:, j)
941951
norm_mag = sqrt(dot_product(norm_vec, norm_vec))
942-
if (norm_mag > 0._wp) norm_vec = norm_vec / norm_mag
952+
if (norm_mag > 0._wp) norm_vec = norm_vec/norm_mag
943953
normals(:) = norm_vec(:)
944954
end if
945955
else
@@ -951,7 +961,7 @@ contains
951961
dist_min = dist_v
952962
norm_vec(:) = point(:) - verts(:, mod(j, 3) + 1)
953963
norm_mag = sqrt(dot_product(norm_vec, norm_vec))
954-
if (norm_mag > 0._wp) norm_vec = norm_vec / norm_mag
964+
if (norm_mag > 0._wp) norm_vec = norm_vec/norm_mag
955965
normals(:) = norm_vec(:)
956966
end if
957967
end if
@@ -1021,13 +1031,13 @@ contains
10211031
norm(1) = point(1) - v1(1)
10221032
norm(2) = point(2) - v1(2)
10231033
norm_mag = sqrt(dot_product(norm, norm))
1024-
norm = norm / norm_mag
1034+
norm = norm/norm_mag
10251035
else ! t > 1 means that v2 is the closest point on the line edge
10261036
dist = sqrt((point(1) - v2(1))**2 + (point(2) - v2(2))**2)
10271037
norm(1) = point(1) - v2(1)
10281038
norm(2) = point(2) - v2(2)
10291039
norm_mag = sqrt(dot_product(norm, norm))
1030-
norm = norm / norm_mag
1040+
norm = norm/norm_mag
10311041
end if
10321042

10331043
if (dist < dist_min) then

src/simulation/m_ib_patches.fpp

Lines changed: 5 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -858,26 +858,18 @@ contains
858858
& copyin='[patch_id,center,inverse_rotation, offset, spc, threshold]', collapse=2)
859859
do i = -gp_layers, m + gp_layers
860860
do j = -gp_layers, n + gp_layers
861-
862861
xy_local = [x_cc(i) - center(1), y_cc(j) - center(2), 0._wp]
863862
xy_local = matmul(inverse_rotation, xy_local)
864863
xy_local = xy_local - offset
865864
866-
if (grid_geometry == 3) then
867-
xy_local = f_convert_cyl_to_cart(xy_local)
868-
end if
869-
870865
eta = f_model_is_inside_flat(gpu_ntrs(patch_id), &
871866
gpu_trs_v, gpu_trs_n, &
872-
patch_id, &
873-
xy_local, (/dx(i), dy(j), 0._wp/), &
874-
spc)
867+
patch_id, xy_local)
875868
876869
! Reading STL boundary vertices and compute the levelset and levelset_norm
877-
if (eta > threshold) then
870+
if (eta > 0.5_wp) then
878871
ib_markers%sf(i, j, 0) = patch_id
879872
end if
880-
881873
end do
882874
end do
883875
$:END_GPU_PARALLEL_LOOP()
@@ -929,26 +921,18 @@ contains
929921
do i = il, ir
930922
do j = jl, jr
931923
do k = kl, kr
932-
933924
xyz_local = [x_cc(i) - center(1), y_cc(j) - center(2), z_cc(k) - center(3)]
934925
xyz_local = matmul(inverse_rotation, xyz_local)
935926
xyz_local = xyz_local - offset
936927
937-
if (grid_geometry == 3) then
938-
xyz_local = f_convert_cyl_to_cart(xyz_local)
939-
end if
940-
941928
eta = f_model_is_inside_flat(gpu_ntrs(patch_id), &
942929
gpu_trs_v, gpu_trs_n, &
943-
patch_id, &
944-
xyz_local, (/dx(i), dy(j), dz(k)/), &
945-
spc)
930+
patch_id, xyz_local)
946931
947-
! Reading STL boundary vertices and compute the levelset and levelset_norm
948-
if (eta > patch_ib(patch_id)%model_threshold) then
932+
! if (eta > patch_ib(patch_id)%model_threshold) then
933+
if (eta > 0.5_wp) then
949934
ib_markers%sf(i, j, k) = patch_id
950935
end if
951-
952936
end do
953937
end do
954938
end do

0 commit comments

Comments
 (0)