warp-lang 1.3.3__py3-none-manylinux2014_aarch64.whl → 1.4.0__py3-none-manylinux2014_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of warp-lang might be problematic. Click here for more details.

Files changed (106) hide show
  1. warp/__init__.py +6 -0
  2. warp/autograd.py +59 -6
  3. warp/bin/warp.so +0 -0
  4. warp/build_dll.py +8 -10
  5. warp/builtins.py +126 -4
  6. warp/codegen.py +435 -53
  7. warp/config.py +1 -1
  8. warp/context.py +678 -403
  9. warp/dlpack.py +2 -0
  10. warp/examples/benchmarks/benchmark_cloth.py +10 -0
  11. warp/examples/core/example_render_opengl.py +12 -10
  12. warp/examples/fem/example_adaptive_grid.py +251 -0
  13. warp/examples/fem/example_apic_fluid.py +1 -1
  14. warp/examples/fem/example_diffusion_3d.py +2 -2
  15. warp/examples/fem/example_magnetostatics.py +1 -1
  16. warp/examples/fem/example_streamlines.py +1 -0
  17. warp/examples/fem/utils.py +23 -4
  18. warp/examples/sim/example_cloth.py +50 -6
  19. warp/fem/__init__.py +2 -0
  20. warp/fem/adaptivity.py +493 -0
  21. warp/fem/field/field.py +2 -1
  22. warp/fem/field/nodal_field.py +18 -26
  23. warp/fem/field/test.py +4 -4
  24. warp/fem/field/trial.py +4 -4
  25. warp/fem/geometry/__init__.py +1 -0
  26. warp/fem/geometry/adaptive_nanogrid.py +843 -0
  27. warp/fem/geometry/nanogrid.py +55 -28
  28. warp/fem/space/__init__.py +1 -1
  29. warp/fem/space/nanogrid_function_space.py +69 -35
  30. warp/fem/utils.py +113 -107
  31. warp/jax_experimental.py +28 -15
  32. warp/native/array.h +0 -1
  33. warp/native/builtin.h +103 -6
  34. warp/native/bvh.cu +2 -0
  35. warp/native/cuda_util.cpp +14 -0
  36. warp/native/cuda_util.h +2 -0
  37. warp/native/error.cpp +4 -2
  38. warp/native/exports.h +99 -17
  39. warp/native/mat.h +97 -0
  40. warp/native/mesh.cpp +36 -0
  41. warp/native/mesh.cu +51 -0
  42. warp/native/mesh.h +1 -0
  43. warp/native/quat.h +43 -0
  44. warp/native/spatial.h +6 -0
  45. warp/native/vec.h +74 -0
  46. warp/native/warp.cpp +2 -1
  47. warp/native/warp.cu +10 -3
  48. warp/native/warp.h +8 -1
  49. warp/paddle.py +382 -0
  50. warp/sim/__init__.py +1 -0
  51. warp/sim/collide.py +519 -0
  52. warp/sim/integrator_euler.py +18 -5
  53. warp/sim/integrator_featherstone.py +5 -5
  54. warp/sim/integrator_vbd.py +1026 -0
  55. warp/sim/model.py +49 -23
  56. warp/stubs.py +459 -0
  57. warp/tape.py +2 -0
  58. warp/tests/aux_test_dependent.py +1 -0
  59. warp/tests/aux_test_name_clash1.py +32 -0
  60. warp/tests/aux_test_name_clash2.py +32 -0
  61. warp/tests/aux_test_square.py +1 -0
  62. warp/tests/test_array.py +188 -0
  63. warp/tests/test_async.py +3 -3
  64. warp/tests/test_atomic.py +6 -0
  65. warp/tests/test_closest_point_edge_edge.py +93 -1
  66. warp/tests/test_codegen.py +62 -15
  67. warp/tests/test_codegen_instancing.py +1457 -0
  68. warp/tests/test_collision.py +486 -0
  69. warp/tests/test_compile_consts.py +3 -28
  70. warp/tests/test_dlpack.py +170 -0
  71. warp/tests/test_examples.py +22 -8
  72. warp/tests/test_fast_math.py +10 -4
  73. warp/tests/test_fem.py +64 -0
  74. warp/tests/test_func.py +46 -0
  75. warp/tests/test_implicit_init.py +49 -0
  76. warp/tests/test_jax.py +58 -0
  77. warp/tests/test_mat.py +84 -0
  78. warp/tests/test_mesh_query_point.py +188 -0
  79. warp/tests/test_module_hashing.py +40 -0
  80. warp/tests/test_multigpu.py +3 -3
  81. warp/tests/test_overwrite.py +8 -0
  82. warp/tests/test_paddle.py +852 -0
  83. warp/tests/test_print.py +89 -0
  84. warp/tests/test_quat.py +111 -0
  85. warp/tests/test_reload.py +31 -1
  86. warp/tests/test_scalar_ops.py +2 -0
  87. warp/tests/test_static.py +412 -0
  88. warp/tests/test_streams.py +64 -3
  89. warp/tests/test_struct.py +4 -4
  90. warp/tests/test_torch.py +24 -0
  91. warp/tests/test_triangle_closest_point.py +137 -0
  92. warp/tests/test_types.py +1 -1
  93. warp/tests/test_vbd.py +386 -0
  94. warp/tests/test_vec.py +143 -0
  95. warp/tests/test_vec_scalar_ops.py +139 -0
  96. warp/tests/unittest_suites.py +12 -0
  97. warp/tests/unittest_utils.py +9 -5
  98. warp/thirdparty/dlpack.py +3 -1
  99. warp/types.py +150 -28
  100. warp/utils.py +37 -14
  101. {warp_lang-1.3.3.dist-info → warp_lang-1.4.0.dist-info}/METADATA +10 -8
  102. {warp_lang-1.3.3.dist-info → warp_lang-1.4.0.dist-info}/RECORD +105 -93
  103. warp/tests/test_point_triangle_closest_point.py +0 -143
  104. {warp_lang-1.3.3.dist-info → warp_lang-1.4.0.dist-info}/LICENSE.md +0 -0
  105. {warp_lang-1.3.3.dist-info → warp_lang-1.4.0.dist-info}/WHEEL +0 -0
  106. {warp_lang-1.3.3.dist-info → warp_lang-1.4.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,486 @@
1
+ # Copyright (c) 2024 NVIDIA CORPORATION. All rights reserved.
2
+ # NVIDIA CORPORATION and its licensors retain all intellectual property
3
+ # and proprietary rights in and to this software, related documentation
4
+ # and any modifications thereto. Any use, reproduction, disclosure or
5
+ # distribution of this software and related documentation without an express
6
+ # license agreement from NVIDIA CORPORATION is strictly prohibited.
7
+
8
+ import unittest
9
+
10
+ import warp.examples
11
+ from warp.sim.collide import *
12
+ from warp.tests.unittest_utils import *
13
+
14
+
15
+ @wp.kernel
16
+ def vertex_triangle_collision_detection_brute_force(
17
+ query_radius: float,
18
+ mesh_id: wp.uint64,
19
+ pos: wp.array(dtype=wp.vec3),
20
+ tri_indices: wp.array(dtype=wp.int32, ndim=2),
21
+ vertex_colliding_triangles: wp.array(dtype=wp.int32),
22
+ vertex_colliding_triangles_count: wp.array(dtype=wp.int32),
23
+ vertex_colliding_triangles_offsets: wp.array(dtype=wp.int32),
24
+ vertex_colliding_triangles_buffer_size: wp.array(dtype=wp.int32),
25
+ vertex_colliding_triangles_min_dist: wp.array(dtype=float),
26
+ triangle_colliding_vertices: wp.array(dtype=wp.int32),
27
+ triangle_colliding_vertices_count: wp.array(dtype=wp.int32),
28
+ triangle_colliding_vertices_buffer_offsets: wp.array(dtype=wp.int32),
29
+ triangle_colliding_vertices_buffer_sizes: wp.array(dtype=wp.int32),
30
+ triangle_colliding_vertices_min_dist: wp.array(dtype=float),
31
+ resize_flags: wp.array(dtype=wp.int32),
32
+ ):
33
+ v_index = wp.tid()
34
+ v = pos[v_index]
35
+
36
+ vertex_num_collisions = wp.int32(0)
37
+ min_dis_to_tris = query_radius
38
+ for tri_index in range(tri_indices.shape[0]):
39
+ t1 = tri_indices[tri_index, 0]
40
+ t2 = tri_indices[tri_index, 1]
41
+ t3 = tri_indices[tri_index, 2]
42
+ if vertex_adjacent_to_triangle(v_index, t1, t2, t3):
43
+ continue
44
+
45
+ u1 = pos[t1]
46
+ u2 = pos[t2]
47
+ u3 = pos[t3]
48
+
49
+ closest_p, bary, feature_type = triangle_closest_point(u1, u2, u3, v)
50
+
51
+ dis = wp.length(closest_p - v)
52
+
53
+ if dis < query_radius:
54
+ vertex_num_collisions = vertex_num_collisions + 1
55
+ min_dis_to_tris = wp.min(dis, min_dis_to_tris)
56
+
57
+ wp.atomic_add(triangle_colliding_vertices_count, tri_index, 1)
58
+ wp.atomic_min(triangle_colliding_vertices_min_dist, tri_index, dis)
59
+
60
+ vertex_colliding_triangles_count[v_index] = vertex_num_collisions
61
+ vertex_colliding_triangles_min_dist[v_index] = min_dis_to_tris
62
+
63
+
64
+ @wp.kernel
65
+ def validate_vertex_collisions(
66
+ query_radius: float,
67
+ mesh_id: wp.uint64,
68
+ pos: wp.array(dtype=wp.vec3),
69
+ tri_indices: wp.array(dtype=wp.int32, ndim=2),
70
+ vertex_colliding_triangles: wp.array(dtype=wp.int32),
71
+ vertex_colliding_triangles_count: wp.array(dtype=wp.int32),
72
+ vertex_colliding_triangles_offsets: wp.array(dtype=wp.int32),
73
+ vertex_colliding_triangles_buffer_size: wp.array(dtype=wp.int32),
74
+ vertex_colliding_triangles_min_dist: wp.array(dtype=float),
75
+ resize_flags: wp.array(dtype=wp.int32),
76
+ ):
77
+ v_index = wp.tid()
78
+ v = pos[v_index]
79
+
80
+ num_cols = vertex_colliding_triangles_count[v_index]
81
+ offset = vertex_colliding_triangles_offsets[v_index]
82
+ min_dis = vertex_colliding_triangles_min_dist[v_index]
83
+ for col in range(wp.min(num_cols, vertex_colliding_triangles_buffer_size[v_index])):
84
+ tri_index = vertex_colliding_triangles[offset + col]
85
+
86
+ t1 = tri_indices[tri_index, 0]
87
+ t2 = tri_indices[tri_index, 1]
88
+ t3 = tri_indices[tri_index, 2]
89
+ # wp.expect_eq(vertex_on_triangle(v_index, t1, t2, t3), False)
90
+
91
+ u1 = pos[t1]
92
+ u2 = pos[t2]
93
+ u3 = pos[t3]
94
+
95
+ closest_p, bary, feature_type = triangle_closest_point(u1, u2, u3, v)
96
+ dis = wp.length(closest_p - v)
97
+ wp.expect_eq(dis < query_radius, True)
98
+ wp.expect_eq(dis >= min_dis, True)
99
+
100
+ # wp.printf("vertex %d, offset %d, num cols %d, colliding with triangle: %d, dis: %f\n",
101
+ # v_index, offset, num_cols, tri_index, dis)
102
+
103
+
104
+ @wp.kernel
105
+ def validate_triangle_collisions(
106
+ query_radius: float,
107
+ mesh_id: wp.uint64,
108
+ pos: wp.array(dtype=wp.vec3),
109
+ tri_indices: wp.array(dtype=wp.int32, ndim=2),
110
+ triangle_colliding_vertices: wp.array(dtype=wp.int32),
111
+ triangle_colliding_vertices_count: wp.array(dtype=wp.int32),
112
+ triangle_colliding_vertices_buffer_offsets: wp.array(dtype=wp.int32),
113
+ triangle_colliding_vertices_buffer_sizes: wp.array(dtype=wp.int32),
114
+ triangle_colliding_vertices_min_dist: wp.array(dtype=float),
115
+ resize_flags: wp.array(dtype=wp.int32),
116
+ ):
117
+ tri_index = wp.tid()
118
+
119
+ t1 = tri_indices[tri_index, 0]
120
+ t2 = tri_indices[tri_index, 1]
121
+ t3 = tri_indices[tri_index, 2]
122
+ # wp.expect_eq(vertex_on_triangle(v_index, t1, t2, t3), False)
123
+
124
+ u1 = pos[t1]
125
+ u2 = pos[t2]
126
+ u3 = pos[t3]
127
+
128
+ num_cols = triangle_colliding_vertices_count[tri_index]
129
+ offset = triangle_colliding_vertices_buffer_offsets[tri_index]
130
+ min_dis = triangle_colliding_vertices_min_dist[tri_index]
131
+ for col in range(wp.min(num_cols, triangle_colliding_vertices_buffer_sizes[tri_index])):
132
+ v_index = triangle_colliding_vertices[offset + col]
133
+ v = pos[v_index]
134
+
135
+ closest_p, bary, feature_type = triangle_closest_point(u1, u2, u3, v)
136
+ dis = wp.length(closest_p - v)
137
+ wp.expect_eq(dis < query_radius, True)
138
+ wp.expect_eq(dis >= min_dis, True)
139
+
140
+ # wp.printf("vertex %d, offset %d, num cols %d, colliding with triangle: %d, dis: %f\n",
141
+ # v_index, offset, num_cols, tri_index, dis)
142
+
143
+
144
+ @wp.kernel
145
+ def edge_edge_collision_detection_brute_force(
146
+ query_radius: float,
147
+ bvh_id: wp.uint64,
148
+ pos: wp.array(dtype=wp.vec3),
149
+ edge_indices: wp.array(dtype=wp.int32, ndim=2),
150
+ edge_colliding_edges_offsets: wp.array(dtype=wp.int32),
151
+ edge_colliding_edges_buffer_sizes: wp.array(dtype=wp.int32),
152
+ edge_edge_parallel_epsilon: float,
153
+ # outputs
154
+ edge_colliding_edges: wp.array(dtype=wp.int32),
155
+ edge_colliding_edges_count: wp.array(dtype=wp.int32),
156
+ edge_colliding_edges_min_dist: wp.array(dtype=float),
157
+ resize_flags: wp.array(dtype=wp.int32),
158
+ ):
159
+ e_index = wp.tid()
160
+
161
+ e0_v0 = edge_indices[e_index, 2]
162
+ e0_v1 = edge_indices[e_index, 3]
163
+
164
+ e0_v0_pos = pos[e0_v0]
165
+ e0_v1_pos = pos[e0_v1]
166
+
167
+ min_dis_to_edges = query_radius
168
+ edge_num_collisions = wp.int32(0)
169
+ for e1_index in range(edge_indices.shape[0]):
170
+ e1_v0 = edge_indices[e1_index, 2]
171
+ e1_v1 = edge_indices[e1_index, 3]
172
+
173
+ if e0_v0 == e1_v0 or e0_v0 == e1_v1 or e0_v1 == e1_v0 or e0_v1 == e1_v1:
174
+ continue
175
+
176
+ e1_v0_pos = pos[e1_v0]
177
+ e1_v1_pos = pos[e1_v1]
178
+
179
+ st = wp.closest_point_edge_edge(e0_v0_pos, e0_v1_pos, e1_v0_pos, e1_v1_pos, edge_edge_parallel_epsilon)
180
+ s = st[0]
181
+ t = st[1]
182
+ c1 = e0_v0_pos + (e0_v1_pos - e0_v0_pos) * s
183
+ c2 = e1_v0_pos + (e1_v1_pos - e1_v0_pos) * t
184
+
185
+ dist = wp.length(c1 - c2)
186
+ if dist < query_radius:
187
+ edge_buffer_offset = edge_colliding_edges_offsets[e_index]
188
+ edge_buffer_size = edge_colliding_edges_offsets[e_index + 1] - edge_buffer_offset
189
+
190
+ # record e-e collision to e0, and leave e1; e1 will detect this collision from its own thread
191
+ min_dis_to_edges = wp.min(min_dis_to_edges, dist)
192
+ if edge_num_collisions < edge_buffer_size:
193
+ edge_colliding_edges[edge_buffer_offset + edge_num_collisions] = e1_index
194
+ else:
195
+ resize_flags[1] = 1
196
+
197
+ edge_num_collisions = edge_num_collisions + 1
198
+
199
+ edge_colliding_edges_count[e_index] = edge_num_collisions
200
+ edge_colliding_edges_min_dist[e_index] = min_dis_to_edges
201
+
202
+
203
+ @wp.kernel
204
+ def validate_edge_collisions(
205
+ query_radius: float,
206
+ bvh_id: wp.uint64,
207
+ pos: wp.array(dtype=wp.vec3),
208
+ edge_indices: wp.array(dtype=wp.int32, ndim=2),
209
+ edge_colliding_edges_offsets: wp.array(dtype=wp.int32),
210
+ edge_colliding_edges_buffer_sizes: wp.array(dtype=wp.int32),
211
+ edge_edge_parallel_epsilon: float,
212
+ # outputs
213
+ edge_colliding_edges: wp.array(dtype=wp.int32),
214
+ edge_colliding_edges_count: wp.array(dtype=wp.int32),
215
+ edge_colliding_edges_min_dist: wp.array(dtype=float),
216
+ resize_flags: wp.array(dtype=wp.int32),
217
+ ):
218
+ e0_index = wp.tid()
219
+
220
+ e0_v0 = edge_indices[e0_index, 2]
221
+ e0_v1 = edge_indices[e0_index, 3]
222
+
223
+ e0_v0_pos = pos[e0_v0]
224
+ e0_v1_pos = pos[e0_v1]
225
+
226
+ num_cols = edge_colliding_edges_count[e0_index]
227
+ offset = edge_colliding_edges_offsets[e0_index]
228
+ min_dist = edge_colliding_edges_min_dist[e0_index]
229
+ for col in range(wp.min(num_cols, edge_colliding_edges_buffer_sizes[e0_index])):
230
+ e1_index = edge_colliding_edges[offset + col]
231
+
232
+ e1_v0 = edge_indices[e1_index, 2]
233
+ e1_v1 = edge_indices[e1_index, 3]
234
+
235
+ if e0_v0 == e1_v0 or e0_v0 == e1_v1 or e0_v1 == e1_v0 or e0_v1 == e1_v1:
236
+ wp.expect_eq(False, True)
237
+
238
+ e1_v0_pos = pos[e1_v0]
239
+ e1_v1_pos = pos[e1_v1]
240
+
241
+ st = wp.closest_point_edge_edge(e0_v0_pos, e0_v1_pos, e1_v0_pos, e1_v1_pos, edge_edge_parallel_epsilon)
242
+ s = st[0]
243
+ t = st[1]
244
+ c1 = e0_v0_pos + (e0_v1_pos - e0_v0_pos) * s
245
+ c2 = e1_v0_pos + (e1_v1_pos - e1_v0_pos) * t
246
+
247
+ dist = wp.length(c2 - c1)
248
+
249
+ wp.expect_eq(dist >= min_dist, True)
250
+
251
+
252
+ class Example:
253
+ def __init__(self, device, vs, fs):
254
+ self.device = device
255
+
256
+ self.input_scale_factor = 1.0
257
+ self.renderer_scale_factor = 0.01
258
+ vertices = [wp.vec3(v) * self.input_scale_factor for v in vs]
259
+
260
+ builder = wp.sim.ModelBuilder()
261
+ builder.add_cloth_mesh(
262
+ pos=wp.vec3(0.0, 200.0, 0.0),
263
+ rot=wp.quat_from_axis_angle(wp.vec3(1.0, 0.0, 0.0), 0.0),
264
+ scale=1.0,
265
+ vertices=vertices,
266
+ indices=fs,
267
+ vel=wp.vec3(0.0, 0.0, 0.0),
268
+ density=0.02,
269
+ tri_ke=0,
270
+ tri_ka=0,
271
+ tri_kd=0,
272
+ )
273
+ self.model = builder.finalize(device=self.device)
274
+
275
+ self.collision_detector = TriMeshCollisionDetector(model=self.model)
276
+
277
+ def run_vertex_triangle_test(self):
278
+ rs = [1e-2, 2e-2, 5e-2, 1e-1]
279
+ for query_radius in rs:
280
+ self.collision_detector.vertex_triangle_collision_detection(query_radius)
281
+ vertex_colliding_triangles_count_1 = self.collision_detector.vertex_colliding_triangles_count.numpy()
282
+ vertex_min_dis_1 = self.collision_detector.vertex_colliding_triangles_min_dist.numpy()
283
+
284
+ triangle_colliding_vertices_count_1 = self.collision_detector.triangle_colliding_vertices_count.numpy()
285
+ triangle_min_dis_1 = self.collision_detector.triangle_colliding_vertices_min_dist.numpy()
286
+
287
+ wp.launch(
288
+ kernel=init_triangle_collision_data_kernel,
289
+ inputs=[
290
+ query_radius,
291
+ self.collision_detector.triangle_colliding_vertices_count,
292
+ self.collision_detector.triangle_colliding_vertices_min_dist,
293
+ self.collision_detector.resize_flags,
294
+ ],
295
+ dim=self.model.tri_count,
296
+ device=self.model.device,
297
+ )
298
+
299
+ wp.launch(
300
+ kernel=vertex_triangle_collision_detection_brute_force,
301
+ inputs=[
302
+ query_radius,
303
+ self.collision_detector.mesh_tris.id,
304
+ self.collision_detector.model.particle_q,
305
+ self.collision_detector.model.tri_indices,
306
+ self.collision_detector.vertex_colliding_triangles,
307
+ self.collision_detector.vertex_colliding_triangles_count,
308
+ self.collision_detector.vertex_colliding_triangles_offsets,
309
+ self.collision_detector.vertex_colliding_triangles_buffer_sizes,
310
+ self.collision_detector.vertex_colliding_triangles_min_dist,
311
+ self.collision_detector.triangle_colliding_vertices,
312
+ self.collision_detector.triangle_colliding_vertices_count,
313
+ self.collision_detector.triangle_colliding_vertices_offsets,
314
+ self.collision_detector.triangle_colliding_vertices_buffer_sizes,
315
+ self.collision_detector.triangle_colliding_vertices_min_dist,
316
+ self.collision_detector.resize_flags,
317
+ ],
318
+ dim=self.model.particle_count,
319
+ device=self.model.device,
320
+ )
321
+
322
+ vertex_colliding_triangles_count_2 = self.collision_detector.vertex_colliding_triangles_count.numpy()
323
+ vertex_min_dis_2 = self.collision_detector.vertex_colliding_triangles_min_dist.numpy()
324
+
325
+ triangle_colliding_vertices_count_2 = self.collision_detector.triangle_colliding_vertices_count.numpy()
326
+ triangle_min_dis_2 = self.collision_detector.triangle_colliding_vertices_min_dist.numpy()
327
+
328
+ assert (vertex_colliding_triangles_count_2 == vertex_colliding_triangles_count_1).all()
329
+ assert (triangle_min_dis_2 == triangle_min_dis_1).all()
330
+ assert (triangle_colliding_vertices_count_2 == triangle_colliding_vertices_count_1).all()
331
+ assert (vertex_min_dis_2 == vertex_min_dis_1).all()
332
+
333
+ wp.launch(
334
+ kernel=validate_vertex_collisions,
335
+ inputs=[
336
+ query_radius,
337
+ self.collision_detector.mesh_tris.id,
338
+ self.collision_detector.model.particle_q,
339
+ self.collision_detector.model.tri_indices,
340
+ self.collision_detector.vertex_colliding_triangles,
341
+ self.collision_detector.vertex_colliding_triangles_count,
342
+ self.collision_detector.vertex_colliding_triangles_offsets,
343
+ self.collision_detector.vertex_colliding_triangles_buffer_sizes,
344
+ self.collision_detector.vertex_colliding_triangles_min_dist,
345
+ self.collision_detector.resize_flags,
346
+ ],
347
+ dim=self.model.particle_count,
348
+ device=self.model.device,
349
+ )
350
+
351
+ wp.launch(
352
+ kernel=validate_triangle_collisions,
353
+ inputs=[
354
+ query_radius,
355
+ self.collision_detector.mesh_tris.id,
356
+ self.collision_detector.model.particle_q,
357
+ self.collision_detector.model.tri_indices,
358
+ self.collision_detector.triangle_colliding_vertices,
359
+ self.collision_detector.triangle_colliding_vertices_count,
360
+ self.collision_detector.triangle_colliding_vertices_offsets,
361
+ self.collision_detector.triangle_colliding_vertices_buffer_sizes,
362
+ self.collision_detector.triangle_colliding_vertices_min_dist,
363
+ self.collision_detector.resize_flags,
364
+ ],
365
+ dim=self.model.tri_count,
366
+ device=self.model.device,
367
+ )
368
+
369
+ def run_edge_edge_test(self):
370
+ rs = [1e-2, 2e-2, 5e-2, 1e-1]
371
+ edge_edge_parallel_epsilon = 1e-5
372
+ for query_radius in rs:
373
+ self.collision_detector.edge_edge_collision_detection(query_radius)
374
+ edge_colliding_edges_count_1 = self.collision_detector.edge_colliding_edges_count.numpy()
375
+ edge_min_dist_1 = self.collision_detector.edge_colliding_edges_min_dist.numpy()
376
+
377
+ print(edge_colliding_edges_count_1)
378
+
379
+ wp.launch(
380
+ kernel=edge_edge_collision_detection_brute_force,
381
+ inputs=[
382
+ query_radius,
383
+ self.collision_detector.bvh_edges.id,
384
+ self.collision_detector.model.particle_q,
385
+ self.collision_detector.model.edge_indices,
386
+ self.collision_detector.edge_colliding_edges_offsets,
387
+ self.collision_detector.edge_colliding_edges_buffer_sizes,
388
+ edge_edge_parallel_epsilon,
389
+ ],
390
+ outputs=[
391
+ self.collision_detector.edge_colliding_edges,
392
+ self.collision_detector.edge_colliding_edges_count,
393
+ self.collision_detector.edge_colliding_edges_min_dist,
394
+ self.collision_detector.resize_flags,
395
+ ],
396
+ dim=self.model.edge_count,
397
+ device=self.model.device,
398
+ )
399
+
400
+ edge_colliding_edges_count_2 = self.collision_detector.edge_colliding_edges_count.numpy()
401
+ edge_min_dist_2 = self.collision_detector.edge_colliding_edges_min_dist.numpy()
402
+
403
+ assert (edge_colliding_edges_count_2 == edge_colliding_edges_count_1).all()
404
+ assert (edge_min_dist_1 == edge_min_dist_2).all()
405
+
406
+ wp.launch(
407
+ kernel=validate_edge_collisions,
408
+ inputs=[
409
+ query_radius,
410
+ self.collision_detector.bvh_edges.id,
411
+ self.collision_detector.model.particle_q,
412
+ self.collision_detector.model.edge_indices,
413
+ self.collision_detector.edge_colliding_edges_offsets,
414
+ self.collision_detector.edge_colliding_edges_buffer_sizes,
415
+ edge_edge_parallel_epsilon,
416
+ ],
417
+ outputs=[
418
+ self.collision_detector.edge_colliding_edges,
419
+ self.collision_detector.edge_colliding_edges_count,
420
+ self.collision_detector.edge_colliding_edges_min_dist,
421
+ self.collision_detector.resize_flags,
422
+ ],
423
+ dim=self.model.particle_count,
424
+ device=self.model.device,
425
+ )
426
+
427
+ def set_points_fixed(self, model, fixed_particles):
428
+ if len(fixed_particles):
429
+ flags = model.particle_flags.numpy()
430
+ for fixed_v_id in fixed_particles:
431
+ flags[fixed_v_id] = wp.uint32(int(flags[fixed_v_id]) & ~int(PARTICLE_FLAG_ACTIVE))
432
+
433
+ model.particle_flags = wp.array(flags, device=model.device)
434
+
435
+
436
+ @unittest.skipUnless(USD_AVAILABLE, "Requires usd-core")
437
+ def test_vertex_triangle_collision(test, device):
438
+ from pxr import Usd, UsdGeom
439
+
440
+ def get_data():
441
+ usd_stage = Usd.Stage.Open(os.path.join(warp.examples.get_asset_directory(), "bunny.usd"))
442
+ usd_geom = UsdGeom.Mesh(usd_stage.GetPrimAtPath("/root/bunny"))
443
+
444
+ vertices = np.array(usd_geom.GetPointsAttr().Get())
445
+ faces = np.array(usd_geom.GetFaceVertexIndicesAttr().Get())
446
+
447
+ return vertices, faces
448
+
449
+ vertices, faces = get_data()
450
+
451
+ sim = Example(device, vertices, faces)
452
+ sim.run_vertex_triangle_test()
453
+
454
+
455
+ @unittest.skipUnless(USD_AVAILABLE, "Requires usd-core")
456
+ def test_edge_edge_collision(test, device):
457
+ from pxr import Usd, UsdGeom
458
+
459
+ def get_data():
460
+ usd_stage = Usd.Stage.Open(os.path.join(warp.examples.get_asset_directory(), "bunny.usd"))
461
+ usd_geom = UsdGeom.Mesh(usd_stage.GetPrimAtPath("/root/bunny"))
462
+
463
+ vertices = np.array(usd_geom.GetPointsAttr().Get())
464
+ faces = np.array(usd_geom.GetFaceVertexIndicesAttr().Get())
465
+
466
+ return vertices, faces
467
+
468
+ vertices, faces = get_data()
469
+
470
+ sim = Example(device, vertices, faces)
471
+ sim.run_edge_edge_test()
472
+
473
+
474
+ devices = get_test_devices()
475
+
476
+
477
+ class TestCollision(unittest.TestCase):
478
+ pass
479
+
480
+
481
+ add_function_test(TestCollision, "test_vertex_triangle_collision", test_vertex_triangle_collision, devices=devices)
482
+ add_function_test(TestCollision, "test_edge_edge_collision", test_vertex_triangle_collision, devices=devices)
483
+
484
+ if __name__ == "__main__":
485
+ wp.clear_kernel_cache()
486
+ unittest.main(verbosity=2)
@@ -88,15 +88,6 @@ def test_hash_global_capture(test, device):
88
88
  a = 0
89
89
  wp.launch(test_int, (1,), inputs=[a], device=device)
90
90
 
91
- module_constants = wp.get_module(test_int.__module__).constants
92
-
93
- # Ensure the expected constants and values are in the dictionary used in hashing
94
- # Depending on what's been launched already, there might be additional constants present
95
- test.assertEqual(module_constants["Foobar.ONE"], 1)
96
- test.assertEqual(module_constants["Foobar.TWO"], 2)
97
- test.assertEqual(module_constants["warp.tests.aux_test_compile_consts_dummy.MINUS_ONE"], -1)
98
- test.assertEqual(module_constants["LOCAL_ONE"], 1)
99
-
100
91
 
101
92
  def test_hash_redefine_kernel(test, device):
102
93
  """This test defines a second ``test_function`` so that the second launch returns the correct result."""
@@ -113,8 +104,6 @@ def test_hash_redefine_kernel(test, device):
113
104
  test.assertEqual(test_array.numpy()[0], 1.0)
114
105
 
115
106
  module_hash_0 = wp.get_module(test_function.__module__).hash_module()
116
- module_constants = wp.get_module(test_function.__module__).constants
117
- test.assertEqual(module_constants["TEST_CONSTANT"], 1.0)
118
107
 
119
108
  @wp.kernel
120
109
  def test_function(data: wp.array(dtype=wp.float32)):
@@ -127,9 +116,7 @@ def test_hash_redefine_kernel(test, device):
127
116
  test.assertEqual(test_array.numpy()[0], 2.0)
128
117
 
129
118
  module_hash_1 = wp.get_module(test_function.__module__).hash_module()
130
- module_constants = wp.get_module(test_function.__module__).constants
131
119
 
132
- test.assertEqual(module_constants["TEST_CONSTANT"], 2.0)
133
120
  test.assertNotEqual(module_hash_0, module_hash_1)
134
121
 
135
122
 
@@ -152,19 +139,12 @@ def test_hash_redefine_constant_only(test, device):
152
139
 
153
140
  module_hash_0 = wp.get_module(test_function.__module__).hash_module()
154
141
 
155
- module_constants = wp.get_module(test_function.__module__).constants
156
- test.assertEqual(module_constants["TEST_CONSTANT"], 1.0)
157
-
158
142
  TEST_CONSTANT = wp.constant(2.0)
159
- module_hash_1 = wp.get_module(test_function.__module__).hash_module(recompute_content_hash=True)
160
- module_constants = wp.get_module(test_function.__module__).constants
161
- test.assertEqual(module_constants["TEST_CONSTANT"], 2.0)
143
+ module_hash_1 = wp.get_module(test_function.__module__).hash_module()
162
144
  test.assertNotEqual(module_hash_0, module_hash_1, "Module hashes should be different if TEST_CONSTANT is changed.")
163
145
 
164
146
  TEST_CONSTANT = wp.constant(1.0)
165
- module_hash_2 = wp.get_module(test_function.__module__).hash_module(recompute_content_hash=True)
166
- module_constants = wp.get_module(test_function.__module__).constants
167
- test.assertEqual(module_constants["TEST_CONSTANT"], 1.0)
147
+ module_hash_2 = wp.get_module(test_function.__module__).hash_module()
168
148
  test.assertEqual(module_hash_0, module_hash_2, "Module hashes should be the same if TEST_CONSTANT is the same.")
169
149
 
170
150
 
@@ -187,16 +167,11 @@ def test_hash_shadowed_var(test, device):
187
167
  test.assertEqual(test_array.numpy()[0], 14.0)
188
168
 
189
169
  module_hash_0 = wp.get_module(test_function.__module__).hash_module()
190
- module_constants = wp.get_module(test_function.__module__).constants
191
-
192
- test.assertFalse("TEST_CONSTANT_SHADOW_0" in module_constants, "Constant should not be in dictionary.")
193
- test.assertFalse("TEST_CONSTANT_SHADOW_1" in module_constants, "Constant should not be in dictionary.")
194
- test.assertFalse("TEST_CONSTANT_SHADOW_2" in module_constants, "Constant should not be in dictionary.")
195
170
 
196
171
  TEST_CONSTANT_SHADOW_0 = wp.constant(0.0)
197
172
  TEST_CONSTANT_SHADOW_1 = wp.constant(0.0)
198
173
  TEST_CONSTANT_SHADOW_2 = wp.constant(0.0)
199
- module_hash_1 = wp.get_module(test_function.__module__).hash_module(recompute_content_hash=True)
174
+ module_hash_1 = wp.get_module(test_function.__module__).hash_module()
200
175
  test.assertEqual(module_hash_0, module_hash_1, "Module hashes should be the same since all constants are shadowed.")
201
176
 
202
177