warp-lang 1.5.1__py3-none-manylinux2014_aarch64.whl → 1.6.1__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 (131) hide show
  1. warp/__init__.py +5 -0
  2. warp/autograd.py +414 -191
  3. warp/bin/warp-clang.so +0 -0
  4. warp/bin/warp.so +0 -0
  5. warp/build.py +40 -12
  6. warp/build_dll.py +13 -6
  7. warp/builtins.py +1077 -481
  8. warp/codegen.py +250 -122
  9. warp/config.py +65 -21
  10. warp/context.py +500 -149
  11. warp/examples/assets/square_cloth.usd +0 -0
  12. warp/examples/benchmarks/benchmark_gemm.py +27 -18
  13. warp/examples/benchmarks/benchmark_interop_paddle.py +3 -3
  14. warp/examples/benchmarks/benchmark_interop_torch.py +3 -3
  15. warp/examples/core/example_marching_cubes.py +1 -1
  16. warp/examples/core/example_mesh.py +1 -1
  17. warp/examples/core/example_torch.py +18 -34
  18. warp/examples/core/example_wave.py +1 -1
  19. warp/examples/fem/example_apic_fluid.py +1 -0
  20. warp/examples/fem/example_mixed_elasticity.py +1 -1
  21. warp/examples/optim/example_bounce.py +1 -1
  22. warp/examples/optim/example_cloth_throw.py +1 -1
  23. warp/examples/optim/example_diffray.py +4 -15
  24. warp/examples/optim/example_drone.py +1 -1
  25. warp/examples/optim/example_softbody_properties.py +392 -0
  26. warp/examples/optim/example_trajectory.py +1 -3
  27. warp/examples/optim/example_walker.py +5 -0
  28. warp/examples/sim/example_cartpole.py +0 -2
  29. warp/examples/sim/example_cloth_self_contact.py +314 -0
  30. warp/examples/sim/example_granular_collision_sdf.py +4 -5
  31. warp/examples/sim/example_jacobian_ik.py +0 -2
  32. warp/examples/sim/example_quadruped.py +5 -2
  33. warp/examples/tile/example_tile_cholesky.py +79 -0
  34. warp/examples/tile/example_tile_convolution.py +2 -2
  35. warp/examples/tile/example_tile_fft.py +2 -2
  36. warp/examples/tile/example_tile_filtering.py +3 -3
  37. warp/examples/tile/example_tile_matmul.py +4 -4
  38. warp/examples/tile/example_tile_mlp.py +12 -12
  39. warp/examples/tile/example_tile_nbody.py +191 -0
  40. warp/examples/tile/example_tile_walker.py +319 -0
  41. warp/math.py +147 -0
  42. warp/native/array.h +12 -0
  43. warp/native/builtin.h +0 -1
  44. warp/native/bvh.cpp +149 -70
  45. warp/native/bvh.cu +287 -68
  46. warp/native/bvh.h +195 -85
  47. warp/native/clang/clang.cpp +6 -2
  48. warp/native/crt.h +1 -0
  49. warp/native/cuda_util.cpp +35 -0
  50. warp/native/cuda_util.h +5 -0
  51. warp/native/exports.h +40 -40
  52. warp/native/intersect.h +17 -0
  53. warp/native/mat.h +57 -3
  54. warp/native/mathdx.cpp +19 -0
  55. warp/native/mesh.cpp +25 -8
  56. warp/native/mesh.cu +153 -101
  57. warp/native/mesh.h +482 -403
  58. warp/native/quat.h +40 -0
  59. warp/native/solid_angle.h +7 -0
  60. warp/native/sort.cpp +85 -0
  61. warp/native/sort.cu +34 -0
  62. warp/native/sort.h +3 -1
  63. warp/native/spatial.h +11 -0
  64. warp/native/tile.h +1189 -664
  65. warp/native/tile_reduce.h +8 -6
  66. warp/native/vec.h +41 -0
  67. warp/native/warp.cpp +8 -1
  68. warp/native/warp.cu +263 -40
  69. warp/native/warp.h +19 -5
  70. warp/optim/linear.py +22 -4
  71. warp/render/render_opengl.py +132 -59
  72. warp/render/render_usd.py +10 -2
  73. warp/sim/__init__.py +6 -1
  74. warp/sim/collide.py +289 -32
  75. warp/sim/import_urdf.py +20 -5
  76. warp/sim/integrator_euler.py +25 -7
  77. warp/sim/integrator_featherstone.py +147 -35
  78. warp/sim/integrator_vbd.py +842 -40
  79. warp/sim/model.py +173 -112
  80. warp/sim/render.py +2 -2
  81. warp/stubs.py +249 -116
  82. warp/tape.py +28 -30
  83. warp/tests/aux_test_module_unload.py +15 -0
  84. warp/tests/{test_sim_grad.py → flaky_test_sim_grad.py} +104 -63
  85. warp/tests/test_array.py +100 -0
  86. warp/tests/test_assert.py +242 -0
  87. warp/tests/test_codegen.py +14 -61
  88. warp/tests/test_collision.py +8 -8
  89. warp/tests/test_examples.py +16 -1
  90. warp/tests/test_grad_debug.py +87 -2
  91. warp/tests/test_hash_grid.py +1 -1
  92. warp/tests/test_ipc.py +116 -0
  93. warp/tests/test_launch.py +77 -26
  94. warp/tests/test_mat.py +213 -168
  95. warp/tests/test_math.py +47 -1
  96. warp/tests/test_matmul.py +11 -7
  97. warp/tests/test_matmul_lite.py +4 -4
  98. warp/tests/test_mesh.py +84 -60
  99. warp/tests/test_mesh_query_aabb.py +165 -0
  100. warp/tests/test_mesh_query_point.py +328 -286
  101. warp/tests/test_mesh_query_ray.py +134 -121
  102. warp/tests/test_mlp.py +2 -2
  103. warp/tests/test_operators.py +43 -0
  104. warp/tests/test_overwrite.py +6 -5
  105. warp/tests/test_quat.py +77 -0
  106. warp/tests/test_reload.py +29 -0
  107. warp/tests/test_sim_grad_bounce_linear.py +204 -0
  108. warp/tests/test_static.py +16 -0
  109. warp/tests/test_tape.py +25 -0
  110. warp/tests/test_tile.py +134 -191
  111. warp/tests/test_tile_load.py +399 -0
  112. warp/tests/test_tile_mathdx.py +61 -8
  113. warp/tests/test_tile_mlp.py +17 -17
  114. warp/tests/test_tile_reduce.py +24 -18
  115. warp/tests/test_tile_shared_memory.py +66 -17
  116. warp/tests/test_tile_view.py +165 -0
  117. warp/tests/test_torch.py +35 -0
  118. warp/tests/test_utils.py +36 -24
  119. warp/tests/test_vec.py +110 -0
  120. warp/tests/unittest_suites.py +29 -4
  121. warp/tests/unittest_utils.py +30 -11
  122. warp/thirdparty/unittest_parallel.py +5 -2
  123. warp/types.py +419 -111
  124. warp/utils.py +9 -5
  125. {warp_lang-1.5.1.dist-info → warp_lang-1.6.1.dist-info}/METADATA +86 -45
  126. {warp_lang-1.5.1.dist-info → warp_lang-1.6.1.dist-info}/RECORD +129 -118
  127. {warp_lang-1.5.1.dist-info → warp_lang-1.6.1.dist-info}/WHEEL +1 -1
  128. warp/examples/benchmarks/benchmark_tile.py +0 -179
  129. warp/native/tile_gemm.h +0 -341
  130. {warp_lang-1.5.1.dist-info → warp_lang-1.6.1.dist-info}/LICENSE.md +0 -0
  131. {warp_lang-1.5.1.dist-info → warp_lang-1.6.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,242 @@
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 as wp
11
+ from warp.tests.unittest_utils import *
12
+
13
+
14
+ @wp.kernel
15
+ def expect_ones(a: wp.array(dtype=int)):
16
+ i = wp.tid()
17
+
18
+ assert a[i] == 1
19
+
20
+
21
+ @wp.kernel
22
+ def expect_ones_with_msg(a: wp.array(dtype=int)):
23
+ i = wp.tid()
24
+
25
+ assert a[i] == 1, "Array element must be 1"
26
+
27
+
28
+ @wp.kernel
29
+ def expect_ones_compound(a: wp.array(dtype=int)):
30
+ i = wp.tid()
31
+
32
+ assert a[i] > 0 and a[i] < 2
33
+
34
+
35
+ @wp.func
36
+ def expect_ones_function(value: int):
37
+ assert value == 1, "Array element must be 1"
38
+
39
+
40
+ @wp.kernel
41
+ def expect_ones_call_function(a: wp.array(dtype=int)):
42
+ i = wp.tid()
43
+ expect_ones_function(a[i])
44
+
45
+
46
+ class TestAssertRelease(unittest.TestCase):
47
+ """Assert test cases that are to be run with Warp in release mode."""
48
+
49
+ @classmethod
50
+ def setUpClass(cls):
51
+ cls._saved_mode = wp.get_module_options()["mode"]
52
+ cls._saved_cache_kernels = wp.config.cache_kernels
53
+
54
+ wp.config.mode = "release"
55
+ wp.config.cache_kernels = False
56
+
57
+ @classmethod
58
+ def tearDownClass(cls):
59
+ wp.set_module_options({"mode": cls._saved_mode})
60
+ wp.config.cache_kernels = cls._saved_cache_kernels
61
+
62
+ def test_basic_assert_false_condition(self):
63
+ with wp.ScopedDevice("cpu"):
64
+ wp.load_module(device=wp.get_device())
65
+
66
+ input_array = wp.zeros(1, dtype=int)
67
+
68
+ capture = StdErrCapture()
69
+ capture.begin()
70
+
71
+ wp.launch(expect_ones, input_array.shape, inputs=[input_array])
72
+
73
+ output = capture.end()
74
+
75
+ self.assertEqual(output, "", f"Kernel should not print anything to stderr, got {output}")
76
+
77
+ def test_basic_assert_with_msg(self):
78
+ with wp.ScopedDevice("cpu"):
79
+ wp.load_module(device=wp.get_device())
80
+
81
+ input_array = wp.zeros(1, dtype=int)
82
+
83
+ capture = StdErrCapture()
84
+ capture.begin()
85
+
86
+ wp.launch(expect_ones_with_msg, input_array.shape, inputs=[input_array])
87
+
88
+ output = capture.end()
89
+
90
+ self.assertEqual(output, "", f"Kernel should not print anything to stderr, got {output}")
91
+
92
+ def test_compound_assert_false_condition(self):
93
+ with wp.ScopedDevice("cpu"):
94
+ wp.load_module(device=wp.get_device())
95
+
96
+ input_array = wp.full(1, value=3, dtype=int)
97
+
98
+ capture = StdErrCapture()
99
+ capture.begin()
100
+
101
+ wp.launch(expect_ones_compound, input_array.shape, inputs=[input_array])
102
+
103
+ output = capture.end()
104
+
105
+ self.assertEqual(output, "", f"Kernel should not print anything to stderr, got {output}")
106
+
107
+ def test_basic_assert_false_condition_function(self):
108
+ with wp.ScopedDevice("cpu"):
109
+ wp.load_module(device=wp.get_device())
110
+
111
+ input_array = wp.full(1, value=3, dtype=int)
112
+
113
+ capture = StdErrCapture()
114
+ capture.begin()
115
+
116
+ wp.launch(expect_ones_call_function, input_array.shape, inputs=[input_array])
117
+
118
+ output = capture.end()
119
+
120
+ self.assertEqual(output, "", f"Kernel should not print anything to stderr, got {output}")
121
+
122
+
123
+ # NOTE: Failed assertions on CUDA devices leaves the CUDA context in an unrecoverable state,
124
+ # so we currently do not test them.
125
+ class TestAssertDebug(unittest.TestCase):
126
+ """Assert test cases that are to be run with Warp in debug mode."""
127
+
128
+ @classmethod
129
+ def setUpClass(cls):
130
+ cls._saved_mode = wp.get_module_options()["mode"]
131
+ cls._saved_cache_kernels = wp.config.cache_kernels
132
+
133
+ wp.set_module_options({"mode": "debug"})
134
+ wp.config.cache_kernels = False
135
+
136
+ @classmethod
137
+ def tearDownClass(cls):
138
+ wp.set_module_options({"mode": cls._saved_mode})
139
+ wp.config.cache_kernels = cls._saved_cache_kernels
140
+
141
+ def test_basic_assert_false_condition(self):
142
+ with wp.ScopedDevice("cpu"):
143
+ wp.load_module(device=wp.get_device())
144
+
145
+ input_array = wp.zeros(1, dtype=int)
146
+
147
+ capture = StdErrCapture()
148
+ capture.begin()
149
+
150
+ wp.launch(expect_ones, input_array.shape, inputs=[input_array])
151
+
152
+ output = capture.end()
153
+
154
+ # Older Windows C runtimes have a bug where stdout sometimes does not get properly flushed.
155
+ if output != "" or sys.platform != "win32":
156
+ self.assertRegex(output, r"Assertion failed: .*assert a\[i\] == 1")
157
+
158
+ def test_basic_assert_true_condition(self):
159
+ with wp.ScopedDevice("cpu"):
160
+ wp.load_module(device=wp.get_device())
161
+
162
+ input_array = wp.ones(1, dtype=int)
163
+
164
+ capture = StdErrCapture()
165
+ capture.begin()
166
+
167
+ wp.launch(expect_ones, input_array.shape, inputs=[input_array])
168
+
169
+ output = capture.end()
170
+
171
+ self.assertEqual(output, "", f"Kernel should not print anything to stderr, got {output}")
172
+
173
+ def test_basic_assert_with_msg(self):
174
+ with wp.ScopedDevice("cpu"):
175
+ wp.load_module(device=wp.get_device())
176
+
177
+ input_array = wp.zeros(1, dtype=int)
178
+
179
+ capture = StdErrCapture()
180
+ capture.begin()
181
+
182
+ wp.launch(expect_ones_with_msg, input_array.shape, inputs=[input_array])
183
+
184
+ output = capture.end()
185
+
186
+ # Older Windows C runtimes have a bug where stdout sometimes does not get properly flushed.
187
+ if output != "" or sys.platform != "win32":
188
+ self.assertRegex(output, r"Assertion failed: .*assert a\[i\] == 1.*Array element must be 1")
189
+
190
+ def test_compound_assert_true_condition(self):
191
+ with wp.ScopedDevice("cpu"):
192
+ wp.load_module(device=wp.get_device())
193
+
194
+ input_array = wp.ones(1, dtype=int)
195
+
196
+ capture = StdErrCapture()
197
+ capture.begin()
198
+
199
+ wp.launch(expect_ones_compound, input_array.shape, inputs=[input_array])
200
+
201
+ output = capture.end()
202
+
203
+ self.assertEqual(output, "", f"Kernel should not print anything to stderr, got {output}")
204
+
205
+ def test_compound_assert_false_condition(self):
206
+ with wp.ScopedDevice("cpu"):
207
+ wp.load_module(device=wp.get_device())
208
+
209
+ input_array = wp.full(1, value=3, dtype=int)
210
+
211
+ capture = StdErrCapture()
212
+ capture.begin()
213
+
214
+ wp.launch(expect_ones_compound, input_array.shape, inputs=[input_array])
215
+
216
+ output = capture.end()
217
+
218
+ # Older Windows C runtimes have a bug where stdout sometimes does not get properly flushed.
219
+ if output != "" or sys.platform != "win32":
220
+ self.assertRegex(output, r"Assertion failed: .*assert a\[i\] > 0 and a\[i\] < 2")
221
+
222
+ def test_basic_assert_false_condition_function(self):
223
+ with wp.ScopedDevice("cpu"):
224
+ wp.load_module(device=wp.get_device())
225
+
226
+ input_array = wp.full(1, value=3, dtype=int)
227
+
228
+ capture = StdErrCapture()
229
+ capture.begin()
230
+
231
+ wp.launch(expect_ones_call_function, input_array.shape, inputs=[input_array])
232
+
233
+ output = capture.end()
234
+
235
+ # Older Windows C runtimes have a bug where stdout sometimes does not get properly flushed.
236
+ if output != "" or sys.platform != "win32":
237
+ self.assertRegex(output, r"Assertion failed: .*assert value == 1.*Array element must be 1")
238
+
239
+
240
+ if __name__ == "__main__":
241
+ wp.clear_kernel_cache()
242
+ unittest.main(verbosity=2)
@@ -396,48 +396,29 @@ def test_unresolved_symbol(test, device):
396
396
 
397
397
 
398
398
  def test_error_global_var(test, device):
399
- arr = wp.array(
400
- (1.0, 2.0, 3.0),
401
- dtype=float,
402
- device=device,
403
- )
399
+ arr = wp.array((1.0, 2.0, 3.0), dtype=float, device=device)
404
400
 
405
- def kernel_1_fn(
406
- out: wp.array(dtype=float),
407
- ):
401
+ def kernel_1_fn(out: wp.array(dtype=float)):
408
402
  out[0] = arr[0]
409
403
 
410
- def kernel_2_fn(
411
- out: wp.array(dtype=float),
412
- ):
404
+ def kernel_2_fn(out: wp.array(dtype=float)):
413
405
  out[0] = arr
414
406
 
415
- def kernel_3_fn(
416
- out: wp.array(dtype=float),
417
- ):
407
+ def kernel_3_fn(out: wp.array(dtype=float)):
418
408
  out[0] = wp.lower_bound(arr, 2.0)
419
409
 
420
410
  out = wp.empty_like(arr)
421
411
 
422
412
  kernel = wp.Kernel(func=kernel_1_fn)
423
- with test.assertRaisesRegex(
424
- TypeError,
425
- r"Invalid external reference type: <class 'warp.types.array'>",
426
- ):
413
+ with test.assertRaisesRegex(TypeError, r"Invalid external reference type: <class 'warp.types.array'>"):
427
414
  wp.launch(kernel, dim=out.shape, inputs=(), outputs=(out,), device=device)
428
415
 
429
416
  kernel = wp.Kernel(func=kernel_2_fn)
430
- with test.assertRaisesRegex(
431
- TypeError,
432
- r"Invalid external reference type: <class 'warp.types.array'>",
433
- ):
417
+ with test.assertRaisesRegex(TypeError, r"Invalid external reference type: <class 'warp.types.array'>"):
434
418
  wp.launch(kernel, dim=out.shape, inputs=(), outputs=(out,), device=device)
435
419
 
436
420
  kernel = wp.Kernel(func=kernel_3_fn)
437
- with test.assertRaisesRegex(
438
- TypeError,
439
- r"Invalid external reference type: <class 'warp.types.array'>",
440
- ):
421
+ with test.assertRaisesRegex(TypeError, r"Invalid external reference type: <class 'warp.types.array'>"):
441
422
  wp.launch(kernel, dim=out.shape, inputs=(), outputs=(out,), device=device)
442
423
 
443
424
 
@@ -469,16 +450,12 @@ def test_error_collection_construct(test, device):
469
450
  wp.launch(kernel, dim=1, device=device)
470
451
 
471
452
  kernel = wp.Kernel(func=kernel_3_fn)
472
- with test.assertRaisesRegex(
473
- RuntimeError,
474
- r"Construct `ast.Dict` not supported in kernels.",
475
- ):
453
+ with test.assertRaisesRegex(RuntimeError, r"Construct `ast.Dict` not supported in kernels."):
476
454
  wp.launch(kernel, dim=1, device=device)
477
455
 
478
456
  kernel = wp.Kernel(func=kernel_4_fn)
479
457
  with test.assertRaisesRegex(
480
- RuntimeError,
481
- r"Tuple constructs are not supported in kernels. Use vectors like `wp.vec3\(\)` instead.",
458
+ RuntimeError, r"Tuple constructs are not supported in kernels. Use vectors like `wp.vec3\(\)` instead."
482
459
  ):
483
460
  wp.launch(kernel, dim=1, device=device)
484
461
 
@@ -491,10 +468,7 @@ def test_error_unmatched_arguments(test, device):
491
468
  x = wp.dot(wp.vec2(1.0, 2.0), wp.vec2h(wp.float16(1.0), wp.float16(2.0)))
492
469
 
493
470
  kernel = wp.Kernel(func=kernel_1_fn)
494
- with test.assertRaisesRegex(
495
- RuntimeError,
496
- r"Input types must be the same, got \['int32', 'float32'\]",
497
- ):
471
+ with test.assertRaisesRegex(RuntimeError, r"Input types must be the same, got \['int32', 'float32'\]"):
498
472
  wp.launch(kernel, dim=1, device=device)
499
473
 
500
474
  kernel = wp.Kernel(func=kernel_2_fn)
@@ -704,12 +678,7 @@ add_kernel_test(
704
678
  TestCodeGen, name="test_dynamic_for_rename", kernel=test_dynamic_for_rename, inputs=[10], dim=1, devices=devices
705
679
  )
706
680
  add_kernel_test(
707
- TestCodeGen,
708
- name="test_dynamic_for_inplace",
709
- kernel=test_dynamic_for_inplace,
710
- inputs=[10],
711
- dim=1,
712
- devices=devices,
681
+ TestCodeGen, name="test_dynamic_for_inplace", kernel=test_dynamic_for_inplace, inputs=[10], dim=1, devices=devices
713
682
  )
714
683
  add_kernel_test(TestCodeGen, name="test_reassign", kernel=test_reassign, dim=1, devices=devices)
715
684
  add_kernel_test(
@@ -754,12 +723,7 @@ add_kernel_test(
754
723
  )
755
724
 
756
725
  add_kernel_test(
757
- TestCodeGen,
758
- name="test_range_static_sum",
759
- kernel=test_range_static_sum,
760
- dim=1,
761
- expect=[10, 10, 10],
762
- devices=devices,
726
+ TestCodeGen, name="test_range_static_sum", kernel=test_range_static_sum, dim=1, expect=[10, 10, 10], devices=devices
763
727
  )
764
728
  add_kernel_test(
765
729
  TestCodeGen,
@@ -789,20 +753,9 @@ add_kernel_test(
789
753
  devices=devices,
790
754
  )
791
755
  add_kernel_test(
792
- TestCodeGen,
793
- name="test_range_dynamic_nested",
794
- kernel=test_range_dynamic_nested,
795
- dim=1,
796
- inputs=[4],
797
- devices=devices,
798
- )
799
- add_kernel_test(
800
- TestCodeGen,
801
- name="test_range_expression",
802
- kernel=test_range_expression,
803
- dim=1,
804
- devices=devices,
756
+ TestCodeGen, name="test_range_dynamic_nested", kernel=test_range_dynamic_nested, dim=1, inputs=[4], devices=devices
805
757
  )
758
+ add_kernel_test(TestCodeGen, name="test_range_expression", kernel=test_range_expression, dim=1, devices=devices)
806
759
 
807
760
  add_kernel_test(TestCodeGen, name="test_while_zero", kernel=test_while, dim=1, inputs=[0], devices=devices)
808
761
  add_kernel_test(TestCodeGen, name="test_while_positive", kernel=test_while, dim=1, inputs=[16], devices=devices)
@@ -18,7 +18,7 @@ from warp.tests.unittest_utils import *
18
18
  @wp.kernel
19
19
  def vertex_triangle_collision_detection_brute_force(
20
20
  query_radius: float,
21
- mesh_id: wp.uint64,
21
+ bvh_id: wp.uint64,
22
22
  pos: wp.array(dtype=wp.vec3),
23
23
  tri_indices: wp.array(dtype=wp.int32, ndim=2),
24
24
  vertex_colliding_triangles: wp.array(dtype=wp.int32),
@@ -67,7 +67,7 @@ def vertex_triangle_collision_detection_brute_force(
67
67
  @wp.kernel
68
68
  def validate_vertex_collisions(
69
69
  query_radius: float,
70
- mesh_id: wp.uint64,
70
+ bvh_id: wp.uint64,
71
71
  pos: wp.array(dtype=wp.vec3),
72
72
  tri_indices: wp.array(dtype=wp.int32, ndim=2),
73
73
  vertex_colliding_triangles: wp.array(dtype=wp.int32),
@@ -107,7 +107,7 @@ def validate_vertex_collisions(
107
107
  @wp.kernel
108
108
  def validate_triangle_collisions(
109
109
  query_radius: float,
110
- mesh_id: wp.uint64,
110
+ bvh_id: wp.uint64,
111
111
  pos: wp.array(dtype=wp.vec3),
112
112
  tri_indices: wp.array(dtype=wp.int32, ndim=2),
113
113
  triangle_colliding_vertices: wp.array(dtype=wp.int32),
@@ -303,7 +303,7 @@ class Example:
303
303
  kernel=vertex_triangle_collision_detection_brute_force,
304
304
  inputs=[
305
305
  query_radius,
306
- self.collision_detector.mesh_tris.id,
306
+ self.collision_detector.bvh_tris.id,
307
307
  self.collision_detector.model.particle_q,
308
308
  self.collision_detector.model.tri_indices,
309
309
  self.collision_detector.vertex_colliding_triangles,
@@ -337,7 +337,7 @@ class Example:
337
337
  kernel=validate_vertex_collisions,
338
338
  inputs=[
339
339
  query_radius,
340
- self.collision_detector.mesh_tris.id,
340
+ self.collision_detector.bvh_tris.id,
341
341
  self.collision_detector.model.particle_q,
342
342
  self.collision_detector.model.tri_indices,
343
343
  self.collision_detector.vertex_colliding_triangles,
@@ -355,7 +355,7 @@ class Example:
355
355
  kernel=validate_triangle_collisions,
356
356
  inputs=[
357
357
  query_radius,
358
- self.collision_detector.mesh_tris.id,
358
+ self.collision_detector.bvh_tris.id,
359
359
  self.collision_detector.model.particle_q,
360
360
  self.collision_detector.model.tri_indices,
361
361
  self.collision_detector.triangle_colliding_vertices,
@@ -430,8 +430,8 @@ class Example:
430
430
  def set_points_fixed(self, model, fixed_particles):
431
431
  if len(fixed_particles):
432
432
  flags = model.particle_flags.numpy()
433
- for fixed_v_id in fixed_particles:
434
- flags[fixed_v_id] = wp.uint32(int(flags[fixed_v_id]) & ~int(PARTICLE_FLAG_ACTIVE))
433
+ for fixed_vertex_id in fixed_particles:
434
+ flags[fixed_vertex_id] = wp.uint32(int(flags[fixed_vertex_id]) & ~int(PARTICLE_FLAG_ACTIVE))
435
435
 
436
436
  model.particle_flags = wp.array(flags, device=model.device)
437
437
 
@@ -234,7 +234,13 @@ add_example_test(
234
234
  devices=test_devices,
235
235
  test_options={"height": 512, "width": 1024, "headless": True},
236
236
  )
237
- add_example_test(TestCoreExamples, name="core.example_sph", devices=test_devices, test_options_cpu={"num_frames": 1})
237
+ add_example_test(
238
+ TestCoreExamples,
239
+ name="core.example_sph",
240
+ devices=test_devices,
241
+ test_options_cpu={"num_frames": 1},
242
+ test_options_cuda={"test_timeout": 600},
243
+ )
238
244
  add_example_test(
239
245
  TestCoreExamples,
240
246
  name="core.example_torch",
@@ -304,6 +310,15 @@ add_example_test(
304
310
  },
305
311
  test_options_cpu={"train_iters": 1, "num_frames": 30},
306
312
  )
313
+ add_example_test(
314
+ TestOptimExamples,
315
+ name="optim.example_softbody_properties",
316
+ devices=test_devices,
317
+ test_options_cuda={
318
+ "train_iters": 1 if warp.context.runtime.core.is_debug_enabled() else 3,
319
+ },
320
+ test_options_cpu={"train_iters": 1},
321
+ )
307
322
 
308
323
 
309
324
  class TestSimExamples(unittest.TestCase):
@@ -8,7 +8,12 @@
8
8
  import unittest
9
9
 
10
10
  import warp as wp
11
- from warp.autograd import gradcheck, gradcheck_tape, jacobian, jacobian_fd
11
+ from warp.autograd import (
12
+ gradcheck,
13
+ gradcheck_tape,
14
+ jacobian,
15
+ jacobian_fd,
16
+ )
12
17
  from warp.tests.unittest_utils import *
13
18
 
14
19
 
@@ -43,7 +48,7 @@ def vec_length_kernel(a: wp.array(dtype=wp.vec3), out: wp.array(dtype=float)):
43
48
  tid = wp.tid()
44
49
  v = a[tid]
45
50
  # instead of wp.length(v), we use a trivial implementation that
46
- # fails when a division by zero is occurs in the backward pass of sqrt
51
+ # fails when a division by zero occurs in the backward pass of sqrt
47
52
  out[tid] = wp.sqrt(v[0] ** 2.0 + v[1] ** 2.0 + v[2] ** 2.0)
48
53
 
49
54
 
@@ -63,6 +68,16 @@ def wrong_grad_kernel(a: wp.array(dtype=float), out: wp.array(dtype=float)):
63
68
  out[tid] = wrong_grad_func(a[tid])
64
69
 
65
70
 
71
+ @wp.kernel
72
+ def transform_point_kernel(
73
+ transforms: wp.array(dtype=wp.transform),
74
+ points: wp.array(dtype=wp.vec3),
75
+ out: wp.array(dtype=wp.vec3),
76
+ ):
77
+ tid = wp.tid()
78
+ out[tid] = wp.transform_point(transforms[tid], points[tid])
79
+
80
+
66
81
  def test_gradcheck_3d(test, device):
67
82
  a_3d = wp.array([((2.0, 0.0), (1.0, 0.0), (2.0, 0.0))], dtype=float, requires_grad=True, device=device)
68
83
  b_3d = wp.array([((3.0, 0.0), (1.0, 0.0), (2.0, 0.0))], dtype=float, requires_grad=True, device=device)
@@ -229,6 +244,76 @@ def test_gradcheck_tape(test, device):
229
244
  assert passed
230
245
 
231
246
 
247
+ def test_gradcheck_function(test, device):
248
+ def compute_transformed_point_norms(transforms, points):
249
+ tf_points = wp.empty_like(points)
250
+ norms = wp.empty(len(points), dtype=float, requires_grad=points.requires_grad, device=points.device)
251
+
252
+ wp.launch(
253
+ transform_point_kernel,
254
+ dim=len(points),
255
+ inputs=[transforms, points],
256
+ outputs=[tf_points],
257
+ device=device,
258
+ )
259
+ wp.launch(
260
+ vec_length_kernel,
261
+ dim=len(points),
262
+ inputs=[tf_points],
263
+ outputs=[norms],
264
+ device=device,
265
+ )
266
+ return tf_points, norms
267
+
268
+ transforms = wp.array(
269
+ [
270
+ wp.transform(wp.vec3(1.0, 0.6, -2.0), wp.quat_rpy(-0.5, 0.1, 0.8)),
271
+ wp.transform(wp.vec3(0.2, 1.4, -0.4), wp.quat_rpy(0.5, 0.65, -0.3)),
272
+ wp.transform(wp.vec3(0.5, 0.2, 0.0), wp.quat_rpy(-0.5, -0.3, 0.4)),
273
+ ],
274
+ dtype=wp.transform,
275
+ requires_grad=True,
276
+ device=device,
277
+ )
278
+ points = wp.array(
279
+ [
280
+ (1.0, -0.5, 2.0),
281
+ (-0.95, -0.1, 0.0),
282
+ (9.1, 9.7, 3.8),
283
+ ],
284
+ dtype=wp.vec3,
285
+ requires_grad=True,
286
+ device=device,
287
+ )
288
+
289
+ jacs_ad = jacobian(
290
+ kernel_mixed,
291
+ dim=len(points),
292
+ inputs=[transforms, points],
293
+ )
294
+ jacs_fd = jacobian_fd(
295
+ kernel_mixed,
296
+ dim=len(points),
297
+ inputs=[transforms, points],
298
+ eps=1e-4,
299
+ )
300
+
301
+ # manual gradcheck
302
+ for i in range(2):
303
+ for j in range(2):
304
+ assert np.allclose(jacs_ad[(i, j)].numpy(), jacs_fd[(i, j)].numpy(), atol=1e-2, rtol=1e-2)
305
+
306
+ passed = gradcheck(
307
+ kernel_mixed,
308
+ dim=len(points),
309
+ inputs=[transforms, points],
310
+ raise_exception=False,
311
+ show_summary=False,
312
+ )
313
+
314
+ assert passed
315
+
316
+
232
317
  devices = get_test_devices()
233
318
 
234
319
 
@@ -85,7 +85,7 @@ def test_hashgrid_query(test, device):
85
85
 
86
86
  for i in range(num_runs):
87
87
  if print_enabled:
88
- print(f"Run: {i+1}")
88
+ print(f"Run: {i + 1}")
89
89
  print("---------")
90
90
 
91
91
  points = particle_grid(16, 32, 16, (0.0, 0.3, 0.0), cell_radius * 0.25, 0.1)