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
@@ -2030,6 +2030,486 @@ def test_transform_to_matrix(test, device, dtype, register_kernels=False):
2030
2030
  wp.launch(kernel, dim=1, device=device)
2031
2031
 
2032
2032
 
2033
+ def test_transform_compose(test, device, dtype, register_kernels=False):
2034
+ wptype = wp.types.np_dtype_to_warp_type[np.dtype(dtype)]
2035
+ mat44 = wp.types.matrix((4, 4), wptype)
2036
+ vec3 = wp.types.vector(3, wptype)
2037
+ quat = wp.types.quaternion(wptype)
2038
+
2039
+ def transform_compose_kernel():
2040
+ p = vec3(wptype(1.0), wptype(2.0), wptype(3.0))
2041
+ q = quat(wptype(-0.4), wptype(0.2), wptype(-0.4), wptype(0.8))
2042
+ s = vec3(wptype(4.0), wptype(5.0), wptype(6.0))
2043
+ m = wp.transform_compose(p, q, s)
2044
+ # fmt: off
2045
+ wp.expect_near(
2046
+ m,
2047
+ mat44(
2048
+ wptype(0.6 * 4.0), wptype(0.48 * 5.0), wptype(0.64 * 6.0), wptype(1.0),
2049
+ wptype(-0.8 * 4.0), wptype(0.36 * 5.0), wptype(0.48 * 6.0), wptype(2.0),
2050
+ wptype(0.0 * 4.0), wptype(-0.8 * 5.0), wptype(0.6 * 6.0), wptype(3.0),
2051
+ wptype(0.0), wptype(0.0), wptype(0.0), wptype(1.0),
2052
+ ),
2053
+ tolerance=wptype(1e-2),
2054
+ )
2055
+ # fmt: on
2056
+
2057
+ kernel = getkernel(transform_compose_kernel, suffix=dtype.__name__)
2058
+
2059
+ if register_kernels:
2060
+ return
2061
+
2062
+ wp.launch(kernel, dim=1, device=device)
2063
+
2064
+
2065
+ def test_transform_decompose(test, device, dtype, register_kernels=False):
2066
+ wptype = wp.types.np_dtype_to_warp_type[np.dtype(dtype)]
2067
+ mat44 = wp.types.matrix((4, 4), wptype)
2068
+ vec3 = wp.types.vector(3, wptype)
2069
+ quat = wp.types.quaternion(wptype)
2070
+
2071
+ def transform_decompose_kernel():
2072
+ # fmt: off
2073
+ m = mat44(
2074
+ wptype(0.6 * 4.0), wptype(0.48 * 5.0), wptype(0.64 * 6.0), wptype(1.0),
2075
+ wptype(-0.8 * 4.0), wptype(0.36 * 5.0), wptype(0.48 * 6.0), wptype(2.0),
2076
+ wptype(0.0 * 4.0), wptype(-0.8 * 5.0), wptype(0.6 * 6.0), wptype(3.0),
2077
+ wptype(0.0), wptype(0.0), wptype(0.0), wptype(1.0),
2078
+ )
2079
+ # fmt: on
2080
+ p, q, s = wp.transform_decompose(m)
2081
+ wp.expect_near(p, vec3(wptype(1.0), wptype(2.0), wptype(3.0)), tolerance=wptype(1e-2))
2082
+ wp.expect_near(q, quat(wptype(-0.4), wptype(0.2), wptype(-0.4), wptype(0.8)), tolerance=wptype(1e-2))
2083
+ wp.expect_near(s, vec3(wptype(4.0), wptype(5.0), wptype(6.0)), tolerance=wptype(1e-2))
2084
+
2085
+ kernel = getkernel(transform_decompose_kernel, suffix=dtype.__name__)
2086
+
2087
+ if register_kernels:
2088
+ return
2089
+
2090
+ wp.launch(kernel, dim=1, device=device)
2091
+
2092
+
2093
+ def test_transform_getter_setter(test, device):
2094
+ t = wp.transform()
2095
+
2096
+ a = wp.vec3(1.0, 2.0, 3.0)
2097
+ b = wp.quat(0.0, 0.0, 0.0, 1.0)
2098
+
2099
+ t.p = a
2100
+ t.q = b
2101
+
2102
+ c = t.p
2103
+ d = t.q
2104
+
2105
+ test.assertEqual(c, a)
2106
+ test.assertEqual(d, b)
2107
+
2108
+
2109
+ @wp.kernel
2110
+ def transform_extract_subscript(x: wp.array(dtype=wp.transform), y: wp.array(dtype=float)):
2111
+ tid = wp.tid()
2112
+
2113
+ a = x[tid]
2114
+ b = a[0] + 2.0 * a[1] + 3.0 * a[2] + 4.0 * a[3] + 5.0 * a[4] + 6.0 * a[5] + 7.0 * a[6]
2115
+ y[tid] = b
2116
+
2117
+
2118
+ @wp.kernel
2119
+ def transform_extract_attribute(
2120
+ x: wp.array(dtype=wp.transform), y: wp.array(dtype=wp.vec3), z: wp.array(dtype=wp.quat)
2121
+ ):
2122
+ tid = wp.tid()
2123
+
2124
+ a = x[tid]
2125
+ p = a.p
2126
+ q = a.q
2127
+
2128
+ y[tid] = p
2129
+ z[tid] = q
2130
+
2131
+
2132
+ def test_transform_extract(test, device):
2133
+ x = wp.ones(1, dtype=wp.transform, requires_grad=True, device=device)
2134
+ y = wp.zeros(1, dtype=float, requires_grad=True, device=device)
2135
+
2136
+ tape = wp.Tape()
2137
+ with tape:
2138
+ wp.launch(transform_extract_subscript, 1, inputs=[x], outputs=[y], device=device)
2139
+
2140
+ y.grad = wp.ones_like(y)
2141
+
2142
+ tape.backward()
2143
+
2144
+ assert_np_equal(y.numpy(), np.array([28.0], dtype=float))
2145
+ assert_np_equal(x.grad.numpy(), np.array([[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0]], dtype=float))
2146
+
2147
+ x = wp.ones(1, dtype=wp.transform, requires_grad=True, device=device)
2148
+ y = wp.zeros(1, dtype=wp.vec3, requires_grad=True, device=device)
2149
+ z = wp.zeros(1, dtype=wp.quat, requires_grad=True, device=device)
2150
+
2151
+ tape = wp.Tape()
2152
+ with tape:
2153
+ wp.launch(transform_extract_attribute, 1, inputs=[x], outputs=[y, z], device=device)
2154
+
2155
+ y.grad = wp.ones_like(y)
2156
+ z.grad = wp.ones_like(z)
2157
+
2158
+ tape.backward()
2159
+
2160
+ assert_np_equal(y.numpy(), np.array([[1.0, 1.0, 1.0]], dtype=float))
2161
+ assert_np_equal(z.numpy(), np.array([[1.0, 1.0, 1.0, 1.0]], dtype=float))
2162
+ assert_np_equal(x.grad.numpy(), np.array([[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]], dtype=float))
2163
+
2164
+
2165
+ @wp.kernel
2166
+ def transform_assign_subscript(x: wp.array(dtype=float), y: wp.array(dtype=wp.transform)):
2167
+ i = wp.tid()
2168
+
2169
+ a = wp.transform()
2170
+ a[0] = 1.0 * x[i]
2171
+ a[1] = 2.0 * x[i]
2172
+ a[2] = 3.0 * x[i]
2173
+ a[3] = 4.0 * x[i]
2174
+ a[4] = 5.0 * x[i]
2175
+ a[5] = 6.0 * x[i]
2176
+ a[6] = 7.0 * x[i]
2177
+ y[i] = a
2178
+
2179
+
2180
+ @wp.kernel
2181
+ def transform_assign_attribute(x: wp.array(dtype=wp.vec3), y: wp.array(dtype=wp.quat), z: wp.array(dtype=wp.transform)):
2182
+ i = wp.tid()
2183
+
2184
+ a = wp.transform()
2185
+ a.p = x[i]
2186
+ a.q = y[i]
2187
+ z[i] = a
2188
+
2189
+
2190
+ def test_transform_assign(test, device):
2191
+ x = wp.ones(1, dtype=float, requires_grad=True, device=device)
2192
+ y = wp.zeros(1, dtype=wp.transform, requires_grad=True, device=device)
2193
+
2194
+ tape = wp.Tape()
2195
+ with tape:
2196
+ wp.launch(transform_assign_subscript, 1, inputs=[x], outputs=[y], device=device)
2197
+
2198
+ y.grad = wp.ones_like(y)
2199
+ tape.backward()
2200
+
2201
+ assert_np_equal(y.numpy(), np.array([[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0]], dtype=float))
2202
+ assert_np_equal(x.grad.numpy(), np.array([28.0], dtype=float))
2203
+
2204
+ x = wp.ones(1, dtype=wp.vec3, requires_grad=True, device=device)
2205
+ y = wp.ones(1, dtype=wp.quat, requires_grad=True, device=device)
2206
+ z = wp.zeros(1, dtype=wp.transform, requires_grad=True, device=device)
2207
+
2208
+ tape = wp.Tape()
2209
+ with tape:
2210
+ wp.launch(transform_assign_attribute, 1, inputs=[x, y], outputs=[z], device=device)
2211
+
2212
+ z.grad = wp.ones_like(z)
2213
+ tape.backward()
2214
+
2215
+ assert_np_equal(z.numpy(), np.array([[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]], dtype=float))
2216
+ assert_np_equal(x.grad.numpy(), np.array([[1.0, 1.0, 1.0]], dtype=float))
2217
+ assert_np_equal(y.grad.numpy(), np.array([[1.0, 1.0, 1.0, 1.0]], dtype=float))
2218
+
2219
+
2220
+ def test_transform_assign_copy(test, device):
2221
+ saved_enable_vector_component_overwrites_setting = wp.config.enable_vector_component_overwrites
2222
+ try:
2223
+ wp.config.enable_vector_component_overwrites = True
2224
+
2225
+ @wp.kernel
2226
+ def transform_assign_overwrite(x: wp.array(dtype=wp.transform), y: wp.array(dtype=wp.transform)):
2227
+ tid = wp.tid()
2228
+
2229
+ a = wp.transform()
2230
+ b = x[tid]
2231
+ a = b
2232
+ a[1] = 3.0
2233
+
2234
+ y[tid] = a
2235
+
2236
+ x = wp.ones(1, dtype=wp.transform, device=device, requires_grad=True)
2237
+ y = wp.zeros(1, dtype=wp.transform, device=device, requires_grad=True)
2238
+
2239
+ tape = wp.Tape()
2240
+ with tape:
2241
+ wp.launch(transform_assign_overwrite, dim=1, inputs=[x, y], device=device)
2242
+
2243
+ y.grad = wp.ones_like(y, requires_grad=False)
2244
+ tape.backward()
2245
+
2246
+ assert_np_equal(y.numpy(), np.array([[1.0, 3.0, 1.0, 1.0, 1.0, 1.0, 1.0]], dtype=float))
2247
+ assert_np_equal(x.grad.numpy(), np.array([[1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0]], dtype=float))
2248
+
2249
+ finally:
2250
+ wp.config.enable_vector_component_overwrites = saved_enable_vector_component_overwrites_setting
2251
+
2252
+
2253
+ @wp.kernel
2254
+ def transform_array_extract_subscript(x: wp.array2d(dtype=wp.transform), y: wp.array2d(dtype=float)):
2255
+ i, j = wp.tid()
2256
+ a = x[i, j][0]
2257
+ b = x[i, j][1]
2258
+ c = x[i, j][2]
2259
+ d = x[i, j][3]
2260
+ e = x[i, j][4]
2261
+ f = x[i, j][5]
2262
+ g = x[i, j][6]
2263
+ y[i, j] = 1.0 * a + 2.0 * b + 3.0 * c + 4.0 * d + 5.0 * e + 6.0 * f + 7.0 * g
2264
+
2265
+
2266
+ @wp.kernel
2267
+ def transform_array_extract_attribute(
2268
+ x: wp.array2d(dtype=wp.transform), y: wp.array2d(dtype=wp.vec3), z: wp.array2d(dtype=wp.quat)
2269
+ ):
2270
+ i, j = wp.tid()
2271
+ a = x[i, j].p
2272
+ b = x[i, j].q
2273
+ y[i, j] = a
2274
+ z[i, j] = b
2275
+
2276
+
2277
+ def test_transform_array_extract(test, device):
2278
+ x = wp.ones((1, 1), dtype=wp.transform, requires_grad=True, device=device)
2279
+ y = wp.zeros((1, 1), dtype=float, requires_grad=True, device=device)
2280
+
2281
+ tape = wp.Tape()
2282
+ with tape:
2283
+ wp.launch(transform_array_extract_subscript, (1, 1), inputs=[x], outputs=[y], device=device)
2284
+
2285
+ y.grad = wp.ones_like(y)
2286
+ tape.backward()
2287
+
2288
+ assert_np_equal(y.numpy(), np.array([[28.0]], dtype=float))
2289
+ assert_np_equal(x.grad.numpy(), np.array([[[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0]]], dtype=float))
2290
+
2291
+ x = wp.ones((1, 1), dtype=wp.transform, requires_grad=True, device=device)
2292
+ y = wp.zeros((1, 1), dtype=wp.vec3, requires_grad=True, device=device)
2293
+ z = wp.zeros((1, 1), dtype=wp.quat, requires_grad=True, device=device)
2294
+
2295
+ tape = wp.Tape()
2296
+ with tape:
2297
+ wp.launch(transform_array_extract_attribute, (1, 1), inputs=[x], outputs=[y, z], device=device)
2298
+
2299
+ y.grad = wp.ones_like(y)
2300
+ z.grad = wp.ones_like(z)
2301
+ tape.backward()
2302
+
2303
+ assert_np_equal(y.numpy(), np.array([[[1.0, 1.0, 1.0]]], dtype=float))
2304
+ assert_np_equal(z.numpy(), np.array([[[1.0, 1.0, 1.0, 1.0]]], dtype=float))
2305
+ assert_np_equal(x.grad.numpy(), np.array([[[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]]], dtype=float))
2306
+
2307
+
2308
+ @wp.kernel
2309
+ def transform_array_assign_subscript(x: wp.array2d(dtype=float), y: wp.array2d(dtype=wp.transform)):
2310
+ i, j = wp.tid()
2311
+
2312
+ y[i, j][0] = 1.0 * x[i, j]
2313
+ y[i, j][1] = 2.0 * x[i, j]
2314
+ y[i, j][2] = 3.0 * x[i, j]
2315
+ y[i, j][3] = 4.0 * x[i, j]
2316
+ y[i, j][4] = 5.0 * x[i, j]
2317
+ y[i, j][5] = 6.0 * x[i, j]
2318
+ y[i, j][6] = 7.0 * x[i, j]
2319
+
2320
+
2321
+ # @wp.kernel
2322
+ # def transform_array_assign_attribute(x: wp.array2d(dtype=wp.vec3), y: wp.array2d(dtype=wp.quat), z: wp.array2d(dtype=wp.transform)):
2323
+ # i, j = wp.tid()
2324
+
2325
+ # z[i, j].p = x[i, j]
2326
+ # z[i, j].q = y[i, j]
2327
+
2328
+
2329
+ def test_transform_array_assign(test, device):
2330
+ x = wp.ones((1, 1), dtype=float, requires_grad=True, device=device)
2331
+ y = wp.zeros((1, 1), dtype=wp.transform, requires_grad=True, device=device)
2332
+
2333
+ tape = wp.Tape()
2334
+ with tape:
2335
+ wp.launch(transform_array_assign_subscript, (1, 1), inputs=[x], outputs=[y], device=device)
2336
+
2337
+ assert_np_equal(y.numpy(), np.array([[[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0]]], dtype=float))
2338
+ # TODO: gradient propagation for in-place array assignment
2339
+
2340
+ x = wp.ones((1, 1), dtype=wp.vec3, requires_grad=True, device=device)
2341
+ y = wp.ones((1, 1), dtype=wp.quat, requires_grad=True, device=device)
2342
+ z = wp.zeros((1, 1), dtype=wp.transform, requires_grad=True, device=device)
2343
+
2344
+ # TODO: transform_array_assign_attribute
2345
+ # tape = wp.Tape()
2346
+ # with tape:
2347
+ # wp.launch(transform_array_assign_attribute, (1, 1), inputs=[x, y], outputs=[z], device=device)
2348
+
2349
+ # assert_np_equal(z.numpy(), np.array([[[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]]], dtype=float))
2350
+ # TODO: gradient propagation for in-place array assignment
2351
+
2352
+
2353
+ @wp.kernel
2354
+ def transform_add_inplace_subscript(x: wp.array(dtype=wp.transform), y: wp.array(dtype=wp.transform)):
2355
+ i = wp.tid()
2356
+
2357
+ a = wp.transform()
2358
+ b = x[i]
2359
+
2360
+ a[0] += 1.0 * b[0]
2361
+ a[1] += 2.0 * b[1]
2362
+ a[2] += 3.0 * b[2]
2363
+ a[3] += 4.0 * b[3]
2364
+ a[4] += 5.0 * b[4]
2365
+ a[5] += 6.0 * b[5]
2366
+ a[6] += 7.0 * b[6]
2367
+
2368
+ y[i] = a
2369
+
2370
+
2371
+ @wp.kernel
2372
+ def transform_add_inplace_attribute(x: wp.array(dtype=wp.transform), y: wp.array(dtype=wp.transform)):
2373
+ i = wp.tid()
2374
+
2375
+ a = wp.transform()
2376
+ b = x[i]
2377
+
2378
+ a.p += b.p
2379
+
2380
+ y[i] = a
2381
+
2382
+
2383
+ def test_transform_add_inplace(test, device):
2384
+ x = wp.ones(1, dtype=wp.transform, requires_grad=True, device=device)
2385
+ y = wp.zeros(1, dtype=wp.transform, requires_grad=True, device=device)
2386
+
2387
+ tape = wp.Tape()
2388
+ with tape:
2389
+ wp.launch(transform_add_inplace_subscript, 1, inputs=[x], outputs=[y], device=device)
2390
+
2391
+ y.grad = wp.ones_like(y)
2392
+ tape.backward()
2393
+
2394
+ assert_np_equal(y.numpy(), np.array([[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0]], dtype=float))
2395
+ assert_np_equal(x.grad.numpy(), np.array([[1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0]], dtype=float))
2396
+
2397
+ x = wp.ones(1, dtype=wp.transform, requires_grad=True, device=device)
2398
+ y = wp.zeros(1, dtype=wp.transform, requires_grad=True, device=device)
2399
+
2400
+ tape = wp.Tape()
2401
+ with tape:
2402
+ wp.launch(transform_add_inplace_attribute, 1, inputs=[x], outputs=[y], device=device)
2403
+
2404
+ y.grad = wp.ones_like(y)
2405
+ tape.backward()
2406
+
2407
+ assert_np_equal(y.numpy(), np.array([[1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0]], dtype=float))
2408
+ assert_np_equal(x.grad.numpy(), np.array([[1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0]], dtype=float))
2409
+
2410
+
2411
+ @wp.kernel
2412
+ def transform_sub_inplace_subscript(x: wp.array(dtype=wp.transform), y: wp.array(dtype=wp.transform)):
2413
+ i = wp.tid()
2414
+
2415
+ a = wp.transform()
2416
+ b = x[i]
2417
+
2418
+ a[0] -= 1.0 * b[0]
2419
+ a[1] -= 2.0 * b[1]
2420
+ a[2] -= 3.0 * b[2]
2421
+ a[3] -= 4.0 * b[3]
2422
+ a[4] -= 5.0 * b[4]
2423
+ a[5] -= 6.0 * b[5]
2424
+ a[6] -= 7.0 * b[6]
2425
+
2426
+ y[i] = a
2427
+
2428
+
2429
+ @wp.kernel
2430
+ def transform_sub_inplace_attribute(x: wp.array(dtype=wp.transform), y: wp.array(dtype=wp.transform)):
2431
+ i = wp.tid()
2432
+
2433
+ a = wp.transform()
2434
+ b = x[i]
2435
+
2436
+ a.p -= b.p
2437
+
2438
+ y[i] = a
2439
+
2440
+
2441
+ def test_transform_sub_inplace(test, device):
2442
+ x = wp.ones(1, dtype=wp.transform, requires_grad=True, device=device)
2443
+ y = wp.zeros(1, dtype=wp.transform, requires_grad=True, device=device)
2444
+
2445
+ tape = wp.Tape()
2446
+ with tape:
2447
+ wp.launch(transform_sub_inplace_subscript, 1, inputs=[x], outputs=[y], device=device)
2448
+
2449
+ y.grad = wp.ones_like(y)
2450
+ tape.backward()
2451
+
2452
+ assert_np_equal(y.numpy(), np.array([[-1.0, -2.0, -3.0, -4.0, -5.0, -6.0, -7.0]], dtype=float))
2453
+ assert_np_equal(x.grad.numpy(), np.array([[-1.0, -2.0, -3.0, -4.0, -5.0, -6.0, -7.0]], dtype=float))
2454
+
2455
+ x = wp.ones(1, dtype=wp.transform, requires_grad=True, device=device)
2456
+ y = wp.zeros(1, dtype=wp.transform, requires_grad=True, device=device)
2457
+
2458
+ tape = wp.Tape()
2459
+ with tape:
2460
+ wp.launch(transform_sub_inplace_attribute, 1, inputs=[x], outputs=[y], device=device)
2461
+
2462
+ y.grad = wp.ones_like(y)
2463
+ tape.backward()
2464
+
2465
+ assert_np_equal(y.numpy(), np.array([[-1.0, -1.0, -1.0, 0.0, 0.0, 0.0, 0.0]], dtype=float))
2466
+ assert_np_equal(x.grad.numpy(), np.array([[-1.0, -1.0, -1.0, 0.0, 0.0, 0.0, 0.0]], dtype=float))
2467
+
2468
+
2469
+ @wp.kernel
2470
+ def transform_array_add_inplace(x: wp.array(dtype=wp.transform), y: wp.array(dtype=wp.transform)):
2471
+ i = wp.tid()
2472
+
2473
+ y[i] += x[i]
2474
+
2475
+
2476
+ def test_transform_array_add_inplace(test, device):
2477
+ x = wp.ones(1, dtype=wp.transform, requires_grad=True, device=device)
2478
+ y = wp.zeros(1, dtype=wp.transform, requires_grad=True, device=device)
2479
+
2480
+ tape = wp.Tape()
2481
+ with tape:
2482
+ wp.launch(transform_array_add_inplace, 1, inputs=[x], outputs=[y], device=device)
2483
+
2484
+ y.grad = wp.ones_like(y)
2485
+ tape.backward()
2486
+
2487
+ assert_np_equal(y.numpy(), np.array([[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]], dtype=float))
2488
+ assert_np_equal(x.grad.numpy(), np.array([[1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0]], dtype=float))
2489
+
2490
+
2491
+ @wp.kernel
2492
+ def transform_array_sub_inplace(x: wp.array(dtype=wp.transform), y: wp.array(dtype=wp.transform)):
2493
+ i = wp.tid()
2494
+
2495
+ y[i] -= x[i]
2496
+
2497
+
2498
+ def test_transform_array_sub_inplace(test, device):
2499
+ x = wp.ones(1, dtype=wp.transform, requires_grad=True, device=device)
2500
+ y = wp.zeros(1, dtype=wp.transform, requires_grad=True, device=device)
2501
+
2502
+ tape = wp.Tape()
2503
+ with tape:
2504
+ wp.launch(transform_array_sub_inplace, 1, inputs=[x], outputs=[y], device=device)
2505
+
2506
+ y.grad = wp.ones_like(y)
2507
+ tape.backward()
2508
+
2509
+ assert_np_equal(y.numpy(), np.array([[-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0]], dtype=float))
2510
+ assert_np_equal(x.grad.numpy(), np.array([[-1.0, -1.0, -1.0, -1.0, -1.0, -1.0, -1.0]], dtype=float))
2511
+
2512
+
2033
2513
  devices = get_test_devices()
2034
2514
 
2035
2515
 
@@ -2220,9 +2700,35 @@ for dtype in np_float_types:
2220
2700
  devices=devices,
2221
2701
  dtype=dtype,
2222
2702
  )
2223
-
2703
+ add_function_test_register_kernel(
2704
+ TestSpatial,
2705
+ f"test_transform_compose_{dtype.__name__}",
2706
+ test_transform_compose,
2707
+ devices=devices,
2708
+ dtype=dtype,
2709
+ )
2710
+ add_function_test_register_kernel(
2711
+ TestSpatial,
2712
+ f"test_transform_decompose_{dtype.__name__}",
2713
+ test_transform_decompose,
2714
+ devices=devices,
2715
+ dtype=dtype,
2716
+ )
2224
2717
  # \TODO: test spatial_mass and spatial_jacobian
2225
2718
 
2719
+ add_function_test(
2720
+ TestSpatial, "test_transform_getter_setter", test_transform_getter_setter, devices=wp.get_device("cpu")
2721
+ )
2722
+ add_function_test(TestSpatial, "test_transform_extract", test_transform_extract, devices=devices)
2723
+ add_function_test(TestSpatial, "test_transform_assign", test_transform_assign, devices=devices)
2724
+ add_function_test(TestSpatial, "test_transform_assign_copy", test_transform_assign_copy, devices=devices)
2725
+ add_function_test(TestSpatial, "test_transform_array_extract", test_transform_array_extract, devices=devices)
2726
+ add_function_test(TestSpatial, "test_transform_array_assign", test_transform_array_assign, devices=devices)
2727
+ add_function_test(TestSpatial, "test_transform_add_inplace", test_transform_add_inplace, devices=devices)
2728
+ add_function_test(TestSpatial, "test_transform_sub_inplace", test_transform_sub_inplace, devices=devices)
2729
+ add_function_test(TestSpatial, "test_transform_array_add_inplace", test_transform_array_add_inplace, devices=devices)
2730
+ add_function_test(TestSpatial, "test_transform_array_sub_inplace", test_transform_array_sub_inplace, devices=devices)
2731
+
2226
2732
 
2227
2733
  if __name__ == "__main__":
2228
2734
  wp.clear_kernel_cache()
warp/tests/test_static.py CHANGED
@@ -559,6 +559,54 @@ def test_static_len_query(test, _):
559
559
  wp.launch(static_len_query_kernel, 1, inputs=(v1,))
560
560
 
561
561
 
562
+ @wp.func
563
+ def func_1() -> int:
564
+ return 1
565
+
566
+
567
+ @wp.func
568
+ def func_2() -> int:
569
+ return 2
570
+
571
+
572
+ funcs = [func_1, func_2]
573
+
574
+
575
+ def unresolved_builder(funcids):
576
+ _funcs = [funcs[id] for id in funcids]
577
+
578
+ @wp.kernel
579
+ def eval(input: wp.array(dtype=int), output: wp.array(dtype=int)):
580
+ for i in range(wp.static(len(_funcs))):
581
+ output[0] = wp.static(_funcs[i])()
582
+
583
+ return eval
584
+
585
+
586
+ def test_unresolved_static_expression(test, device):
587
+ # The module hash will need to be updated from the static expressions
588
+ # resolved at code generation time, since some of them cannot be evaluated
589
+ # at declaration time.
590
+ with wp.ScopedDevice(device):
591
+ output1 = wp.array((1,), dtype=int)
592
+ wp.launch(
593
+ unresolved_builder([0]),
594
+ dim=(1,),
595
+ inputs=[wp.array(np.array([0]), dtype=int)],
596
+ outputs=[output1],
597
+ )
598
+ test.assertEqual(output1.numpy()[0], 1)
599
+
600
+ output2 = wp.array((1,), dtype=int)
601
+ wp.launch(
602
+ unresolved_builder([1]),
603
+ dim=(1,),
604
+ inputs=[wp.array(np.array([1]), dtype=int)],
605
+ outputs=[output2],
606
+ )
607
+ test.assertEqual(output2.numpy()[0], 2)
608
+
609
+
562
610
  devices = get_test_devices()
563
611
 
564
612
 
warp/tests/test_struct.py CHANGED
@@ -768,8 +768,8 @@ class TestStruct(unittest.TestCase):
768
768
  v.value[2] = 3.0
769
769
 
770
770
  arr = wp.array([v], dtype=VecStruct)
771
- expected = np.array(([1.0, 2.0, 3.0],))
772
- assert np.all(arr.numpy().tolist() == expected)
771
+ expected = np.array([[[1.0, 2.0, 3.0]]])
772
+ np.testing.assert_equal(arr.numpy().tolist(), expected)
773
773
 
774
774
 
775
775
  add_function_test(TestStruct, "test_step", test_step, devices=devices)
warp/tests/test_tape.py CHANGED
@@ -157,6 +157,43 @@ def test_tape_zero_multiple_outputs(test, device):
157
157
  assert_np_equal(x.grad.numpy(), np.ones(3, dtype=float))
158
158
 
159
159
 
160
+ @wp.struct
161
+ class NestedStruct:
162
+ arr: wp.array(dtype=float)
163
+
164
+
165
+ @wp.struct
166
+ class WrapperStruct:
167
+ nested: NestedStruct
168
+
169
+
170
+ @wp.kernel
171
+ def nested_loss_kernel(wrapper: WrapperStruct, loss: wp.array(dtype=float)):
172
+ i = wp.tid()
173
+ wp.atomic_add(loss, 0, wrapper.nested.arr[i])
174
+
175
+
176
+ def test_tape_nested_struct(test, device):
177
+ wrapper = WrapperStruct()
178
+ wrapper.nested = NestedStruct()
179
+ wrapper.nested.arr = wp.ones(shape=(1,), dtype=float, requires_grad=True, device=device)
180
+
181
+ loss = wp.zeros(shape=(1,), dtype=float, requires_grad=True, device=device)
182
+
183
+ tape = wp.Tape()
184
+ with tape:
185
+ wp.launch(nested_loss_kernel, dim=1, inputs=(wrapper, loss), device=device)
186
+
187
+ assert_np_equal(loss.numpy(), [1.0])
188
+
189
+ tape.backward(loss)
190
+ assert_np_equal(wrapper.nested.arr.grad.numpy(), [1.0])
191
+
192
+ tape.zero()
193
+
194
+ assert_np_equal(wrapper.nested.arr.grad.numpy(), [0.0])
195
+
196
+
160
197
  def test_tape_visualize(test, device):
161
198
  dim = 8
162
199
  tape = wp.Tape()
@@ -196,6 +233,7 @@ add_function_test(TestTape, "test_tape_mul_constant", test_tape_mul_constant, de
196
233
  add_function_test(TestTape, "test_tape_mul_variable", test_tape_mul_variable, devices=devices)
197
234
  add_function_test(TestTape, "test_tape_dot_product", test_tape_dot_product, devices=devices)
198
235
  add_function_test(TestTape, "test_tape_zero_multiple_outputs", test_tape_zero_multiple_outputs, devices=devices)
236
+ add_function_test(TestTape, "test_tape_nested_struct", test_tape_nested_struct, devices=devices)
199
237
  add_function_test(TestTape, "test_tape_visualize", test_tape_visualize, devices=devices)
200
238
 
201
239