warp-lang 1.3.3__py3-none-win_amd64.whl → 1.4.0__py3-none-win_amd64.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 (107) hide show
  1. warp/__init__.py +6 -0
  2. warp/autograd.py +59 -6
  3. warp/bin/warp-clang.dll +0 -0
  4. warp/bin/warp.dll +0 -0
  5. warp/build_dll.py +8 -10
  6. warp/builtins.py +126 -4
  7. warp/codegen.py +435 -53
  8. warp/config.py +1 -1
  9. warp/context.py +678 -403
  10. warp/dlpack.py +2 -0
  11. warp/examples/benchmarks/benchmark_cloth.py +10 -0
  12. warp/examples/core/example_render_opengl.py +12 -10
  13. warp/examples/fem/example_adaptive_grid.py +251 -0
  14. warp/examples/fem/example_apic_fluid.py +1 -1
  15. warp/examples/fem/example_diffusion_3d.py +2 -2
  16. warp/examples/fem/example_magnetostatics.py +1 -1
  17. warp/examples/fem/example_streamlines.py +1 -0
  18. warp/examples/fem/utils.py +23 -4
  19. warp/examples/sim/example_cloth.py +50 -6
  20. warp/fem/__init__.py +2 -0
  21. warp/fem/adaptivity.py +493 -0
  22. warp/fem/field/field.py +2 -1
  23. warp/fem/field/nodal_field.py +18 -26
  24. warp/fem/field/test.py +4 -4
  25. warp/fem/field/trial.py +4 -4
  26. warp/fem/geometry/__init__.py +1 -0
  27. warp/fem/geometry/adaptive_nanogrid.py +843 -0
  28. warp/fem/geometry/nanogrid.py +55 -28
  29. warp/fem/space/__init__.py +1 -1
  30. warp/fem/space/nanogrid_function_space.py +69 -35
  31. warp/fem/utils.py +113 -107
  32. warp/jax_experimental.py +28 -15
  33. warp/native/array.h +0 -1
  34. warp/native/builtin.h +103 -6
  35. warp/native/bvh.cu +2 -0
  36. warp/native/cuda_util.cpp +14 -0
  37. warp/native/cuda_util.h +2 -0
  38. warp/native/error.cpp +4 -2
  39. warp/native/exports.h +99 -17
  40. warp/native/mat.h +97 -0
  41. warp/native/mesh.cpp +36 -0
  42. warp/native/mesh.cu +51 -0
  43. warp/native/mesh.h +1 -0
  44. warp/native/quat.h +43 -0
  45. warp/native/spatial.h +6 -0
  46. warp/native/vec.h +74 -0
  47. warp/native/warp.cpp +2 -1
  48. warp/native/warp.cu +10 -3
  49. warp/native/warp.h +8 -1
  50. warp/paddle.py +382 -0
  51. warp/sim/__init__.py +1 -0
  52. warp/sim/collide.py +519 -0
  53. warp/sim/integrator_euler.py +18 -5
  54. warp/sim/integrator_featherstone.py +5 -5
  55. warp/sim/integrator_vbd.py +1026 -0
  56. warp/sim/model.py +49 -23
  57. warp/stubs.py +459 -0
  58. warp/tape.py +2 -0
  59. warp/tests/aux_test_dependent.py +1 -0
  60. warp/tests/aux_test_name_clash1.py +32 -0
  61. warp/tests/aux_test_name_clash2.py +32 -0
  62. warp/tests/aux_test_square.py +1 -0
  63. warp/tests/test_array.py +188 -0
  64. warp/tests/test_async.py +3 -3
  65. warp/tests/test_atomic.py +6 -0
  66. warp/tests/test_closest_point_edge_edge.py +93 -1
  67. warp/tests/test_codegen.py +62 -15
  68. warp/tests/test_codegen_instancing.py +1457 -0
  69. warp/tests/test_collision.py +486 -0
  70. warp/tests/test_compile_consts.py +3 -28
  71. warp/tests/test_dlpack.py +170 -0
  72. warp/tests/test_examples.py +22 -8
  73. warp/tests/test_fast_math.py +10 -4
  74. warp/tests/test_fem.py +64 -0
  75. warp/tests/test_func.py +46 -0
  76. warp/tests/test_implicit_init.py +49 -0
  77. warp/tests/test_jax.py +58 -0
  78. warp/tests/test_mat.py +84 -0
  79. warp/tests/test_mesh_query_point.py +188 -0
  80. warp/tests/test_module_hashing.py +40 -0
  81. warp/tests/test_multigpu.py +3 -3
  82. warp/tests/test_overwrite.py +8 -0
  83. warp/tests/test_paddle.py +852 -0
  84. warp/tests/test_print.py +89 -0
  85. warp/tests/test_quat.py +111 -0
  86. warp/tests/test_reload.py +31 -1
  87. warp/tests/test_scalar_ops.py +2 -0
  88. warp/tests/test_static.py +412 -0
  89. warp/tests/test_streams.py +64 -3
  90. warp/tests/test_struct.py +4 -4
  91. warp/tests/test_torch.py +24 -0
  92. warp/tests/test_triangle_closest_point.py +137 -0
  93. warp/tests/test_types.py +1 -1
  94. warp/tests/test_vbd.py +386 -0
  95. warp/tests/test_vec.py +143 -0
  96. warp/tests/test_vec_scalar_ops.py +139 -0
  97. warp/tests/unittest_suites.py +12 -0
  98. warp/tests/unittest_utils.py +9 -5
  99. warp/thirdparty/dlpack.py +3 -1
  100. warp/types.py +150 -28
  101. warp/utils.py +37 -14
  102. {warp_lang-1.3.3.dist-info → warp_lang-1.4.0.dist-info}/METADATA +10 -8
  103. {warp_lang-1.3.3.dist-info → warp_lang-1.4.0.dist-info}/RECORD +106 -94
  104. warp/tests/test_point_triangle_closest_point.py +0 -143
  105. {warp_lang-1.3.3.dist-info → warp_lang-1.4.0.dist-info}/LICENSE.md +0 -0
  106. {warp_lang-1.3.3.dist-info → warp_lang-1.4.0.dist-info}/WHEEL +0 -0
  107. {warp_lang-1.3.3.dist-info → warp_lang-1.4.0.dist-info}/top_level.txt +0 -0
@@ -192,12 +192,14 @@ def test_py_arithmetic_ops(test, device, dtype):
192
192
  test.assertSequenceEqual(-v, make_vec(-1, 2, -3))
193
193
  test.assertSequenceEqual(v + vec_cls(5, 5, 5), make_vec(6, 3, 8))
194
194
  test.assertSequenceEqual(v - vec_cls(5, 5, 5), make_vec(-4, -7, -2))
195
+ test.assertSequenceEqual(v % vec_cls(2, 2, 2), make_vec(1, 0, 1))
195
196
 
196
197
  v = vec_cls(2, 4, 6)
197
198
  test.assertSequenceEqual(v * wptype(2), make_vec(4, 8, 12))
198
199
  test.assertSequenceEqual(wptype(2) * v, make_vec(4, 8, 12))
199
200
  test.assertSequenceEqual(v / wptype(2), make_vec(1, 2, 3))
200
201
  test.assertSequenceEqual(wptype(24) / v, make_vec(12, 6, 4))
202
+ test.assertSequenceEqual(v % vec_cls(3, 3, 3), make_vec(2, 1, 0))
201
203
 
202
204
 
203
205
  def test_constructors(test, device, dtype, register_kernels=False):
@@ -1797,6 +1799,140 @@ def test_dotproduct(test, device, dtype, register_kernels=False):
1797
1799
  tape.zero()
1798
1800
 
1799
1801
 
1802
+ def test_modulo(test, device, dtype, register_kernels=False):
1803
+ rng = np.random.default_rng(123)
1804
+
1805
+ tol = {
1806
+ np.float16: 1.0e-2,
1807
+ np.float32: 1.0e-6,
1808
+ np.float64: 1.0e-8,
1809
+ }.get(dtype, 0)
1810
+
1811
+ wptype = wp.types.np_dtype_to_warp_type[np.dtype(dtype)]
1812
+ vec2 = wp.types.vector(length=2, dtype=wptype)
1813
+ vec3 = wp.types.vector(length=3, dtype=wptype)
1814
+ vec4 = wp.types.vector(length=4, dtype=wptype)
1815
+ vec5 = wp.types.vector(length=5, dtype=wptype)
1816
+
1817
+ def check_mod(
1818
+ s2: wp.array(dtype=vec2),
1819
+ s3: wp.array(dtype=vec3),
1820
+ s4: wp.array(dtype=vec4),
1821
+ s5: wp.array(dtype=vec5),
1822
+ v2: wp.array(dtype=vec2),
1823
+ v3: wp.array(dtype=vec3),
1824
+ v4: wp.array(dtype=vec4),
1825
+ v5: wp.array(dtype=vec5),
1826
+ v20: wp.array(dtype=wptype),
1827
+ v21: wp.array(dtype=wptype),
1828
+ v30: wp.array(dtype=wptype),
1829
+ v31: wp.array(dtype=wptype),
1830
+ v32: wp.array(dtype=wptype),
1831
+ v40: wp.array(dtype=wptype),
1832
+ v41: wp.array(dtype=wptype),
1833
+ v42: wp.array(dtype=wptype),
1834
+ v43: wp.array(dtype=wptype),
1835
+ v50: wp.array(dtype=wptype),
1836
+ v51: wp.array(dtype=wptype),
1837
+ v52: wp.array(dtype=wptype),
1838
+ v53: wp.array(dtype=wptype),
1839
+ v54: wp.array(dtype=wptype),
1840
+ ):
1841
+ v20[0] = (wptype(2) * wp.mod(v2[0], s2[0]))[0]
1842
+ v21[0] = (wptype(2) * wp.mod(v2[0], s2[0]))[1]
1843
+
1844
+ v30[0] = (wptype(2) * wp.mod(v3[0], s3[0]))[0]
1845
+ v31[0] = (wptype(2) * wp.mod(v3[0], s3[0]))[1]
1846
+ v32[0] = (wptype(2) * wp.mod(v3[0], s3[0]))[2]
1847
+
1848
+ v40[0] = (wptype(2) * wp.mod(v4[0], s4[0]))[0]
1849
+ v41[0] = (wptype(2) * wp.mod(v4[0], s4[0]))[1]
1850
+ v42[0] = (wptype(2) * wp.mod(v4[0], s4[0]))[2]
1851
+ v43[0] = (wptype(2) * wp.mod(v4[0], s4[0]))[3]
1852
+
1853
+ v50[0] = (wptype(2) * wp.mod(v5[0], s5[0]))[0]
1854
+ v51[0] = (wptype(2) * wp.mod(v5[0], s5[0]))[1]
1855
+ v52[0] = (wptype(2) * wp.mod(v5[0], s5[0]))[2]
1856
+ v53[0] = (wptype(2) * wp.mod(v5[0], s5[0]))[3]
1857
+ v54[0] = (wptype(2) * wp.mod(v5[0], s5[0]))[4]
1858
+
1859
+ kernel = getkernel(check_mod, suffix=dtype.__name__)
1860
+
1861
+ if register_kernels:
1862
+ return
1863
+
1864
+ s2 = wp.array(randvals(rng, (1, 2), dtype), dtype=vec2, requires_grad=True, device=device)
1865
+ s3 = wp.array(randvals(rng, (1, 3), dtype), dtype=vec3, requires_grad=True, device=device)
1866
+ s4 = wp.array(randvals(rng, (1, 4), dtype), dtype=vec4, requires_grad=True, device=device)
1867
+ s5 = wp.array(randvals(rng, (1, 5), dtype), dtype=vec5, requires_grad=True, device=device)
1868
+ v2 = wp.array(randvals(rng, (1, 2), dtype), dtype=vec2, requires_grad=True, device=device)
1869
+ v3 = wp.array(randvals(rng, (1, 3), dtype), dtype=vec3, requires_grad=True, device=device)
1870
+ v4 = wp.array(randvals(rng, (1, 4), dtype), dtype=vec4, requires_grad=True, device=device)
1871
+ v5 = wp.array(randvals(rng, (1, 5), dtype), dtype=vec5, requires_grad=True, device=device)
1872
+ v20 = wp.zeros(1, dtype=wptype, requires_grad=True, device=device)
1873
+ v21 = wp.zeros(1, dtype=wptype, requires_grad=True, device=device)
1874
+ v30 = wp.zeros(1, dtype=wptype, requires_grad=True, device=device)
1875
+ v31 = wp.zeros(1, dtype=wptype, requires_grad=True, device=device)
1876
+ v32 = wp.zeros(1, dtype=wptype, requires_grad=True, device=device)
1877
+ v40 = wp.zeros(1, dtype=wptype, requires_grad=True, device=device)
1878
+ v41 = wp.zeros(1, dtype=wptype, requires_grad=True, device=device)
1879
+ v42 = wp.zeros(1, dtype=wptype, requires_grad=True, device=device)
1880
+ v43 = wp.zeros(1, dtype=wptype, requires_grad=True, device=device)
1881
+ v50 = wp.zeros(1, dtype=wptype, requires_grad=True, device=device)
1882
+ v51 = wp.zeros(1, dtype=wptype, requires_grad=True, device=device)
1883
+ v52 = wp.zeros(1, dtype=wptype, requires_grad=True, device=device)
1884
+ v53 = wp.zeros(1, dtype=wptype, requires_grad=True, device=device)
1885
+ v54 = wp.zeros(1, dtype=wptype, requires_grad=True, device=device)
1886
+ tape = wp.Tape()
1887
+ with tape:
1888
+ wp.launch(
1889
+ kernel,
1890
+ dim=1,
1891
+ inputs=[
1892
+ s2,
1893
+ s3,
1894
+ s4,
1895
+ s5,
1896
+ v2,
1897
+ v3,
1898
+ v4,
1899
+ v5,
1900
+ ],
1901
+ outputs=[
1902
+ v20,
1903
+ v21,
1904
+ v30,
1905
+ v31,
1906
+ v32,
1907
+ v40,
1908
+ v41,
1909
+ v42,
1910
+ v43,
1911
+ v50,
1912
+ v51,
1913
+ v52,
1914
+ v53,
1915
+ v54,
1916
+ ],
1917
+ device=device,
1918
+ )
1919
+
1920
+ assert_np_equal(v20.numpy()[0], 2.0 * np.fmod(v2.numpy(), s2.numpy())[0, 0], tol=10 * tol)
1921
+ assert_np_equal(v21.numpy()[0], 2.0 * np.fmod(v2.numpy(), s2.numpy())[0, 1], tol=10 * tol)
1922
+ assert_np_equal(v30.numpy()[0], 2.0 * np.fmod(v3.numpy(), s3.numpy())[0, 0], tol=10 * tol)
1923
+ assert_np_equal(v31.numpy()[0], 2.0 * np.fmod(v3.numpy(), s3.numpy())[0, 1], tol=10 * tol)
1924
+ assert_np_equal(v32.numpy()[0], 2.0 * np.fmod(v3.numpy(), s3.numpy())[0, 2], tol=10 * tol)
1925
+ assert_np_equal(v40.numpy()[0], 2.0 * np.fmod(v4.numpy(), s4.numpy())[0, 0], tol=10 * tol)
1926
+ assert_np_equal(v41.numpy()[0], 2.0 * np.fmod(v4.numpy(), s4.numpy())[0, 1], tol=10 * tol)
1927
+ assert_np_equal(v42.numpy()[0], 2.0 * np.fmod(v4.numpy(), s4.numpy())[0, 2], tol=10 * tol)
1928
+ assert_np_equal(v43.numpy()[0], 2.0 * np.fmod(v4.numpy(), s4.numpy())[0, 3], tol=10 * tol)
1929
+ assert_np_equal(v50.numpy()[0], 2.0 * np.fmod(v5.numpy(), s5.numpy())[0, 0], tol=10 * tol)
1930
+ assert_np_equal(v51.numpy()[0], 2.0 * np.fmod(v5.numpy(), s5.numpy())[0, 1], tol=10 * tol)
1931
+ assert_np_equal(v52.numpy()[0], 2.0 * np.fmod(v5.numpy(), s5.numpy())[0, 2], tol=10 * tol)
1932
+ assert_np_equal(v53.numpy()[0], 2.0 * np.fmod(v5.numpy(), s5.numpy())[0, 3], tol=10 * tol)
1933
+ assert_np_equal(v54.numpy()[0], 2.0 * np.fmod(v5.numpy(), s5.numpy())[0, 4], tol=10 * tol)
1934
+
1935
+
1800
1936
  def test_equivalent_types(test, device, dtype, register_kernels=False):
1801
1937
  wptype = wp.types.np_dtype_to_warp_type[np.dtype(dtype)]
1802
1938
 
@@ -2150,6 +2286,9 @@ for dtype in np_scalar_types:
2150
2286
  add_function_test_register_kernel(
2151
2287
  TestVecScalarOps, f"test_addition_{dtype.__name__}", test_addition, devices=devices, dtype=dtype
2152
2288
  )
2289
+ add_function_test_register_kernel(
2290
+ TestVecScalarOps, f"test_modulo_{dtype.__name__}", test_modulo, devices=devices, dtype=dtype
2291
+ )
2153
2292
  add_function_test_register_kernel(
2154
2293
  TestVecScalarOps, f"test_dotproduct_{dtype.__name__}", test_dotproduct, devices=devices, dtype=dtype
2155
2294
  )
@@ -98,6 +98,7 @@ def default_suite(test_loader: unittest.TestLoader = unittest.defaultTestLoader)
98
98
  from warp.tests.test_bvh import TestBvh
99
99
  from warp.tests.test_closest_point_edge_edge import TestClosestPointEdgeEdgeMethods
100
100
  from warp.tests.test_codegen import TestCodeGen
101
+ from warp.tests.test_codegen_instancing import TestCodeGenInstancing
101
102
  from warp.tests.test_compile_consts import TestConstants
102
103
  from warp.tests.test_conditional import TestConditional
103
104
  from warp.tests.test_copy import TestCopy
@@ -117,6 +118,7 @@ def default_suite(test_loader: unittest.TestLoader = unittest.defaultTestLoader)
117
118
  from warp.tests.test_fem import TestFem, TestFemShapeFunctions
118
119
  from warp.tests.test_fp16 import TestFp16
119
120
  from warp.tests.test_func import TestFunc
121
+ from warp.tests.test_future_annotations import TestFutureAnnotations
120
122
  from warp.tests.test_generics import TestGenerics
121
123
  from warp.tests.test_grad import TestGrad
122
124
  from warp.tests.test_grad_customs import TestGradCustoms
@@ -160,6 +162,7 @@ def default_suite(test_loader: unittest.TestLoader = unittest.defaultTestLoader)
160
162
  from warp.tests.test_reload import TestReload
161
163
  from warp.tests.test_rounding import TestRounding
162
164
  from warp.tests.test_runlength_encode import TestRunlengthEncode
165
+ from warp.tests.test_scalar_ops import TestScalarOps
163
166
  from warp.tests.test_sim_grad import TestSimGradients
164
167
  from warp.tests.test_sim_kinematics import TestSimKinematics
165
168
  from warp.tests.test_smoothstep import TestSmoothstep
@@ -172,8 +175,10 @@ def default_suite(test_loader: unittest.TestLoader = unittest.defaultTestLoader)
172
175
  from warp.tests.test_tape import TestTape
173
176
  from warp.tests.test_torch import TestTorch
174
177
  from warp.tests.test_transient_module import TestTransientModule
178
+ from warp.tests.test_triangle_closest_point import TestTriangleClosestPoint
175
179
  from warp.tests.test_types import TestTypes
176
180
  from warp.tests.test_utils import TestUtils
181
+ from warp.tests.test_vbd import TestVBD
177
182
  from warp.tests.test_vec import TestVec
178
183
  from warp.tests.test_vec_lite import TestVecLite
179
184
  from warp.tests.test_vec_scalar_ops import TestVecScalarOps
@@ -193,6 +198,7 @@ def default_suite(test_loader: unittest.TestLoader = unittest.defaultTestLoader)
193
198
  TestBvh,
194
199
  TestClosestPointEdgeEdgeMethods,
195
200
  TestCodeGen,
201
+ TestCodeGenInstancing,
196
202
  TestConstants,
197
203
  TestConditional,
198
204
  TestCopy,
@@ -211,6 +217,7 @@ def default_suite(test_loader: unittest.TestLoader = unittest.defaultTestLoader)
211
217
  TestFemShapeFunctions,
212
218
  TestFp16,
213
219
  TestFunc,
220
+ TestFutureAnnotations,
214
221
  TestGenerics,
215
222
  TestGrad,
216
223
  TestGradCustoms,
@@ -254,6 +261,7 @@ def default_suite(test_loader: unittest.TestLoader = unittest.defaultTestLoader)
254
261
  TestReload,
255
262
  TestRounding,
256
263
  TestRunlengthEncode,
264
+ TestScalarOps,
257
265
  TestSimGradients,
258
266
  TestSimKinematics,
259
267
  TestSmoothstep,
@@ -266,8 +274,10 @@ def default_suite(test_loader: unittest.TestLoader = unittest.defaultTestLoader)
266
274
  TestTape,
267
275
  TestTorch,
268
276
  TestTransientModule,
277
+ TestTriangleClosestPoint,
269
278
  TestTypes,
270
279
  TestUtils,
280
+ TestVBD,
271
281
  TestVec,
272
282
  TestVecLite,
273
283
  TestVecScalarOps,
@@ -288,6 +298,7 @@ def kit_suite(test_loader: unittest.TestLoader = unittest.defaultTestLoader):
288
298
  from warp.tests.test_array_reduce import TestArrayReduce
289
299
  from warp.tests.test_bvh import TestBvh
290
300
  from warp.tests.test_codegen import TestCodeGen
301
+ from warp.tests.test_codegen_instancing import TestCodeGenInstancing
291
302
  from warp.tests.test_compile_consts import TestConstants
292
303
  from warp.tests.test_conditional import TestConditional
293
304
  from warp.tests.test_ctypes import TestCTypes
@@ -332,6 +343,7 @@ def kit_suite(test_loader: unittest.TestLoader = unittest.defaultTestLoader):
332
343
  TestArrayReduce,
333
344
  TestBvh,
334
345
  TestCodeGen,
346
+ TestCodeGenInstancing,
335
347
  TestConstants,
336
348
  TestConditional,
337
349
  TestCTypes,
@@ -198,11 +198,15 @@ class CheckOutput:
198
198
  if s != "":
199
199
  print(s.rstrip())
200
200
 
201
- # fail if test produces unexpected output (e.g.: from wp.expect_eq() builtins)
202
- # we allow strings starting of the form "Module xxx load on device xxx"
203
- # for lazy loaded modules
204
- if s != "" and not s.startswith("Module"):
205
- self.test.fail(f"Unexpected output:\n'{s.rstrip()}'")
201
+ # fail if test produces unexpected output (e.g.: from wp.expect_eq() builtins)
202
+ # we allow strings starting of the form "Module xxx load on device xxx"
203
+ # for lazy loaded modules
204
+ filtered_s = "\n".join(
205
+ [line for line in s.splitlines() if not (line.startswith("Module") and "load on device" in line)]
206
+ )
207
+
208
+ if filtered_s.strip():
209
+ self.test.fail(f"Unexpected output:\n'{s.rstrip()}'")
206
210
 
207
211
 
208
212
  def assert_array_equal(result: wp.array, expect: wp.array):
warp/thirdparty/dlpack.py CHANGED
@@ -58,6 +58,7 @@ class DLDataTypeCode(ctypes.c_uint8):
58
58
  kDLOpaquePointer = 3
59
59
  kDLBfloat = 4
60
60
  kDLComplex = 5
61
+ kDLBool = 6
61
62
 
62
63
  def __str__(self):
63
64
  return {
@@ -66,6 +67,7 @@ class DLDataTypeCode(ctypes.c_uint8):
66
67
  self.kDLFloat: "float",
67
68
  self.kDLBfloat: "bfloat",
68
69
  self.kDLComplex: "complex",
70
+ self.kDLBool: "bool",
69
71
  self.kDLOpaquePointer: "void_p",
70
72
  }[self.value]
71
73
 
@@ -85,7 +87,7 @@ class DLDataType(ctypes.Structure):
85
87
  ("lanes", ctypes.c_uint16),
86
88
  ]
87
89
  TYPE_MAP = {
88
- "bool": (DLDataTypeCode.kDLUInt, 1, 1),
90
+ "bool": (DLDataTypeCode.kDLBool, 8, 1),
89
91
  "int8": (DLDataTypeCode.kDLInt, 8, 1),
90
92
  "int16": (DLDataTypeCode.kDLInt, 16, 1),
91
93
  "int32": (DLDataTypeCode.kDLInt, 32, 1),
warp/types.py CHANGED
@@ -66,8 +66,8 @@ def constant(x):
66
66
  x: Compile-time constant value, can be any of the built-in math types.
67
67
  """
68
68
 
69
- if not isinstance(x, (builtins.bool, int, float, tuple(scalar_and_bool_types), ctypes.Array)):
70
- raise RuntimeError(f"Invalid constant type: {type(x)}")
69
+ if not is_value(x):
70
+ raise TypeError(f"Invalid constant type: {type(x)}")
71
71
 
72
72
  return x
73
73
 
@@ -237,6 +237,12 @@ def vector(length, dtype):
237
237
  def __rtruediv__(self, x):
238
238
  return warp.div(x, self)
239
239
 
240
+ def __mod__(self, x):
241
+ return warp.mod(self, x)
242
+
243
+ def __rmod__(self, x):
244
+ return warp.mod(x, self)
245
+
240
246
  def __pos__(self):
241
247
  return warp.pos(self)
242
248
 
@@ -519,6 +525,12 @@ class scalar_base:
519
525
  def __rtruediv__(self, x):
520
526
  return warp.div(x, self)
521
527
 
528
+ def __mod__(self, x):
529
+ return warp.mod(self, x)
530
+
531
+ def __rmod__(self, x):
532
+ return warp.mod(x, self)
533
+
522
534
  def __pos__(self):
523
535
  return warp.pos(self)
524
536
 
@@ -979,6 +991,43 @@ vector_types = (
979
991
  spatial_matrixd,
980
992
  )
981
993
 
994
+ atomic_vector_types = (
995
+ vec2i,
996
+ vec2ui,
997
+ vec2l,
998
+ vec2ul,
999
+ vec2h,
1000
+ vec2f,
1001
+ vec2d,
1002
+ vec3i,
1003
+ vec3ui,
1004
+ vec3l,
1005
+ vec3ul,
1006
+ vec3h,
1007
+ vec3f,
1008
+ vec3d,
1009
+ vec4i,
1010
+ vec4ui,
1011
+ vec4l,
1012
+ vec4ul,
1013
+ vec4h,
1014
+ vec4f,
1015
+ vec4d,
1016
+ mat22h,
1017
+ mat22f,
1018
+ mat22d,
1019
+ mat33h,
1020
+ mat33f,
1021
+ mat33d,
1022
+ mat44h,
1023
+ mat44f,
1024
+ mat44d,
1025
+ quath,
1026
+ quatf,
1027
+ quatd,
1028
+ )
1029
+ atomic_types = float_types + (int32, uint32, int64, uint64) + atomic_vector_types
1030
+
982
1031
  np_dtype_to_warp_type = {
983
1032
  # Numpy scalar types
984
1033
  np.bool_: bool,
@@ -1253,7 +1302,7 @@ def type_to_warp(dtype):
1253
1302
 
1254
1303
  def type_typestr(dtype):
1255
1304
  if dtype == bool:
1256
- return "?"
1305
+ return "|b1"
1257
1306
  elif dtype == float16:
1258
1307
  return "<f2"
1259
1308
  elif dtype == float32:
@@ -1261,9 +1310,9 @@ def type_typestr(dtype):
1261
1310
  elif dtype == float64:
1262
1311
  return "<f8"
1263
1312
  elif dtype == int8:
1264
- return "b"
1313
+ return "|i1"
1265
1314
  elif dtype == uint8:
1266
- return "B"
1315
+ return "|u1"
1267
1316
  elif dtype == int16:
1268
1317
  return "<i2"
1269
1318
  elif dtype == uint16:
@@ -1335,7 +1384,7 @@ value_types = (int, float, builtins.bool) + scalar_types
1335
1384
 
1336
1385
  # returns true for all value types (int, float, bool, scalars, vectors, matrices)
1337
1386
  def type_is_value(x):
1338
- return x in value_types or issubclass(x, ctypes.Array)
1387
+ return x in value_types or hasattr(x, "_wp_scalar_type_")
1339
1388
 
1340
1389
 
1341
1390
  # equivalent of the above but for values
@@ -1442,6 +1491,10 @@ def types_equal(a, b, match_generic=False):
1442
1491
  if is_array(a) and type(a) is type(b):
1443
1492
  return True
1444
1493
 
1494
+ # match NewStructInstance and Struct dtype
1495
+ if getattr(a, "cls", "a") is getattr(b, "cls", "b"):
1496
+ return True
1497
+
1445
1498
  return scalars_equal(a, b, match_generic)
1446
1499
 
1447
1500
 
@@ -1486,7 +1539,7 @@ def array_ctype_from_interface(interface: dict, dtype=None, owner=None):
1486
1539
  strides = strides_from_shape(shape, element_dtype)
1487
1540
 
1488
1541
  if dtype is None:
1489
- # accept verbatum
1542
+ # accept verbatim
1490
1543
  pass
1491
1544
  elif hasattr(dtype, "_shape_"):
1492
1545
  # vector/matrix types, ensure element dtype matches
@@ -2005,24 +2058,27 @@ class array(Array):
2005
2058
  if self.device is None:
2006
2059
  raise RuntimeError("Array has no device assigned")
2007
2060
 
2008
- if self.device.is_cuda and stream != -1:
2009
- if not isinstance(stream, int):
2010
- raise TypeError("DLPack stream must be an integer or None")
2011
-
2012
- # assume that the array is being used on its device's current stream
2013
- array_stream = self.device.stream
2014
-
2015
- # the external stream should wait for outstanding operations to complete
2016
- if stream in (None, 0, 1):
2017
- external_stream = 0
2018
- else:
2019
- external_stream = stream
2020
-
2021
- # Performance note: avoid wrapping the external stream in a temporary Stream object
2022
- if external_stream != array_stream.cuda_stream:
2023
- warp.context.runtime.core.cuda_stream_wait_stream(
2024
- external_stream, array_stream.cuda_stream, array_stream.cached_event.cuda_event
2025
- )
2061
+ # check if synchronization is needed
2062
+ if stream != -1:
2063
+ if self.device.is_cuda:
2064
+ # validate stream argument
2065
+ if stream is None:
2066
+ stream = 1 # legacy default stream
2067
+ elif not isinstance(stream, int) or stream < -1:
2068
+ raise TypeError("DLPack stream must None or an integer >= -1")
2069
+
2070
+ # assume that the array is being used on its device's current stream
2071
+ array_stream = self.device.stream
2072
+
2073
+ # Performance note: avoid wrapping the external stream in a temporary Stream object
2074
+ if stream != array_stream.cuda_stream:
2075
+ warp.context.runtime.core.cuda_stream_wait_stream(
2076
+ stream, array_stream.cuda_stream, array_stream.cached_event.cuda_event
2077
+ )
2078
+ elif self.device.is_cpu:
2079
+ # on CPU, stream must be None or -1
2080
+ if stream is not None:
2081
+ raise TypeError("DLPack stream must be None or -1 for CPU device")
2026
2082
 
2027
2083
  return warp.dlpack.to_dlpack(self)
2028
2084
 
@@ -3012,8 +3068,8 @@ class Mesh:
3012
3068
  raise RuntimeError("Mesh indices should be a flattened 1d array of indices")
3013
3069
 
3014
3070
  self.device = points.device
3015
- self.points = points
3016
- self.velocities = velocities
3071
+ self._points = points
3072
+ self._velocities = velocities
3017
3073
  self.indices = indices
3018
3074
 
3019
3075
  self.runtime = warp.context.runtime
@@ -3058,6 +3114,72 @@ class Mesh:
3058
3114
  self.runtime.core.mesh_refit_device(self.id)
3059
3115
  self.runtime.verify_cuda_device(self.device)
3060
3116
 
3117
+ @property
3118
+ def points(self):
3119
+ """The array of mesh's vertex positions of type :class:`warp.vec3`.
3120
+
3121
+ The `Mesh.points` property has a custom setter method. Users can modify the vertex positions in-place,
3122
+ but the `refit()` method must be called manually after such modifications. Alternatively, assigning a new array
3123
+ to this property is also supported. The new array must have the same shape as the original, and once assigned,
3124
+ the `Mesh` class will automatically perform a refit operation based on the new vertex positions.
3125
+ """
3126
+ return self._points
3127
+
3128
+ @points.setter
3129
+ def points(self, points_new):
3130
+ if points_new.device != self._points.device:
3131
+ raise RuntimeError(
3132
+ "The new points and the original points must live on the same device, currently "
3133
+ "the new points lives on {} while the old points lives on {}.".format(
3134
+ points_new.device, self._points.device
3135
+ )
3136
+ )
3137
+
3138
+ if points_new.ndim != 1 or points_new.shape[0] != self._points.shape[0]:
3139
+ raise RuntimeError(
3140
+ "the new points and the original points must have the same shape, currently new points shape is: {},"
3141
+ " while the old points' shape is: {}".format(points_new.shape, self._points.shape)
3142
+ )
3143
+
3144
+ self._points = points_new
3145
+ if self.device.is_cpu:
3146
+ self.runtime.core.mesh_set_points_host(self.id, points_new.__ctype__())
3147
+ else:
3148
+ self.runtime.core.mesh_set_points_device(self.id, points_new.__ctype__())
3149
+ self.runtime.verify_cuda_device(self.device)
3150
+
3151
+ @property
3152
+ def velocities(self):
3153
+ """The array of mesh's velocities of type :class:`warp.vec3`.
3154
+
3155
+ This is a property with a custom setter method. Users can modify the velocities in-place,
3156
+ or assigning a new array to this property. No refitting is needed for changing velocities.
3157
+ """
3158
+ return self._velocities
3159
+
3160
+ @velocities.setter
3161
+ def velocities(self, velocities_new):
3162
+ if velocities_new.device != self._velocities.device:
3163
+ raise RuntimeError(
3164
+ "The new points and the original points must live on the same device, currently "
3165
+ "the new points lives on {} while the old points lives on {}.".format(
3166
+ velocities_new.device, self._velocities.device
3167
+ )
3168
+ )
3169
+
3170
+ if velocities_new.ndim != 1 or velocities_new.shape[0] != self._velocities.shape[0]:
3171
+ raise RuntimeError(
3172
+ "the new points and the original points must have the same shape, currently new points shape is: {},"
3173
+ " while the old points' shape is: {}".format(velocities_new.shape, self._velocities.shape)
3174
+ )
3175
+
3176
+ self._velocities = velocities_new
3177
+ if self.device.is_cpu:
3178
+ self.runtime.core.mesh_set_velocities_host(self.id, velocities_new.__ctype__())
3179
+ else:
3180
+ self.runtime.core.mesh_set_velocities_device(self.id, velocities_new.__ctype__())
3181
+ self.runtime.verify_cuda_device(self.device)
3182
+
3061
3183
 
3062
3184
  class Volume:
3063
3185
  #: Enum value to specify nearest-neighbor interpolation during sampling
@@ -5025,7 +5147,7 @@ def get_type_code(arg_type):
5025
5147
  elif isinstance(arg_type, indexedfabricarray):
5026
5148
  return f"ifa{arg_type.ndim}{get_type_code(arg_type.dtype)}"
5027
5149
  elif isinstance(arg_type, warp.codegen.Struct):
5028
- return warp.codegen.make_full_qualified_name(arg_type.cls)
5150
+ return arg_type.native_name
5029
5151
  elif arg_type == Scalar:
5030
5152
  # generic scalar type
5031
5153
  return "s?"
warp/utils.py CHANGED
@@ -11,7 +11,7 @@ import os
11
11
  import sys
12
12
  import time
13
13
  import warnings
14
- from typing import Any
14
+ from typing import Any, Optional
15
15
 
16
16
  import numpy as np
17
17
 
@@ -578,7 +578,32 @@ class ScopedDevice:
578
578
 
579
579
 
580
580
  class ScopedStream:
581
- def __init__(self, stream, sync_enter=True, sync_exit=False):
581
+ """A context manager to temporarily change the current stream on a device.
582
+
583
+ Attributes:
584
+ stream (Stream or None): The stream that will temporarily become the device's
585
+ default stream within the context.
586
+ saved_stream (Stream): The device's previous current stream. This is
587
+ restored as the device's current stream on exiting the context.
588
+ sync_enter (bool): Whether to synchronize this context's stream with
589
+ the device's previous current stream on entering the context.
590
+ sync_exit (bool): Whether to synchronize the device's previous current
591
+ with this context's stream on exiting the context.
592
+ device (Device): The device associated with the stream.
593
+ """
594
+
595
+ def __init__(self, stream: Optional[wp.Stream], sync_enter: bool = True, sync_exit: bool = False):
596
+ """Initializes the context manager with a stream and synchronization options.
597
+
598
+ Args:
599
+ stream: The stream that will temporarily become the device's
600
+ default stream within the context.
601
+ sync_enter (bool): Whether to synchronize this context's stream with
602
+ the device's previous current stream on entering the context.
603
+ sync_exit (bool): Whether to synchronize the device's previous current
604
+ with this context's stream on exiting the context.
605
+ """
606
+
582
607
  self.stream = stream
583
608
  self.sync_enter = sync_enter
584
609
  self.sync_exit = sync_exit
@@ -832,16 +857,22 @@ for T in [wp.float16, wp.float32, wp.float64]:
832
857
  wp.overload(add_kernel_3d, [wp.array3d(dtype=T), wp.array3d(dtype=T), T])
833
858
 
834
859
 
835
- def check_iommu():
836
- """Check if IOMMU is enabled on Linux, which can affect peer-to-peer transfers.
860
+ def check_p2p():
861
+ """Check if the machine is configured properly for peer-to-peer transfers.
837
862
 
838
863
  Returns:
839
- A Boolean indicating whether IOMMU is configured properly for peer-to-peer transfers.
864
+ A Boolean indicating whether the machine is configured properly for peer-to-peer transfers.
840
865
  On Linux, this function attempts to determine if IOMMU is enabled and will return `False` if IOMMU is detected.
841
866
  On other operating systems, it always return `True`.
842
867
  """
843
868
 
869
+ # HACK: allow disabling P2P tests using an environment variable
870
+ disable_p2p_tests = os.getenv("WARP_DISABLE_P2P_TESTS", default="0")
871
+ if int(disable_p2p_tests):
872
+ return False
873
+
844
874
  if sys.platform == "linux":
875
+ # IOMMU enablement can affect peer-to-peer transfers.
845
876
  # On modern Linux, there should be IOMMU-related entries in the /sys file system.
846
877
  # This should be more reliable than checking kernel logs like dmesg.
847
878
  if os.path.isdir("/sys/class/iommu") and os.listdir("/sys/class/iommu"):
@@ -849,15 +880,7 @@ def check_iommu():
849
880
  if os.path.isdir("/sys/kernel/iommu_groups") and os.listdir("/sys/kernel/iommu_groups"):
850
881
  return False
851
882
 
852
- # HACK: disable P2P tests on misbehaving agents
853
- disable_p2p_tests = os.getenv("WARP_DISABLE_P2P_TESTS", default="0")
854
- if int(disable_p2p_tests):
855
- return False
856
-
857
- return True
858
- else:
859
- # doesn't matter
860
- return True
883
+ return True
861
884
 
862
885
 
863
886
  class timing_result_t(ctypes.Structure):