warp-lang 1.7.2rc1__py3-none-macosx_10_13_universal2.whl → 1.8.1__py3-none-macosx_10_13_universal2.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 (192) hide show
  1. warp/__init__.py +3 -1
  2. warp/__init__.pyi +3489 -1
  3. warp/autograd.py +45 -122
  4. warp/bin/libwarp.dylib +0 -0
  5. warp/build.py +241 -252
  6. warp/build_dll.py +130 -26
  7. warp/builtins.py +1907 -384
  8. warp/codegen.py +272 -104
  9. warp/config.py +12 -1
  10. warp/constants.py +1 -1
  11. warp/context.py +770 -238
  12. warp/dlpack.py +1 -1
  13. warp/examples/benchmarks/benchmark_cloth.py +2 -2
  14. warp/examples/benchmarks/benchmark_tile_sort.py +155 -0
  15. warp/examples/core/example_sample_mesh.py +1 -1
  16. warp/examples/core/example_spin_lock.py +93 -0
  17. warp/examples/core/example_work_queue.py +118 -0
  18. warp/examples/fem/example_adaptive_grid.py +5 -5
  19. warp/examples/fem/example_apic_fluid.py +1 -1
  20. warp/examples/fem/example_burgers.py +1 -1
  21. warp/examples/fem/example_convection_diffusion.py +9 -6
  22. warp/examples/fem/example_darcy_ls_optimization.py +489 -0
  23. warp/examples/fem/example_deformed_geometry.py +1 -1
  24. warp/examples/fem/example_diffusion.py +2 -2
  25. warp/examples/fem/example_diffusion_3d.py +1 -1
  26. warp/examples/fem/example_distortion_energy.py +1 -1
  27. warp/examples/fem/example_elastic_shape_optimization.py +387 -0
  28. warp/examples/fem/example_magnetostatics.py +5 -3
  29. warp/examples/fem/example_mixed_elasticity.py +5 -3
  30. warp/examples/fem/example_navier_stokes.py +11 -9
  31. warp/examples/fem/example_nonconforming_contact.py +5 -3
  32. warp/examples/fem/example_streamlines.py +8 -3
  33. warp/examples/fem/utils.py +9 -8
  34. warp/examples/interop/example_jax_callable.py +34 -4
  35. warp/examples/interop/example_jax_ffi_callback.py +2 -2
  36. warp/examples/interop/example_jax_kernel.py +27 -1
  37. warp/examples/optim/example_drone.py +1 -1
  38. warp/examples/sim/example_cloth.py +1 -1
  39. warp/examples/sim/example_cloth_self_contact.py +48 -54
  40. warp/examples/tile/example_tile_block_cholesky.py +502 -0
  41. warp/examples/tile/example_tile_cholesky.py +2 -1
  42. warp/examples/tile/example_tile_convolution.py +1 -1
  43. warp/examples/tile/example_tile_filtering.py +1 -1
  44. warp/examples/tile/example_tile_matmul.py +1 -1
  45. warp/examples/tile/example_tile_mlp.py +2 -0
  46. warp/fabric.py +7 -7
  47. warp/fem/__init__.py +5 -0
  48. warp/fem/adaptivity.py +1 -1
  49. warp/fem/cache.py +152 -63
  50. warp/fem/dirichlet.py +2 -2
  51. warp/fem/domain.py +136 -6
  52. warp/fem/field/field.py +141 -99
  53. warp/fem/field/nodal_field.py +85 -39
  54. warp/fem/field/virtual.py +99 -52
  55. warp/fem/geometry/adaptive_nanogrid.py +91 -86
  56. warp/fem/geometry/closest_point.py +13 -0
  57. warp/fem/geometry/deformed_geometry.py +102 -40
  58. warp/fem/geometry/element.py +56 -2
  59. warp/fem/geometry/geometry.py +323 -22
  60. warp/fem/geometry/grid_2d.py +157 -62
  61. warp/fem/geometry/grid_3d.py +116 -20
  62. warp/fem/geometry/hexmesh.py +86 -20
  63. warp/fem/geometry/nanogrid.py +166 -86
  64. warp/fem/geometry/partition.py +59 -25
  65. warp/fem/geometry/quadmesh.py +86 -135
  66. warp/fem/geometry/tetmesh.py +47 -119
  67. warp/fem/geometry/trimesh.py +77 -270
  68. warp/fem/integrate.py +181 -95
  69. warp/fem/linalg.py +25 -58
  70. warp/fem/operator.py +124 -27
  71. warp/fem/quadrature/pic_quadrature.py +36 -14
  72. warp/fem/quadrature/quadrature.py +40 -16
  73. warp/fem/space/__init__.py +1 -1
  74. warp/fem/space/basis_function_space.py +66 -46
  75. warp/fem/space/basis_space.py +17 -4
  76. warp/fem/space/dof_mapper.py +1 -1
  77. warp/fem/space/function_space.py +2 -2
  78. warp/fem/space/grid_2d_function_space.py +4 -1
  79. warp/fem/space/hexmesh_function_space.py +4 -2
  80. warp/fem/space/nanogrid_function_space.py +3 -1
  81. warp/fem/space/partition.py +11 -2
  82. warp/fem/space/quadmesh_function_space.py +4 -1
  83. warp/fem/space/restriction.py +5 -2
  84. warp/fem/space/shape/__init__.py +10 -8
  85. warp/fem/space/tetmesh_function_space.py +4 -1
  86. warp/fem/space/topology.py +52 -21
  87. warp/fem/space/trimesh_function_space.py +4 -1
  88. warp/fem/utils.py +53 -8
  89. warp/jax.py +1 -2
  90. warp/jax_experimental/ffi.py +210 -67
  91. warp/jax_experimental/xla_ffi.py +37 -24
  92. warp/math.py +171 -1
  93. warp/native/array.h +103 -4
  94. warp/native/builtin.h +182 -35
  95. warp/native/coloring.cpp +6 -2
  96. warp/native/cuda_util.cpp +1 -1
  97. warp/native/exports.h +118 -63
  98. warp/native/intersect.h +5 -5
  99. warp/native/mat.h +8 -13
  100. warp/native/mathdx.cpp +11 -5
  101. warp/native/matnn.h +1 -123
  102. warp/native/mesh.h +1 -1
  103. warp/native/quat.h +34 -6
  104. warp/native/rand.h +7 -7
  105. warp/native/sparse.cpp +121 -258
  106. warp/native/sparse.cu +181 -274
  107. warp/native/spatial.h +305 -17
  108. warp/native/svd.h +23 -8
  109. warp/native/tile.h +603 -73
  110. warp/native/tile_radix_sort.h +1112 -0
  111. warp/native/tile_reduce.h +239 -13
  112. warp/native/tile_scan.h +240 -0
  113. warp/native/tuple.h +189 -0
  114. warp/native/vec.h +10 -20
  115. warp/native/warp.cpp +36 -4
  116. warp/native/warp.cu +588 -52
  117. warp/native/warp.h +47 -74
  118. warp/optim/linear.py +5 -1
  119. warp/paddle.py +7 -8
  120. warp/py.typed +0 -0
  121. warp/render/render_opengl.py +110 -80
  122. warp/render/render_usd.py +124 -62
  123. warp/sim/__init__.py +9 -0
  124. warp/sim/collide.py +253 -80
  125. warp/sim/graph_coloring.py +8 -1
  126. warp/sim/import_mjcf.py +4 -3
  127. warp/sim/import_usd.py +11 -7
  128. warp/sim/integrator.py +5 -2
  129. warp/sim/integrator_euler.py +1 -1
  130. warp/sim/integrator_featherstone.py +1 -1
  131. warp/sim/integrator_vbd.py +761 -322
  132. warp/sim/integrator_xpbd.py +1 -1
  133. warp/sim/model.py +265 -260
  134. warp/sim/utils.py +10 -7
  135. warp/sparse.py +303 -166
  136. warp/tape.py +54 -51
  137. warp/tests/cuda/test_conditional_captures.py +1046 -0
  138. warp/tests/cuda/test_streams.py +1 -1
  139. warp/tests/geometry/test_volume.py +2 -2
  140. warp/tests/interop/test_dlpack.py +9 -9
  141. warp/tests/interop/test_jax.py +0 -1
  142. warp/tests/run_coverage_serial.py +1 -1
  143. warp/tests/sim/disabled_kinematics.py +2 -2
  144. warp/tests/sim/{test_vbd.py → test_cloth.py} +378 -112
  145. warp/tests/sim/test_collision.py +159 -51
  146. warp/tests/sim/test_coloring.py +91 -2
  147. warp/tests/test_array.py +254 -2
  148. warp/tests/test_array_reduce.py +2 -2
  149. warp/tests/test_assert.py +53 -0
  150. warp/tests/test_atomic_cas.py +312 -0
  151. warp/tests/test_codegen.py +142 -19
  152. warp/tests/test_conditional.py +47 -1
  153. warp/tests/test_ctypes.py +0 -20
  154. warp/tests/test_devices.py +8 -0
  155. warp/tests/test_fabricarray.py +4 -2
  156. warp/tests/test_fem.py +58 -25
  157. warp/tests/test_func.py +42 -1
  158. warp/tests/test_grad.py +1 -1
  159. warp/tests/test_lerp.py +1 -3
  160. warp/tests/test_map.py +481 -0
  161. warp/tests/test_mat.py +23 -24
  162. warp/tests/test_quat.py +28 -15
  163. warp/tests/test_rounding.py +10 -38
  164. warp/tests/test_runlength_encode.py +7 -7
  165. warp/tests/test_smoothstep.py +1 -1
  166. warp/tests/test_sparse.py +83 -2
  167. warp/tests/test_spatial.py +507 -1
  168. warp/tests/test_static.py +48 -0
  169. warp/tests/test_struct.py +2 -2
  170. warp/tests/test_tape.py +38 -0
  171. warp/tests/test_tuple.py +265 -0
  172. warp/tests/test_types.py +2 -2
  173. warp/tests/test_utils.py +24 -18
  174. warp/tests/test_vec.py +38 -408
  175. warp/tests/test_vec_constructors.py +325 -0
  176. warp/tests/tile/test_tile.py +438 -131
  177. warp/tests/tile/test_tile_mathdx.py +518 -14
  178. warp/tests/tile/test_tile_matmul.py +179 -0
  179. warp/tests/tile/test_tile_reduce.py +307 -5
  180. warp/tests/tile/test_tile_shared_memory.py +136 -7
  181. warp/tests/tile/test_tile_sort.py +121 -0
  182. warp/tests/unittest_suites.py +14 -6
  183. warp/types.py +462 -308
  184. warp/utils.py +647 -86
  185. {warp_lang-1.7.2rc1.dist-info → warp_lang-1.8.1.dist-info}/METADATA +20 -6
  186. {warp_lang-1.7.2rc1.dist-info → warp_lang-1.8.1.dist-info}/RECORD +189 -175
  187. warp/stubs.py +0 -3381
  188. warp/tests/sim/test_xpbd.py +0 -399
  189. warp/tests/test_mlp.py +0 -282
  190. {warp_lang-1.7.2rc1.dist-info → warp_lang-1.8.1.dist-info}/WHEEL +0 -0
  191. {warp_lang-1.7.2rc1.dist-info → warp_lang-1.8.1.dist-info}/licenses/LICENSE.md +0 -0
  192. {warp_lang-1.7.2rc1.dist-info → warp_lang-1.8.1.dist-info}/top_level.txt +0 -0
@@ -78,7 +78,7 @@ def vertex_triangle_collision_detection_brute_force(
78
78
 
79
79
 
80
80
  @wp.kernel
81
- def validate_vertex_collisions(
81
+ def vertex_triangle_collision_detection_brute_force_no_triangle_buffers(
82
82
  query_radius: float,
83
83
  bvh_id: wp.uint64,
84
84
  pos: wp.array(dtype=wp.vec3),
@@ -88,33 +88,82 @@ def validate_vertex_collisions(
88
88
  vertex_colliding_triangles_offsets: wp.array(dtype=wp.int32),
89
89
  vertex_colliding_triangles_buffer_size: wp.array(dtype=wp.int32),
90
90
  vertex_colliding_triangles_min_dist: wp.array(dtype=float),
91
+ triangle_colliding_vertices_min_dist: wp.array(dtype=float),
91
92
  resize_flags: wp.array(dtype=wp.int32),
92
93
  ):
93
94
  v_index = wp.tid()
94
95
  v = pos[v_index]
95
96
 
96
- num_cols = vertex_colliding_triangles_count[v_index]
97
- offset = vertex_colliding_triangles_offsets[v_index]
98
- min_dis = vertex_colliding_triangles_min_dist[v_index]
99
- for col in range(wp.min(num_cols, vertex_colliding_triangles_buffer_size[v_index])):
100
- tri_index = vertex_colliding_triangles[offset + col]
101
-
97
+ vertex_num_collisions = wp.int32(0)
98
+ min_dis_to_tris = query_radius
99
+ for tri_index in range(tri_indices.shape[0]):
102
100
  t1 = tri_indices[tri_index, 0]
103
101
  t2 = tri_indices[tri_index, 1]
104
102
  t3 = tri_indices[tri_index, 2]
105
- # wp.expect_eq(vertex_on_triangle(v_index, t1, t2, t3), False)
103
+ if vertex_adjacent_to_triangle(v_index, t1, t2, t3):
104
+ continue
106
105
 
107
106
  u1 = pos[t1]
108
107
  u2 = pos[t2]
109
108
  u3 = pos[t3]
110
109
 
111
110
  closest_p, bary, feature_type = triangle_closest_point(u1, u2, u3, v)
111
+
112
112
  dis = wp.length(closest_p - v)
113
- wp.expect_eq(dis < query_radius, True)
114
- wp.expect_eq(dis >= min_dis, True)
115
113
 
116
- # wp.printf("vertex %d, offset %d, num cols %d, colliding with triangle: %d, dis: %f\n",
117
- # v_index, offset, num_cols, tri_index, dis)
114
+ if dis < query_radius:
115
+ vertex_num_collisions = vertex_num_collisions + 1
116
+ min_dis_to_tris = wp.min(dis, min_dis_to_tris)
117
+
118
+ wp.atomic_min(triangle_colliding_vertices_min_dist, tri_index, dis)
119
+
120
+ vertex_colliding_triangles_count[v_index] = vertex_num_collisions
121
+ vertex_colliding_triangles_min_dist[v_index] = min_dis_to_tris
122
+
123
+
124
+ @wp.kernel
125
+ def validate_vertex_collisions(
126
+ query_radius: float,
127
+ bvh_id: wp.uint64,
128
+ pos: wp.array(dtype=wp.vec3),
129
+ tri_indices: wp.array(dtype=wp.int32, ndim=2),
130
+ vertex_colliding_triangles: wp.array(dtype=wp.int32),
131
+ vertex_colliding_triangles_count: wp.array(dtype=wp.int32),
132
+ vertex_colliding_triangles_offsets: wp.array(dtype=wp.int32),
133
+ vertex_colliding_triangles_buffer_size: wp.array(dtype=wp.int32),
134
+ vertex_colliding_triangles_min_dist: wp.array(dtype=float),
135
+ resize_flags: wp.array(dtype=wp.int32),
136
+ ):
137
+ v_index = wp.tid()
138
+ v = pos[v_index]
139
+
140
+ num_cols = vertex_colliding_triangles_count[v_index]
141
+ offset = vertex_colliding_triangles_offsets[v_index]
142
+ min_dis = vertex_colliding_triangles_min_dist[v_index]
143
+ for col in range(vertex_colliding_triangles_buffer_size[v_index]):
144
+ vertex_index = vertex_colliding_triangles[2 * (offset + col)]
145
+ tri_index = vertex_colliding_triangles[2 * (offset + col) + 1]
146
+ if col < num_cols:
147
+ t1 = tri_indices[tri_index, 0]
148
+ t2 = tri_indices[tri_index, 1]
149
+ t3 = tri_indices[tri_index, 2]
150
+ # wp.expect_eq(vertex_on_triangle(v_index, t1, t2, t3), False)
151
+
152
+ u1 = pos[t1]
153
+ u2 = pos[t2]
154
+ u3 = pos[t3]
155
+
156
+ closest_p, bary, feature_type = triangle_closest_point(u1, u2, u3, v)
157
+ dis = wp.length(closest_p - v)
158
+ wp.expect_eq(dis < query_radius, True)
159
+ wp.expect_eq(dis >= min_dis, True)
160
+ wp.expect_eq(v_index == vertex_colliding_triangles[2 * (offset + col)], True)
161
+
162
+ # wp.printf("vertex %d, offset %d, num cols %d, colliding with triangle: %d, dis: %f\n",
163
+ # v_index, offset, num_cols, tri_index, dis)
164
+ else:
165
+ wp.expect_eq(vertex_index == -1, True)
166
+ wp.expect_eq(tri_index == -1, True)
118
167
 
119
168
 
120
169
  @wp.kernel
@@ -242,30 +291,35 @@ def validate_edge_collisions(
242
291
  num_cols = edge_colliding_edges_count[e0_index]
243
292
  offset = edge_colliding_edges_offsets[e0_index]
244
293
  min_dist = edge_colliding_edges_min_dist[e0_index]
245
- for col in range(wp.min(num_cols, edge_colliding_edges_buffer_sizes[e0_index])):
246
- e1_index = edge_colliding_edges[offset + col]
294
+ for col in range(edge_colliding_edges_buffer_sizes[e0_index]):
295
+ e1_index = edge_colliding_edges[2 * (offset + col) + 1]
247
296
 
248
- e1_v0 = edge_indices[e1_index, 2]
249
- e1_v1 = edge_indices[e1_index, 3]
297
+ if col < num_cols:
298
+ e1_v0 = edge_indices[e1_index, 2]
299
+ e1_v1 = edge_indices[e1_index, 3]
250
300
 
251
- if e0_v0 == e1_v0 or e0_v0 == e1_v1 or e0_v1 == e1_v0 or e0_v1 == e1_v1:
252
- wp.expect_eq(False, True)
301
+ if e0_v0 == e1_v0 or e0_v0 == e1_v1 or e0_v1 == e1_v0 or e0_v1 == e1_v1:
302
+ wp.expect_eq(False, True)
253
303
 
254
- e1_v0_pos = pos[e1_v0]
255
- e1_v1_pos = pos[e1_v1]
304
+ e1_v0_pos = pos[e1_v0]
305
+ e1_v1_pos = pos[e1_v1]
256
306
 
257
- st = wp.closest_point_edge_edge(e0_v0_pos, e0_v1_pos, e1_v0_pos, e1_v1_pos, edge_edge_parallel_epsilon)
258
- s = st[0]
259
- t = st[1]
260
- c1 = e0_v0_pos + (e0_v1_pos - e0_v0_pos) * s
261
- c2 = e1_v0_pos + (e1_v1_pos - e1_v0_pos) * t
307
+ st = wp.closest_point_edge_edge(e0_v0_pos, e0_v1_pos, e1_v0_pos, e1_v1_pos, edge_edge_parallel_epsilon)
308
+ s = st[0]
309
+ t = st[1]
310
+ c1 = e0_v0_pos + (e0_v1_pos - e0_v0_pos) * s
311
+ c2 = e1_v0_pos + (e1_v1_pos - e1_v0_pos) * t
262
312
 
263
- dist = wp.length(c2 - c1)
313
+ dist = wp.length(c2 - c1)
264
314
 
265
- wp.expect_eq(dist >= min_dist, True)
315
+ wp.expect_eq(dist >= min_dist, True)
316
+ wp.expect_eq(e0_index == edge_colliding_edges[2 * (offset + col)], True)
317
+ else:
318
+ wp.expect_eq(e1_index == -1, True)
319
+ wp.expect_eq(edge_colliding_edges[2 * (offset + col)] == -1, True)
266
320
 
267
321
 
268
- def init_model(vs, fs, device):
322
+ def init_model(vs, fs, device, record_triangle_contacting_vertices=True):
269
323
  vertices = [wp.vec3(v) for v in vs]
270
324
 
271
325
  builder = wp.sim.ModelBuilder()
@@ -283,7 +337,7 @@ def init_model(vs, fs, device):
283
337
  )
284
338
  model = builder.finalize(device=device)
285
339
 
286
- collision_detector = TriMeshCollisionDetector(model=model)
340
+ collision_detector = TriMeshCollisionDetector(model=model, record_triangle_contacting_vertices=True)
287
341
 
288
342
  return model, collision_detector
289
343
 
@@ -304,7 +358,8 @@ def get_data():
304
358
  def test_vertex_triangle_collision(test, device):
305
359
  vertices, faces = get_data()
306
360
 
307
- model, collision_detector = init_model(vertices, faces, device)
361
+ # record triangle contacting vertices
362
+ model, collision_detector = init_model(vertices, faces, device, True)
308
363
 
309
364
  rs = [1e-2, 2e-2, 5e-2, 1e-1]
310
365
 
@@ -316,6 +371,42 @@ def test_vertex_triangle_collision(test, device):
316
371
  triangle_colliding_vertices_count_1 = collision_detector.triangle_colliding_vertices_count.numpy()
317
372
  triangle_min_dis_1 = collision_detector.triangle_colliding_vertices_min_dist.numpy()
318
373
 
374
+ wp.launch(
375
+ kernel=validate_vertex_collisions,
376
+ inputs=[
377
+ query_radius,
378
+ collision_detector.bvh_tris.id,
379
+ collision_detector.model.particle_q,
380
+ collision_detector.model.tri_indices,
381
+ collision_detector.vertex_colliding_triangles,
382
+ collision_detector.vertex_colliding_triangles_count,
383
+ collision_detector.vertex_colliding_triangles_offsets,
384
+ collision_detector.vertex_colliding_triangles_buffer_sizes,
385
+ collision_detector.vertex_colliding_triangles_min_dist,
386
+ collision_detector.resize_flags,
387
+ ],
388
+ dim=model.particle_count,
389
+ device=device,
390
+ )
391
+
392
+ wp.launch(
393
+ kernel=validate_triangle_collisions,
394
+ inputs=[
395
+ query_radius,
396
+ collision_detector.bvh_tris.id,
397
+ collision_detector.model.particle_q,
398
+ collision_detector.model.tri_indices,
399
+ collision_detector.triangle_colliding_vertices,
400
+ collision_detector.triangle_colliding_vertices_count,
401
+ collision_detector.triangle_colliding_vertices_offsets,
402
+ collision_detector.triangle_colliding_vertices_buffer_sizes,
403
+ collision_detector.triangle_colliding_vertices_min_dist,
404
+ collision_detector.resize_flags,
405
+ ],
406
+ dim=model.tri_count,
407
+ device=model.device,
408
+ )
409
+
319
410
  wp.launch(
320
411
  kernel=init_triangle_collision_data_kernel,
321
412
  inputs=[
@@ -325,7 +416,7 @@ def test_vertex_triangle_collision(test, device):
325
416
  collision_detector.resize_flags,
326
417
  ],
327
418
  dim=model.tri_count,
328
- device=device,
419
+ device=model.device,
329
420
  )
330
421
 
331
422
  wp.launch(
@@ -348,7 +439,7 @@ def test_vertex_triangle_collision(test, device):
348
439
  collision_detector.resize_flags,
349
440
  ],
350
441
  dim=model.particle_count,
351
- device=device,
442
+ device=model.device,
352
443
  )
353
444
 
354
445
  vertex_colliding_triangles_count_2 = collision_detector.vertex_colliding_triangles_count.numpy()
@@ -362,6 +453,18 @@ def test_vertex_triangle_collision(test, device):
362
453
  assert_np_equal(triangle_colliding_vertices_count_2, triangle_colliding_vertices_count_1)
363
454
  assert_np_equal(vertex_min_dis_2, vertex_min_dis_1)
364
455
 
456
+ # do not record triangle contacting vertices
457
+ model, collision_detector = init_model(vertices, faces, device, False)
458
+
459
+ rs = [1e-2, 2e-2, 5e-2, 1e-1]
460
+
461
+ for query_radius in rs:
462
+ collision_detector.vertex_triangle_collision_detection(query_radius)
463
+ vertex_colliding_triangles_count_1 = collision_detector.vertex_colliding_triangles_count.numpy()
464
+ vertex_min_dis_1 = collision_detector.vertex_colliding_triangles_min_dist.numpy()
465
+
466
+ triangle_min_dis_1 = collision_detector.triangle_colliding_vertices_min_dist.numpy()
467
+
365
468
  wp.launch(
366
469
  kernel=validate_vertex_collisions,
367
470
  inputs=[
@@ -381,24 +484,31 @@ def test_vertex_triangle_collision(test, device):
381
484
  )
382
485
 
383
486
  wp.launch(
384
- kernel=validate_triangle_collisions,
487
+ kernel=vertex_triangle_collision_detection_brute_force_no_triangle_buffers,
385
488
  inputs=[
386
489
  query_radius,
387
490
  collision_detector.bvh_tris.id,
388
491
  collision_detector.model.particle_q,
389
492
  collision_detector.model.tri_indices,
390
- collision_detector.triangle_colliding_vertices,
391
- collision_detector.triangle_colliding_vertices_count,
392
- collision_detector.triangle_colliding_vertices_offsets,
393
- collision_detector.triangle_colliding_vertices_buffer_sizes,
493
+ collision_detector.vertex_colliding_triangles,
494
+ collision_detector.vertex_colliding_triangles_count,
495
+ collision_detector.vertex_colliding_triangles_offsets,
496
+ collision_detector.vertex_colliding_triangles_buffer_sizes,
497
+ collision_detector.vertex_colliding_triangles_min_dist,
394
498
  collision_detector.triangle_colliding_vertices_min_dist,
395
499
  collision_detector.resize_flags,
396
500
  ],
397
- dim=model.tri_count,
398
- device=device,
501
+ dim=model.particle_count,
502
+ device=model.device,
399
503
  )
400
504
 
401
- wp.synchronize_device(device)
505
+ vertex_colliding_triangles_count_2 = collision_detector.vertex_colliding_triangles_count.numpy()
506
+ vertex_min_dis_2 = collision_detector.vertex_colliding_triangles_min_dist.numpy()
507
+ triangle_min_dis_2 = collision_detector.triangle_colliding_vertices_min_dist.numpy()
508
+
509
+ assert_np_equal(vertex_colliding_triangles_count_2, vertex_colliding_triangles_count_1)
510
+ assert_np_equal(triangle_min_dis_2, triangle_min_dis_1)
511
+ assert_np_equal(vertex_min_dis_2, vertex_min_dis_1)
402
512
 
403
513
 
404
514
  @unittest.skipUnless(USD_AVAILABLE, "Requires usd-core")
@@ -416,7 +526,7 @@ def test_edge_edge_collision(test, device):
416
526
  edge_min_dist_1 = collision_detector.edge_colliding_edges_min_dist.numpy()
417
527
 
418
528
  wp.launch(
419
- kernel=edge_edge_collision_detection_brute_force,
529
+ kernel=validate_edge_collisions,
420
530
  inputs=[
421
531
  query_radius,
422
532
  collision_detector.bvh_edges.id,
@@ -432,18 +542,12 @@ def test_edge_edge_collision(test, device):
432
542
  collision_detector.edge_colliding_edges_min_dist,
433
543
  collision_detector.resize_flags,
434
544
  ],
435
- dim=model.edge_count,
545
+ dim=model.particle_count,
436
546
  device=device,
437
547
  )
438
548
 
439
- edge_colliding_edges_count_2 = collision_detector.edge_colliding_edges_count.numpy()
440
- edge_min_dist_2 = collision_detector.edge_colliding_edges_min_dist.numpy()
441
-
442
- assert_np_equal(edge_colliding_edges_count_2, edge_colliding_edges_count_1)
443
- assert_np_equal(edge_min_dist_2, edge_min_dist_1)
444
-
445
549
  wp.launch(
446
- kernel=validate_edge_collisions,
550
+ kernel=edge_edge_collision_detection_brute_force,
447
551
  inputs=[
448
552
  query_radius,
449
553
  collision_detector.bvh_edges.id,
@@ -459,11 +563,15 @@ def test_edge_edge_collision(test, device):
459
563
  collision_detector.edge_colliding_edges_min_dist,
460
564
  collision_detector.resize_flags,
461
565
  ],
462
- dim=model.particle_count,
566
+ dim=model.edge_count,
463
567
  device=device,
464
568
  )
465
569
 
466
- wp.synchronize_device(device)
570
+ edge_colliding_edges_count_2 = collision_detector.edge_colliding_edges_count.numpy()
571
+ edge_min_dist_2 = collision_detector.edge_colliding_edges_min_dist.numpy()
572
+
573
+ assert_np_equal(edge_colliding_edges_count_2, edge_colliding_edges_count_1)
574
+ assert_np_equal(edge_min_dist_1, edge_min_dist_2)
467
575
 
468
576
 
469
577
  def test_particle_collision(test, device):
@@ -13,6 +13,8 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
+ import itertools
17
+
16
18
  import numpy as np
17
19
 
18
20
  import warp as wp
@@ -48,6 +50,76 @@ def color_lattice_grid(num_x, num_y):
48
50
  return color_groups
49
51
 
50
52
 
53
+ def create_lattice_grid(N):
54
+ size = 10
55
+ position = (0, 0)
56
+
57
+ X = np.linspace(-0.5 * size + position[0], 0.5 * size + position[0], N)
58
+ Y = np.linspace(-0.5 * size + position[1], 0.5 * size + position[1], N)
59
+
60
+ X, Y = np.meshgrid(X, Y)
61
+
62
+ Z = []
63
+ for _i in range(N):
64
+ Z.append(np.linspace(0, size, N))
65
+
66
+ Z = np.array(Z)
67
+
68
+ vs = []
69
+ for i, j in itertools.product(range(N), range(N)):
70
+ vs.append(wp.vec3((X[i, j], Y[i, j], Z[i, j])))
71
+
72
+ fs = []
73
+ for i, j in itertools.product(range(0, N - 1), range(0, N - 1)):
74
+ vId = j + i * N
75
+
76
+ if (j + i) % 2:
77
+ fs.extend(
78
+ [
79
+ vId,
80
+ vId + N + 1,
81
+ vId + 1,
82
+ ]
83
+ )
84
+ fs.extend(
85
+ [
86
+ vId,
87
+ vId + N,
88
+ vId + N + 1,
89
+ ]
90
+ )
91
+ else:
92
+ fs.extend(
93
+ [
94
+ vId,
95
+ vId + N,
96
+ vId + 1,
97
+ ]
98
+ )
99
+ fs.extend(
100
+ [
101
+ vId + N,
102
+ vId + N + 1,
103
+ vId + 1,
104
+ ]
105
+ )
106
+
107
+ return vs, fs
108
+
109
+
110
+ def test_coloring_corner_case(test, device):
111
+ builder_1 = wp.sim.ModelBuilder()
112
+ builder_1.color()
113
+ test.assertTrue(len(builder_1.particle_color_groups) == 0)
114
+
115
+ builder_2 = wp.sim.ModelBuilder()
116
+ builder_2.add_particle(pos=wp.vec3(0, 0, 0), vel=wp.vec3(0, 0, 0), mass=1.0)
117
+ builder_2.add_particle(pos=wp.vec3(1, 0, 0), vel=wp.vec3(0, 0, 0), mass=1.0)
118
+ builder_2.color()
119
+ test.assertTrue(len(builder_2.particle_color_groups) == 1)
120
+ test.assertTrue(builder_2.particle_color_groups[0].shape[0] == 2)
121
+
122
+
51
123
  @unittest.skipUnless(USD_AVAILABLE, "Requires usd-core")
52
124
  def test_coloring_trimesh(test, device):
53
125
  from pxr import Usd, UsdGeom
@@ -151,6 +223,22 @@ def test_coloring_trimesh(test, device):
151
223
  color_sizes = np.array([c.shape[0] for c in color_categories_balanced], dtype=np.float32)
152
224
  test.assertTrue(np.max(color_sizes) / np.min(color_sizes) <= max_min_ratio)
153
225
 
226
+ # test if the color balance can quit from equilibrium
227
+ builder = wp.sim.ModelBuilder()
228
+
229
+ vs, fs = create_lattice_grid(100)
230
+ builder.add_cloth_mesh(
231
+ pos=wp.vec3(0.0, 0.0, 0.0),
232
+ rot=wp.quat_from_axis_angle(wp.vec3(1.0, 0.0, 0.0), 0.0),
233
+ scale=1.0,
234
+ vertices=vs,
235
+ indices=fs,
236
+ vel=wp.vec3(0.0, 0.0, 0.0),
237
+ density=0.02,
238
+ )
239
+
240
+ builder.color(include_bending=True)
241
+
154
242
 
155
243
  @unittest.skipUnless(USD_AVAILABLE, "Requires usd-core")
156
244
  def test_combine_coloring(test, device):
@@ -227,7 +315,7 @@ def test_combine_coloring(test, device):
227
315
 
228
316
  particle_number_colored = np.full((model.particle_count), -1, dtype=int)
229
317
  particle_colors = np.full((model.particle_count), -1, dtype=int)
230
- for color, color_group in enumerate(model.particle_coloring):
318
+ for color, color_group in enumerate(model.particle_color_groups):
231
319
  particle_number_colored[color_group.numpy()] += 1
232
320
  particle_colors[color_group.numpy()] = color
233
321
 
@@ -250,8 +338,9 @@ class TestColoring(unittest.TestCase):
250
338
  pass
251
339
 
252
340
 
253
- add_function_test(TestColoring, "test_coloring_trimesh", test_coloring_trimesh, devices=devices)
341
+ add_function_test(TestColoring, "test_coloring_trimesh", test_coloring_trimesh, devices=devices, check_output=False)
254
342
  add_function_test(TestColoring, "test_combine_coloring", test_combine_coloring, devices=devices)
343
+ add_function_test(TestColoring, "test_coloring_corner_case", test_coloring_corner_case, devices=devices)
255
344
 
256
345
  if __name__ == "__main__":
257
346
  wp.clear_kernel_cache()