61 type(
field_t),
intent(inout) :: field_data
62 class(*),
intent(in) :: object
63 real(kind=
dp),
intent(in),
optional :: max_distance
65 real(kind=
dp) :: max_dist
67 if (
present(max_distance))
then
68 max_dist = max_distance
70 max_dist = huge(0.0_dp)
78 call neko_error(
"signed_distance_field: Object type not supported.")
94 type(
field_t),
intent(inout) :: field_data
96 real(kind=
dp),
intent(in) :: max_distance
101 real(kind=
dp),
dimension(3) :: p
102 real(kind=
dp) :: distance
105 field_data%x = 0.0_dp
106 total_size = field_data%dof%size()
108 call search_tree%init(
mesh%nelv)
109 call search_tree%build(
mesh%el)
111 if (search_tree%get_size() .ne.
mesh%nelv)
then
112 call neko_error(
"signed_distance_field_tri_mesh: &
113 & Error building the search tree.")
116 do id = 1, total_size
117 p(1) = field_data%dof%x(id, 1, 1, 1)
118 p(2) = field_data%dof%y(id, 1, 1, 1)
119 p(3) = field_data%dof%z(id, 1, 1, 1)
123 field_data%x(id, 1, 1, 1) =
real(distance, kind=
rp)
128 & Device version not implemented.")
129 call device_memcpy(field_data%x, field_data%x_d, field_data%size(), &
153 real(kind=
dp),
intent(in) :: p(3)
154 real(kind=
dp),
intent(in) :: max_distance
157 real(kind=
dp) :: distance, weighted_sign
158 real(kind=
dp) :: cd, cs
159 real(kind=
dp) :: tol = 1e-6_dp
162 weighted_sign = 0.0_dp
168 if (abs(cd - distance) / distance .lt. tol)
then
169 weighted_sign = weighted_sign + cs
170 else if (cd .lt. distance)
then
174 distance = min(cd, distance)
177 distance = sign(min(distance, max_distance), weighted_sign)
201 class(
tri_t),
dimension(:),
intent(in) :: object_list
202 real(kind=
dp),
dimension(3),
intent(in) :: p
203 real(kind=
dp),
intent(in) :: max_distance
205 real(kind=
dp) :: distance
206 real(kind=
dp) :: weighted_sign
208 real(kind=
dp),
parameter :: tol = 1.0e-6_dp
211 integer :: current_index
214 type(
aabb_t) :: current_aabb
215 integer :: current_object_index
216 real(kind=
dp) :: current_distance
217 real(kind=
dp) :: current_sign
223 type(
aabb_t) :: search_box
225 integer :: root_index, left_index, right_index
226 real(kind=
dp) :: random_value
229 call simple_stack%init(
size(object_list) * 2)
230 call search_box%init(p - max_distance, p + max_distance)
234 root_index = tree%get_root_index()
235 root_box = tree%get_aabb(root_index)
237 if (.not. root_box%overlaps(search_box))
then
238 distance = max_distance
239 weighted_sign = 1.0_dp
244 call random_number(random_value)
245 current_object_index = floor(random_value *
size(object_list) + 1)
246 call element_distance(object_list(current_object_index), p, distance, weighted_sign)
247 distance = distance + object_list(current_object_index)%diameter()
250 call search_box%init(p - distance, p + distance)
251 call simple_stack%push(root_index)
254 do while (.not. simple_stack%is_empty())
255 current_index = simple_stack%pop()
258 current_node = tree%get_node(current_index)
259 current_aabb = current_node%get_aabb()
261 if (current_node%is_leaf())
then
262 if (distance .lt. current_node%min_distance(p))
then
266 current_object_index = current_node%get_object_index()
267 call element_distance(object_list(current_object_index), p, current_distance, current_sign)
270 if (abs(current_distance - distance) / distance .lt. tol)
then
271 weighted_sign = weighted_sign + current_sign
272 else if (current_distance .lt. distance)
then
273 weighted_sign = current_sign
276 distance = min(distance, current_distance)
279 if (distance .gt. current_aabb%get_diameter())
then
280 call search_box%init(p - distance, p + distance)
284 left_index = tree%get_left_index(current_index)
286 left_node = tree%get_left_node(current_index)
287 if (left_node%aabb%overlaps(search_box))
then
288 call simple_stack%push(left_index)
292 right_index = tree%get_right_index(current_index)
294 right_node = tree%get_right_node(current_index)
295 if (right_node%aabb%overlaps(search_box))
then
296 call simple_stack%push(right_index)
302 if (distance .gt. max_distance)
then
303 distance = max_distance
305 distance = sign(distance, weighted_sign)
315 class(*),
intent(in) ::
element
316 real(kind=
dp),
dimension(3),
intent(in) :: p
317 real(kind=
dp),
intent(out) :: distance
318 real(kind=
dp),
intent(out),
optional :: weighted_sign
325 print *,
"Error: Element type not supported."
351 type(
tri_t),
intent(in) :: triangle
352 real(kind=
dp),
dimension(3),
intent(in) :: p
354 real(kind=
dp),
intent(out) :: distance
355 real(kind=
dp),
intent(out),
optional :: weighted_sign
357 real(kind=
dp),
dimension(3) :: v1, v2, v3
358 real(kind=
dp),
dimension(3) :: normal
359 real(kind=
dp) :: normal_length
360 real(kind=
dp) :: b1, b2, b3
363 real(kind=
dp),
dimension(3) :: edge
364 real(kind=
dp) :: tol = 1e-10_dp
366 real(kind=
dp) :: face_distance
370 v1 = triangle%pts(1)%p%x
371 v2 = triangle%pts(2)%p%x
372 v3 = triangle%pts(3)%p%x
374 normal =
cross(v2 - v1, v3 - v1)
375 normal_length = norm2(normal)
377 if (normal_length .lt. tol)
then
378 distance = huge(1.0_dp)
379 weighted_sign = 0.0_dp
382 normal = normal / normal_length
386 face_distance = dot_product(p - v1, normal)
389 b1 = dot_product(normal,
cross(v2 - v1,
projection - v1)) / normal_length
390 b2 = dot_product(normal,
cross(v3 - v2,
projection - v2)) / normal_length
391 b3 = dot_product(normal,
cross(v1 - v3,
projection - v3)) / normal_length
393 if (b1 .le. tol)
then
395 t = dot_product(p - v1, edge) / norm2(edge)
396 t =
max(0.0_dp, min(1.0_dp, t))
399 else if (b2 .le. tol)
then
401 t = dot_product(p - v2, edge) / norm2(edge)
402 t =
max(0.0_dp, min(1.0_dp, t))
405 else if (b3 .le. tol)
then
407 t = dot_product(p - v3, edge) / norm2(edge)
408 t =
max(0.0_dp, min(1.0_dp, t))
414 if (
present(weighted_sign))
then
415 weighted_sign = face_distance / distance
417 distance = sign(distance, face_distance)
427 real(kind=
dp),
dimension(3),
intent(in) :: a
428 real(kind=
dp),
dimension(3),
intent(in) :: b
429 real(kind=
dp),
dimension(3) :: c
431 c(1) = a(2) * b(3) - a(3) * b(2)
432 c(2) = a(3) * b(1) - a(1) * b(3)
433 c(3) = a(1) * b(2) - a(2) * b(1)
Copy data between host and device (or device and device)
Axis Aligned Bounding Box (aabb) Tree data structure.
integer, parameter, public aabb_null_node
Axis Aligned Bounding Box (aabb) implementation in Fortran.
Device abstraction, common interface for various accelerators.
integer, parameter, public host_to_device
integer, parameter neko_bcknd_device
integer, parameter, public dp
integer, parameter, public rp
Global precision used in computations.
Project x onto X, the space of old solutions and back again.
Module containing Signed Distance Functions.
subroutine signed_distance_field_tri_mesh(field_data, mesh, max_distance)
Signed distance field for a triangular mesh.
pure real(kind=dp) function, dimension(3) cross(a, b)
Compute cross product of two vectors.
subroutine element_distance_triangle(triangle, p, distance, weighted_sign)
Signed distance function for a triangle.
real(kind=dp) function tri_mesh_aabb_tree(tree, object_list, p, max_distance)
Signed distance function using an AABB tree.
subroutine, public signed_distance_field(field_data, object, max_distance)
Signed distance field.
subroutine element_distance(element, p, distance, weighted_sign)
Main interface for the signed distance function for an element.
real(kind=dp) function tri_mesh_brute_force(mesh, p, max_distance)
Signed distance function.
Implements a dynamic stack ADT.
Defines a triangular surface mesh.
Defines a triangular element.
subroutine, public neko_warning(warning_msg)
Reports a warning to standard output.
Axis Aligned Bounding Box (aabb) data structure.
Node type for the Axis Aligned Bounding Box (aabb) Tree.
Axis Aligned Bounding Box (aabb) Tree.
A point in with coordinates .