warp-lang 1.0.0b5__py3-none-manylinux2014_x86_64.whl → 1.0.0b6__py3-none-manylinux2014_x86_64.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.
Files changed (187) hide show
  1. docs/conf.py +3 -4
  2. examples/env/env_ant.py +1 -1
  3. examples/env/env_cartpole.py +1 -1
  4. examples/env/env_humanoid.py +1 -1
  5. examples/example_dem.py +28 -26
  6. examples/example_diffray.py +37 -30
  7. examples/example_fluid.py +7 -3
  8. examples/example_jacobian_ik.py +1 -1
  9. examples/example_mesh_intersect.py +10 -7
  10. examples/example_nvdb.py +3 -3
  11. examples/example_render_opengl.py +19 -10
  12. examples/example_sim_cartpole.py +9 -5
  13. examples/example_sim_cloth.py +29 -25
  14. examples/example_sim_fk_grad.py +2 -2
  15. examples/example_sim_fk_grad_torch.py +3 -3
  16. examples/example_sim_grad_bounce.py +11 -8
  17. examples/example_sim_grad_cloth.py +12 -9
  18. examples/example_sim_granular.py +2 -2
  19. examples/example_sim_granular_collision_sdf.py +13 -13
  20. examples/example_sim_neo_hookean.py +3 -3
  21. examples/example_sim_particle_chain.py +2 -2
  22. examples/example_sim_quadruped.py +8 -5
  23. examples/example_sim_rigid_chain.py +8 -5
  24. examples/example_sim_rigid_contact.py +13 -10
  25. examples/example_sim_rigid_fem.py +2 -2
  26. examples/example_sim_rigid_gyroscopic.py +2 -2
  27. examples/example_sim_rigid_kinematics.py +1 -1
  28. examples/example_sim_trajopt.py +3 -2
  29. examples/fem/example_apic_fluid.py +5 -7
  30. examples/fem/example_diffusion_mgpu.py +18 -16
  31. warp/__init__.py +3 -2
  32. warp/bin/warp.so +0 -0
  33. warp/build_dll.py +29 -9
  34. warp/builtins.py +206 -7
  35. warp/codegen.py +58 -38
  36. warp/config.py +3 -1
  37. warp/context.py +234 -128
  38. warp/fem/__init__.py +2 -2
  39. warp/fem/cache.py +2 -1
  40. warp/fem/field/nodal_field.py +18 -17
  41. warp/fem/geometry/hexmesh.py +11 -6
  42. warp/fem/geometry/quadmesh_2d.py +16 -12
  43. warp/fem/geometry/tetmesh.py +19 -8
  44. warp/fem/geometry/trimesh_2d.py +18 -7
  45. warp/fem/integrate.py +341 -196
  46. warp/fem/quadrature/__init__.py +1 -1
  47. warp/fem/quadrature/pic_quadrature.py +138 -53
  48. warp/fem/quadrature/quadrature.py +81 -9
  49. warp/fem/space/__init__.py +1 -1
  50. warp/fem/space/basis_space.py +169 -51
  51. warp/fem/space/grid_2d_function_space.py +2 -2
  52. warp/fem/space/grid_3d_function_space.py +2 -2
  53. warp/fem/space/hexmesh_function_space.py +2 -2
  54. warp/fem/space/partition.py +9 -6
  55. warp/fem/space/quadmesh_2d_function_space.py +2 -2
  56. warp/fem/space/shape/cube_shape_function.py +27 -15
  57. warp/fem/space/shape/square_shape_function.py +29 -18
  58. warp/fem/space/tetmesh_function_space.py +2 -2
  59. warp/fem/space/topology.py +10 -0
  60. warp/fem/space/trimesh_2d_function_space.py +2 -2
  61. warp/fem/utils.py +10 -5
  62. warp/native/array.h +49 -8
  63. warp/native/builtin.h +31 -14
  64. warp/native/cuda_util.cpp +8 -3
  65. warp/native/cuda_util.h +1 -0
  66. warp/native/exports.h +1177 -1108
  67. warp/native/intersect.h +4 -4
  68. warp/native/intersect_adj.h +8 -8
  69. warp/native/mat.h +65 -6
  70. warp/native/mesh.h +126 -5
  71. warp/native/quat.h +28 -4
  72. warp/native/vec.h +76 -14
  73. warp/native/warp.cu +1 -6
  74. warp/render/render_opengl.py +261 -109
  75. warp/sim/import_mjcf.py +13 -7
  76. warp/sim/import_urdf.py +14 -14
  77. warp/sim/inertia.py +17 -18
  78. warp/sim/model.py +67 -67
  79. warp/sim/render.py +1 -1
  80. warp/sparse.py +6 -6
  81. warp/stubs.py +19 -81
  82. warp/tape.py +1 -1
  83. warp/tests/__main__.py +3 -6
  84. warp/tests/{test_class_kernel.py → aux_test_class_kernel.py} +9 -1
  85. warp/tests/aux_test_conditional_unequal_types_kernels.py +21 -0
  86. warp/tests/{test_dependent.py → aux_test_dependent.py} +2 -2
  87. warp/tests/{test_reference.py → aux_test_reference.py} +1 -1
  88. warp/tests/aux_test_unresolved_func.py +14 -0
  89. warp/tests/aux_test_unresolved_symbol.py +14 -0
  90. warp/tests/{test_kinematics.py → disabled_kinematics.py} +10 -12
  91. warp/tests/run_coverage_serial.py +31 -0
  92. warp/tests/test_adam.py +102 -106
  93. warp/tests/test_arithmetic.py +39 -40
  94. warp/tests/test_array.py +46 -48
  95. warp/tests/test_array_reduce.py +25 -19
  96. warp/tests/test_atomic.py +62 -26
  97. warp/tests/test_bool.py +16 -11
  98. warp/tests/test_builtins_resolution.py +1292 -0
  99. warp/tests/test_bvh.py +9 -12
  100. warp/tests/test_closest_point_edge_edge.py +53 -57
  101. warp/tests/test_codegen.py +164 -134
  102. warp/tests/test_compile_consts.py +13 -19
  103. warp/tests/test_conditional.py +30 -32
  104. warp/tests/test_copy.py +9 -12
  105. warp/tests/test_ctypes.py +90 -98
  106. warp/tests/test_dense.py +20 -14
  107. warp/tests/test_devices.py +34 -35
  108. warp/tests/test_dlpack.py +74 -75
  109. warp/tests/test_examples.py +215 -97
  110. warp/tests/test_fabricarray.py +15 -21
  111. warp/tests/test_fast_math.py +14 -11
  112. warp/tests/test_fem.py +280 -97
  113. warp/tests/test_fp16.py +19 -15
  114. warp/tests/test_func.py +177 -194
  115. warp/tests/test_generics.py +71 -77
  116. warp/tests/test_grad.py +83 -32
  117. warp/tests/test_grad_customs.py +7 -9
  118. warp/tests/test_hash_grid.py +6 -10
  119. warp/tests/test_import.py +9 -23
  120. warp/tests/test_indexedarray.py +19 -21
  121. warp/tests/test_intersect.py +15 -9
  122. warp/tests/test_large.py +17 -19
  123. warp/tests/test_launch.py +14 -17
  124. warp/tests/test_lerp.py +63 -63
  125. warp/tests/test_lvalue.py +84 -35
  126. warp/tests/test_marching_cubes.py +9 -13
  127. warp/tests/test_mat.py +388 -3004
  128. warp/tests/test_mat_lite.py +9 -12
  129. warp/tests/test_mat_scalar_ops.py +2889 -0
  130. warp/tests/test_math.py +10 -11
  131. warp/tests/test_matmul.py +104 -100
  132. warp/tests/test_matmul_lite.py +72 -98
  133. warp/tests/test_mesh.py +35 -32
  134. warp/tests/test_mesh_query_aabb.py +18 -25
  135. warp/tests/test_mesh_query_point.py +39 -23
  136. warp/tests/test_mesh_query_ray.py +9 -21
  137. warp/tests/test_mlp.py +8 -9
  138. warp/tests/test_model.py +89 -93
  139. warp/tests/test_modules_lite.py +15 -25
  140. warp/tests/test_multigpu.py +87 -114
  141. warp/tests/test_noise.py +10 -12
  142. warp/tests/test_operators.py +14 -21
  143. warp/tests/test_options.py +10 -11
  144. warp/tests/test_pinned.py +16 -18
  145. warp/tests/test_print.py +16 -20
  146. warp/tests/test_quat.py +121 -88
  147. warp/tests/test_rand.py +12 -13
  148. warp/tests/test_reload.py +27 -32
  149. warp/tests/test_rounding.py +7 -10
  150. warp/tests/test_runlength_encode.py +105 -106
  151. warp/tests/test_smoothstep.py +8 -9
  152. warp/tests/test_snippet.py +13 -22
  153. warp/tests/test_sparse.py +30 -29
  154. warp/tests/test_spatial.py +179 -174
  155. warp/tests/test_streams.py +100 -107
  156. warp/tests/test_struct.py +98 -67
  157. warp/tests/test_tape.py +11 -17
  158. warp/tests/test_torch.py +89 -86
  159. warp/tests/test_transient_module.py +9 -12
  160. warp/tests/test_types.py +328 -50
  161. warp/tests/test_utils.py +217 -218
  162. warp/tests/test_vec.py +133 -2133
  163. warp/tests/test_vec_lite.py +8 -11
  164. warp/tests/test_vec_scalar_ops.py +2099 -0
  165. warp/tests/test_volume.py +391 -382
  166. warp/tests/test_volume_write.py +122 -135
  167. warp/tests/unittest_serial.py +35 -0
  168. warp/tests/unittest_suites.py +291 -0
  169. warp/tests/{test_base.py → unittest_utils.py} +138 -25
  170. warp/tests/{test_misc.py → unused_test_misc.py} +13 -5
  171. warp/tests/{test_debug.py → walkthough_debug.py} +2 -15
  172. warp/thirdparty/unittest_parallel.py +257 -54
  173. warp/types.py +119 -98
  174. warp/utils.py +14 -0
  175. {warp_lang-1.0.0b5.dist-info → warp_lang-1.0.0b6.dist-info}/METADATA +2 -1
  176. {warp_lang-1.0.0b5.dist-info → warp_lang-1.0.0b6.dist-info}/RECORD +182 -178
  177. {warp_lang-1.0.0b5.dist-info → warp_lang-1.0.0b6.dist-info}/WHEEL +1 -1
  178. warp/tests/test_all.py +0 -239
  179. warp/tests/test_conditional_unequal_types_kernels.py +0 -14
  180. warp/tests/test_coverage.py +0 -38
  181. warp/tests/test_unresolved_func.py +0 -7
  182. warp/tests/test_unresolved_symbol.py +0 -7
  183. /warp/tests/{test_compile_consts_dummy.py → aux_test_compile_consts_dummy.py} +0 -0
  184. /warp/tests/{test_reference_reference.py → aux_test_reference_reference.py} +0 -0
  185. /warp/tests/{test_square.py → aux_test_square.py} +0 -0
  186. {warp_lang-1.0.0b5.dist-info → warp_lang-1.0.0b6.dist-info}/LICENSE.md +0 -0
  187. {warp_lang-1.0.0b5.dist-info → warp_lang-1.0.0b6.dist-info}/top_level.txt +0 -0
warp/tests/test_volume.py CHANGED
@@ -10,7 +10,7 @@ import unittest
10
10
  import numpy as np
11
11
 
12
12
  import warp as wp
13
- from warp.tests.test_base import *
13
+ from warp.tests.unittest_utils import *
14
14
 
15
15
  wp.init()
16
16
 
@@ -330,398 +330,407 @@ def test_volume_store_i(volume: wp.uint64, points: wp.array(dtype=wp.vec3), valu
330
330
  values[tid] = wp.volume_lookup_i(volume, i, j, k)
331
331
 
332
332
 
333
- def register(parent):
334
- devices = get_test_devices()
335
- rng = np.random.default_rng(101215)
336
-
337
- # Note about the test grids:
338
- # test_grid and test_int32_grid
339
- # active region: [-10,10]^3
340
- # values: v[i,j,k] = i * j * k
341
- # voxel size: 0.25
342
- #
343
- # test_vec_grid
344
- # active region: [-10,10]^3
345
- # values: v[i,j,k] = (i + 2*j + 3*k, 4*i + 5*j + 6*k, 7*i + 8*j + 9*k)
346
- # voxel size: 0.25
347
- #
348
- # torus
349
- # index to world transformation:
350
- # [0.1, 0, 0, 0]
351
- # [0, 0, 0.1, 0]
352
- # [0, 0.1, 0, 0]
353
- # [1, 2, 3, 1]
354
- # (-90 degrees rotation along X)
355
- # voxel size: 0.1
356
- volume_paths = {
357
- "float": os.path.abspath(os.path.join(os.path.dirname(__file__), "assets/test_grid.nvdb")),
358
- "int32": os.path.abspath(os.path.join(os.path.dirname(__file__), "assets/test_int32_grid.nvdb")),
359
- "vec3f": os.path.abspath(os.path.join(os.path.dirname(__file__), "assets/test_vec_grid.nvdb")),
360
- "torus": os.path.abspath(os.path.join(os.path.dirname(__file__), "assets/torus.nvdb")),
361
- "float_write": os.path.abspath(os.path.join(os.path.dirname(__file__), "assets/test_grid.nvdb")),
362
- }
363
-
364
- test_volume_tiles = (
365
- np.array([[i, j, k] for i in range(-2, 2) for j in range(-2, 2) for k in range(-2, 2)], dtype=np.int32) * 8
366
- )
333
+ devices = get_test_devices()
334
+ rng = np.random.default_rng(101215)
335
+
336
+ # Note about the test grids:
337
+ # test_grid and test_int32_grid
338
+ # active region: [-10,10]^3
339
+ # values: v[i,j,k] = i * j * k
340
+ # voxel size: 0.25
341
+ #
342
+ # test_vec_grid
343
+ # active region: [-10,10]^3
344
+ # values: v[i,j,k] = (i + 2*j + 3*k, 4*i + 5*j + 6*k, 7*i + 8*j + 9*k)
345
+ # voxel size: 0.25
346
+ #
347
+ # torus
348
+ # index to world transformation:
349
+ # [0.1, 0, 0, 0]
350
+ # [0, 0, 0.1, 0]
351
+ # [0, 0.1, 0, 0]
352
+ # [1, 2, 3, 1]
353
+ # (-90 degrees rotation along X)
354
+ # voxel size: 0.1
355
+ volume_paths = {
356
+ "float": os.path.abspath(os.path.join(os.path.dirname(__file__), "assets/test_grid.nvdb")),
357
+ "int32": os.path.abspath(os.path.join(os.path.dirname(__file__), "assets/test_int32_grid.nvdb")),
358
+ "vec3f": os.path.abspath(os.path.join(os.path.dirname(__file__), "assets/test_vec_grid.nvdb")),
359
+ "torus": os.path.abspath(os.path.join(os.path.dirname(__file__), "assets/torus.nvdb")),
360
+ "float_write": os.path.abspath(os.path.join(os.path.dirname(__file__), "assets/test_grid.nvdb")),
361
+ }
362
+
363
+ test_volume_tiles = (
364
+ np.array([[i, j, k] for i in range(-2, 2) for j in range(-2, 2) for k in range(-2, 2)], dtype=np.int32) * 8
365
+ )
366
+
367
+ volumes = {}
368
+ for value_type, path in volume_paths.items():
369
+ volumes[value_type] = {}
370
+ volume_data = open(path, "rb").read()
371
+ for device in devices:
372
+ try:
373
+ volume = wp.Volume.load_from_nvdb(volume_data, device)
374
+ except RuntimeError as e:
375
+ raise RuntimeError(f'Failed to load volume from "{path}" to {device} memory:\n{e}')
376
+
377
+ volumes[value_type][device.alias] = volume
378
+
379
+ axis = np.linspace(-1, 1, 3)
380
+ point_grid = np.array([[x, y, z] for x in axis for y in axis for z in axis], dtype=np.float32)
381
+
382
+
383
+ def test_volume_sample_linear_f_gradient(test, device):
384
+ points = rng.uniform(-10.0, 10.0, size=(100, 3))
385
+ values = wp.array(np.zeros(1), dtype=wp.float32, device=device, requires_grad=True)
386
+ for test_case in points:
387
+ uvws = wp.array(test_case, dtype=wp.vec3, device=device, requires_grad=True)
388
+ xyzs = wp.array(test_case * 0.25, dtype=wp.vec3, device=device, requires_grad=True)
389
+
390
+ tape = wp.Tape()
391
+ with tape:
392
+ wp.launch(
393
+ test_volume_sample_local_f_linear_values,
394
+ dim=1,
395
+ inputs=[volumes["float"][device.alias].id, uvws, values],
396
+ device=device,
397
+ )
398
+ tape.backward(values)
399
+
400
+ x, y, z = test_case
401
+ grad_expected = np.array([y * z, x * z, x * y])
402
+ grad_computed = tape.gradients[uvws].numpy()[0]
403
+ np.testing.assert_allclose(grad_computed, grad_expected, rtol=1e-4)
404
+
405
+ tape = wp.Tape()
406
+ with tape:
407
+ wp.launch(
408
+ test_volume_sample_world_f_linear_values,
409
+ dim=1,
410
+ inputs=[volumes["float"][device.alias].id, xyzs, values],
411
+ device=device,
412
+ )
413
+ tape.backward(values)
367
414
 
368
- volumes = {}
369
- points = {}
370
- points_jittered = {}
371
- for value_type, path in volume_paths.items():
372
- volumes[value_type] = {}
373
- volume_data = open(path, "rb").read()
374
- for device in devices:
375
- try:
376
- volume = wp.Volume.load_from_nvdb(volume_data, device)
377
- except RuntimeError as e:
378
- raise RuntimeError(f'Failed to load volume from "{path}" to {device} memory:\n{e}')
379
-
380
- volumes[value_type][device.alias] = volume
381
-
382
- axis = np.linspace(-1, 1, 3)
383
- point_grid = np.array([[x, y, z] for x in axis for y in axis for z in axis], dtype=np.float32)
384
-
385
- class TestVolumes(parent):
386
- def test_volume_sample_linear_f_gradient(self):
387
- for device in devices:
388
- points = rng.uniform(-10.0, 10.0, size=(100, 3))
389
- values = wp.array(np.zeros(1), dtype=wp.float32, device=device, requires_grad=True)
390
- for case in points:
391
- uvws = wp.array(case, dtype=wp.vec3, device=device, requires_grad=True)
392
- xyzs = wp.array(case * 0.25, dtype=wp.vec3, device=device, requires_grad=True)
393
-
394
- tape = wp.Tape()
395
- with tape:
396
- wp.launch(
397
- test_volume_sample_local_f_linear_values,
398
- dim=1,
399
- inputs=[volumes["float"][device.alias].id, uvws, values],
400
- device=device,
401
- )
402
- tape.backward(values)
403
-
404
- x, y, z = case
405
- grad_expected = np.array([y * z, x * z, x * y])
406
- grad_computed = tape.gradients[uvws].numpy()[0]
407
- np.testing.assert_allclose(grad_computed, grad_expected, rtol=1e-4)
408
-
409
- tape = wp.Tape()
410
- with tape:
411
- wp.launch(
412
- test_volume_sample_world_f_linear_values,
413
- dim=1,
414
- inputs=[volumes["float"][device.alias].id, xyzs, values],
415
- device=device,
416
- )
417
- tape.backward(values)
418
-
419
- x, y, z = case
420
- grad_expected = np.array([y * z, x * z, x * y]) / 0.25
421
- grad_computed = tape.gradients[xyzs].numpy()[0]
422
- np.testing.assert_allclose(grad_computed, grad_expected, rtol=1e-4)
423
-
424
- def test_volume_sample_grad_linear_f_gradient(self):
425
- for device in devices:
426
- points = rng.uniform(-10.0, 10.0, size=(100, 3))
427
- values = wp.array(np.zeros(1), dtype=wp.float32, device=device, requires_grad=True)
428
- for case in points:
429
- uvws = wp.array(case, dtype=wp.vec3, device=device, requires_grad=True)
430
- xyzs = wp.array(case * 0.25, dtype=wp.vec3, device=device, requires_grad=True)
431
-
432
- for case_num in range(4):
433
- tape = wp.Tape()
434
- with tape:
435
- wp.launch(
436
- test_volume_sample_grad_local_f_linear_values,
437
- dim=1,
438
- inputs=[volumes["float"][device.alias].id, uvws, values, case_num],
439
- device=device,
440
- )
441
- tape.backward(values)
442
-
443
- x, y, z = case
444
- grad_computed = tape.gradients[uvws].numpy()[0]
445
- if case_num == 0:
446
- grad_expected = np.array([y * z, x * z, x * y])
447
- elif case_num == 1:
448
- grad_expected = np.array([0.0, z, y])
449
- elif case_num == 2:
450
- grad_expected = np.array([z, 0.0, x])
451
- elif case_num == 3:
452
- grad_expected = np.array([y, x, 0.0])
453
-
454
- np.testing.assert_allclose(grad_computed, grad_expected, rtol=1e-4)
455
- tape.zero()
456
-
457
- for case_num in range(4):
458
- tape = wp.Tape()
459
- with tape:
460
- wp.launch(
461
- test_volume_sample_grad_world_f_linear_values,
462
- dim=1,
463
- inputs=[volumes["float"][device.alias].id, xyzs, values, case_num],
464
- device=device,
465
- )
466
- tape.backward(values)
467
-
468
- x, y, z = case
469
- grad_computed = tape.gradients[xyzs].numpy()[0]
470
- if case_num == 0:
471
- grad_expected = np.array([y * z, x * z, x * y]) / 0.25
472
- elif case_num == 1:
473
- grad_expected = np.array([0.0, z, y]) / 0.25
474
- elif case_num == 2:
475
- grad_expected = np.array([z, 0.0, x]) / 0.25
476
- elif case_num == 3:
477
- grad_expected = np.array([y, x, 0.0]) / 0.25
478
-
479
- np.testing.assert_allclose(grad_computed, grad_expected, rtol=1e-4)
480
- tape.zero()
481
-
482
- def test_volume_sample_linear_v_gradient(self):
483
- for device in devices:
484
- points = rng.uniform(-10.0, 10.0, size=(100, 3))
485
- values = wp.zeros(1, dtype=wp.float32, device=device, requires_grad=True)
486
- for case in points:
487
- uvws = wp.array(case, dtype=wp.vec3, device=device, requires_grad=True)
488
- xyzs = wp.array(case * 0.25, dtype=wp.vec3, device=device, requires_grad=True)
489
-
490
- tape = wp.Tape()
491
- with tape:
492
- wp.launch(
493
- test_volume_sample_local_v_linear_values,
494
- dim=1,
495
- inputs=[volumes["vec3f"][device.alias].id, uvws, values],
496
- device=device,
497
- )
498
- tape.backward(values)
499
-
500
- grad_expected = np.array([6.0, 15.0, 24.0])
501
- grad_computed = tape.gradients[uvws].numpy()[0]
502
- np.testing.assert_allclose(grad_computed, grad_expected, rtol=1e-4)
503
-
504
- tape = wp.Tape()
505
- with tape:
506
- wp.launch(
507
- test_volume_sample_world_v_linear_values,
508
- dim=1,
509
- inputs=[volumes["vec3f"][device.alias].id, xyzs, values],
510
- device=device,
511
- )
512
- tape.backward(values)
513
-
514
- grad_expected = np.array([6.0, 15.0, 24.0]) / 0.25
515
- grad_computed = tape.gradients[xyzs].numpy()[0]
516
- np.testing.assert_allclose(grad_computed, grad_expected, rtol=1e-4)
517
-
518
- def test_volume_transform_gradient(self):
519
- for device in devices:
520
- values = wp.zeros(1, dtype=wp.float32, device=device, requires_grad=True)
521
- grad_values = wp.zeros(1, dtype=wp.vec3, device=device)
522
- points = rng.uniform(-10.0, 10.0, size=(10, 3))
523
- for case in points:
524
- points = wp.array(case, dtype=wp.vec3, device=device, requires_grad=True)
525
- tape = wp.Tape()
526
- with tape:
527
- wp.launch(
528
- test_volume_index_to_world,
529
- dim=1,
530
- inputs=[volumes["torus"][device.alias].id, points, values, grad_values],
531
- device=device,
532
- )
533
- tape.backward(values)
534
-
535
- grad_computed = tape.gradients[points].numpy()
536
- grad_expected = grad_values.numpy()
537
- np.testing.assert_allclose(grad_computed, grad_expected, rtol=1e-4)
538
-
539
- grad_computed = tape.gradients[points].numpy()
540
- grad_expected = grad_values.numpy()
541
- np.testing.assert_allclose(grad_computed, grad_expected, rtol=1e-4)
542
-
543
- def test_volume_store(self):
544
- values_ref = np.array([x + 100 * y + 10000 * z for x, y, z in point_grid])
545
- for device in devices:
546
- points = wp.array(point_grid, dtype=wp.vec3, device=device)
547
- values = wp.empty(len(point_grid), dtype=wp.float32, device=device)
548
- wp.launch(
549
- test_volume_store_f,
550
- dim=len(point_grid),
551
- inputs=[volumes["float_write"][device.alias].id, points, values],
552
- device=device,
553
- )
415
+ x, y, z = test_case
416
+ grad_expected = np.array([y * z, x * z, x * y]) / 0.25
417
+ grad_computed = tape.gradients[xyzs].numpy()[0]
418
+ np.testing.assert_allclose(grad_computed, grad_expected, rtol=1e-4)
554
419
 
555
- values_res = values.numpy()
556
- np.testing.assert_equal(values_res, values_ref)
557
420
 
558
- def test_volume_allocation_f(self):
559
- bg_value = -123.0
560
- points_np = np.append(point_grid, [[8096, 8096, 8096]], axis=0)
561
- values_ref = np.append(np.array([x + 100 * y + 10000 * z for x, y, z in point_grid]), bg_value)
562
- for device in devices:
563
- if device.is_cpu:
564
- continue
421
+ def test_volume_sample_grad_linear_f_gradient(test, device):
422
+ points = rng.uniform(-10.0, 10.0, size=(100, 3))
423
+ values = wp.array(np.zeros(1), dtype=wp.float32, device=device, requires_grad=True)
424
+ for test_case in points:
425
+ uvws = wp.array(test_case, dtype=wp.vec3, device=device, requires_grad=True)
426
+ xyzs = wp.array(test_case * 0.25, dtype=wp.vec3, device=device, requires_grad=True)
565
427
 
566
- volume = wp.Volume.allocate(
567
- min=[-11, -11, -11], max=[11, 11, 11], voxel_size=0.1, bg_value=bg_value, device=device
428
+ for case_num in range(4):
429
+ tape = wp.Tape()
430
+ with tape:
431
+ wp.launch(
432
+ test_volume_sample_grad_local_f_linear_values,
433
+ dim=1,
434
+ inputs=[volumes["float"][device.alias].id, uvws, values, case_num],
435
+ device=device,
568
436
  )
569
- points = wp.array(points_np, dtype=wp.vec3, device=device)
570
- values = wp.empty(len(points_np), dtype=wp.float32, device=device)
571
- wp.launch(test_volume_store_f, dim=len(points_np), inputs=[volume.id, points, values], device=device)
572
-
573
- values_res = values.numpy()
574
- np.testing.assert_equal(values_res, values_ref)
575
-
576
- def test_volume_allocation_v(self):
577
- bg_value = (-1, 2.0, -3)
578
- points_np = np.append(point_grid, [[8096, 8096, 8096]], axis=0)
579
- values_ref = np.append(point_grid, [bg_value], axis=0)
580
- for device in devices:
581
- if device.is_cpu:
582
- continue
583
-
584
- volume = wp.Volume.allocate(
585
- min=[-11, -11, -11], max=[11, 11, 11], voxel_size=0.1, bg_value=bg_value, device=device
437
+ tape.backward(values)
438
+
439
+ x, y, z = test_case
440
+ grad_computed = tape.gradients[uvws].numpy()[0]
441
+ if case_num == 0:
442
+ grad_expected = np.array([y * z, x * z, x * y])
443
+ elif case_num == 1:
444
+ grad_expected = np.array([0.0, z, y])
445
+ elif case_num == 2:
446
+ grad_expected = np.array([z, 0.0, x])
447
+ elif case_num == 3:
448
+ grad_expected = np.array([y, x, 0.0])
449
+
450
+ np.testing.assert_allclose(grad_computed, grad_expected, rtol=1e-4)
451
+ tape.zero()
452
+
453
+ for case_num in range(4):
454
+ tape = wp.Tape()
455
+ with tape:
456
+ wp.launch(
457
+ test_volume_sample_grad_world_f_linear_values,
458
+ dim=1,
459
+ inputs=[volumes["float"][device.alias].id, xyzs, values, case_num],
460
+ device=device,
586
461
  )
587
- points = wp.array(points_np, dtype=wp.vec3, device=device)
588
- values = wp.empty(len(points_np), dtype=wp.vec3, device=device)
589
- wp.launch(test_volume_store_v, dim=len(points_np), inputs=[volume.id, points, values], device=device)
590
-
591
- values_res = values.numpy()
592
- np.testing.assert_equal(values_res, values_ref)
593
-
594
- def test_volume_allocation_i(self):
595
- bg_value = -123
596
- points_np = np.append(point_grid, [[8096, 8096, 8096]], axis=0)
597
- values_ref = np.append(
598
- np.array([x + 100 * y + 10000 * z for x, y, z in point_grid], dtype=np.int32), bg_value
462
+ tape.backward(values)
463
+
464
+ x, y, z = test_case
465
+ grad_computed = tape.gradients[xyzs].numpy()[0]
466
+ if case_num == 0:
467
+ grad_expected = np.array([y * z, x * z, x * y]) / 0.25
468
+ elif case_num == 1:
469
+ grad_expected = np.array([0.0, z, y]) / 0.25
470
+ elif case_num == 2:
471
+ grad_expected = np.array([z, 0.0, x]) / 0.25
472
+ elif case_num == 3:
473
+ grad_expected = np.array([y, x, 0.0]) / 0.25
474
+
475
+ np.testing.assert_allclose(grad_computed, grad_expected, rtol=1e-4)
476
+ tape.zero()
477
+
478
+
479
+ def test_volume_sample_linear_v_gradient(test, device):
480
+ points = rng.uniform(-10.0, 10.0, size=(100, 3))
481
+ values = wp.zeros(1, dtype=wp.float32, device=device, requires_grad=True)
482
+ for test_case in points:
483
+ uvws = wp.array(test_case, dtype=wp.vec3, device=device, requires_grad=True)
484
+ xyzs = wp.array(test_case * 0.25, dtype=wp.vec3, device=device, requires_grad=True)
485
+
486
+ tape = wp.Tape()
487
+ with tape:
488
+ wp.launch(
489
+ test_volume_sample_local_v_linear_values,
490
+ dim=1,
491
+ inputs=[volumes["vec3f"][device.alias].id, uvws, values],
492
+ device=device,
493
+ )
494
+ tape.backward(values)
495
+
496
+ grad_expected = np.array([6.0, 15.0, 24.0])
497
+ grad_computed = tape.gradients[uvws].numpy()[0]
498
+ np.testing.assert_allclose(grad_computed, grad_expected, rtol=1e-4)
499
+
500
+ tape = wp.Tape()
501
+ with tape:
502
+ wp.launch(
503
+ test_volume_sample_world_v_linear_values,
504
+ dim=1,
505
+ inputs=[volumes["vec3f"][device.alias].id, xyzs, values],
506
+ device=device,
507
+ )
508
+ tape.backward(values)
509
+
510
+ grad_expected = np.array([6.0, 15.0, 24.0]) / 0.25
511
+ grad_computed = tape.gradients[xyzs].numpy()[0]
512
+ np.testing.assert_allclose(grad_computed, grad_expected, rtol=1e-4)
513
+
514
+
515
+ def test_volume_transform_gradient(test, device):
516
+ values = wp.zeros(1, dtype=wp.float32, device=device, requires_grad=True)
517
+ grad_values = wp.zeros(1, dtype=wp.vec3, device=device)
518
+ test_points = rng.uniform(-10.0, 10.0, size=(10, 3))
519
+ for test_case in test_points:
520
+ points = wp.array(test_case, dtype=wp.vec3, device=device, requires_grad=True)
521
+ tape = wp.Tape()
522
+ with tape:
523
+ wp.launch(
524
+ test_volume_index_to_world,
525
+ dim=1,
526
+ inputs=[volumes["torus"][device.alias].id, points, values, grad_values],
527
+ device=device,
599
528
  )
600
- for device in devices:
601
- if device.is_cpu:
602
- continue
529
+ tape.backward(values)
530
+
531
+ grad_computed = tape.gradients[points].numpy()
532
+ grad_expected = grad_values.numpy()
533
+ np.testing.assert_allclose(grad_computed, grad_expected, rtol=1e-4)
534
+
535
+ grad_computed = tape.gradients[points].numpy()
536
+ grad_expected = grad_values.numpy()
537
+ np.testing.assert_allclose(grad_computed, grad_expected, rtol=1e-4)
538
+
539
+
540
+ def test_volume_store(test, device):
541
+ values_ref = np.array([x + 100 * y + 10000 * z for x, y, z in point_grid])
542
+ points = wp.array(point_grid, dtype=wp.vec3, device=device)
543
+ values = wp.empty(len(point_grid), dtype=wp.float32, device=device)
544
+ wp.launch(
545
+ test_volume_store_f,
546
+ dim=len(point_grid),
547
+ inputs=[volumes["float_write"][device.alias].id, points, values],
548
+ device=device,
549
+ )
603
550
 
604
- volume = wp.Volume.allocate(
605
- min=[-11, -11, -11], max=[11, 11, 11], voxel_size=0.1, bg_value=bg_value, device=device
606
- )
607
- points = wp.array(points_np, dtype=wp.vec3, device=device)
608
- values = wp.empty(len(points_np), dtype=wp.int32, device=device)
609
- wp.launch(test_volume_store_i, dim=len(points_np), inputs=[volume.id, points, values], device=device)
610
-
611
- values_res = values.numpy()
612
- np.testing.assert_equal(values_res, values_ref)
613
-
614
- def test_volume_introspection(self):
615
- for volume_names in ("float", "vec3f"):
616
- for device in devices:
617
- volume = volumes[volume_names][device.alias]
618
- tiles_actual = volume.get_tiles().numpy()
619
- tiles_sorted = tiles_actual[np.lexsort(tiles_actual.T[::-1])]
620
- voxel_size = np.array(volume.get_voxel_size())
621
-
622
- np.testing.assert_equal(test_volume_tiles, tiles_sorted)
623
- np.testing.assert_equal([0.25] * 3, voxel_size)
624
-
625
- def test_volume_from_numpy(self):
626
- # Volume.allocate_from_tiles() is only available with CUDA
627
- if wp.is_cuda_available():
628
- mins = np.array([-3.0, -3.0, -3.0])
629
- voxel_size = 0.2
630
- maxs = np.array([3.0, 3.0, 3.0])
631
- nums = np.ceil((maxs - mins) / (voxel_size)).astype(dtype=int)
632
- center = np.array([0.0, 0.0, 0.0])
633
- rad = 2.5
634
- sphere_sdf_np = np.zeros(tuple(nums))
635
- for x in range(nums[0]):
636
- for y in range(nums[1]):
637
- for z in range(nums[2]):
638
- pos = mins + voxel_size * np.array([x, y, z])
639
- dis = np.linalg.norm(pos - center)
640
- sphere_sdf_np[x, y, z] = dis - rad
641
- sphere_vdb = wp.Volume.load_from_numpy(sphere_sdf_np, mins, voxel_size, rad + 3.0 * voxel_size)
642
-
643
- self.assertNotEqual(sphere_vdb.id, 0)
644
-
645
- sphere_vdb_array = sphere_vdb.array()
646
- self.assertEqual(sphere_vdb_array.dtype, wp.uint8)
647
- self.assertFalse(sphere_vdb_array.owner)
551
+ values_res = values.numpy()
552
+ np.testing.assert_equal(values_res, values_ref)
553
+
554
+
555
+ def test_volume_allocation_f(test, device):
556
+ bg_value = -123.0
557
+ points_np = np.append(point_grid, [[8096, 8096, 8096]], axis=0)
558
+ values_ref = np.append(np.array([x + 100 * y + 10000 * z for x, y, z in point_grid]), bg_value)
559
+
560
+ volume = wp.Volume.allocate(min=[-11, -11, -11], max=[11, 11, 11], voxel_size=0.1, bg_value=bg_value, device=device)
561
+ points = wp.array(points_np, dtype=wp.vec3, device=device)
562
+ values = wp.empty(len(points_np), dtype=wp.float32, device=device)
563
+ wp.launch(test_volume_store_f, dim=len(points_np), inputs=[volume.id, points, values], device=device)
564
+
565
+ values_res = values.numpy()
566
+ np.testing.assert_equal(values_res, values_ref)
567
+
568
+
569
+ def test_volume_allocation_v(test, device):
570
+ bg_value = (-1, 2.0, -3)
571
+ points_np = np.append(point_grid, [[8096, 8096, 8096]], axis=0)
572
+ values_ref = np.append(point_grid, [bg_value], axis=0)
573
+
574
+ volume = wp.Volume.allocate(min=[-11, -11, -11], max=[11, 11, 11], voxel_size=0.1, bg_value=bg_value, device=device)
575
+ points = wp.array(points_np, dtype=wp.vec3, device=device)
576
+ values = wp.empty(len(points_np), dtype=wp.vec3, device=device)
577
+ wp.launch(test_volume_store_v, dim=len(points_np), inputs=[volume.id, points, values], device=device)
578
+
579
+ values_res = values.numpy()
580
+ np.testing.assert_equal(values_res, values_ref)
581
+
582
+
583
+ def test_volume_allocation_i(test, device):
584
+ bg_value = -123
585
+ points_np = np.append(point_grid, [[8096, 8096, 8096]], axis=0)
586
+ values_ref = np.append(np.array([x + 100 * y + 10000 * z for x, y, z in point_grid], dtype=np.int32), bg_value)
587
+
588
+ volume = wp.Volume.allocate(min=[-11, -11, -11], max=[11, 11, 11], voxel_size=0.1, bg_value=bg_value, device=device)
589
+ points = wp.array(points_np, dtype=wp.vec3, device=device)
590
+ values = wp.empty(len(points_np), dtype=wp.int32, device=device)
591
+ wp.launch(test_volume_store_i, dim=len(points_np), inputs=[volume.id, points, values], device=device)
592
+
593
+ values_res = values.numpy()
594
+ np.testing.assert_equal(values_res, values_ref)
595
+
596
+
597
+ def test_volume_introspection(test, device):
598
+ for volume_names in ("float", "vec3f"):
599
+ with test.subTest(volume_names=volume_names):
600
+ volume = volumes[volume_names][device.alias]
601
+ tiles_actual = volume.get_tiles().numpy()
602
+ tiles_sorted = tiles_actual[np.lexsort(tiles_actual.T[::-1])]
603
+ voxel_size = np.array(volume.get_voxel_size())
604
+
605
+ np.testing.assert_equal(test_volume_tiles, tiles_sorted)
606
+ np.testing.assert_equal([0.25] * 3, voxel_size)
607
+
608
+
609
+ def test_volume_from_numpy(test, device):
610
+ # Volume.allocate_from_tiles() is only available with CUDA
611
+ mins = np.array([-3.0, -3.0, -3.0])
612
+ voxel_size = 0.2
613
+ maxs = np.array([3.0, 3.0, 3.0])
614
+ nums = np.ceil((maxs - mins) / (voxel_size)).astype(dtype=int)
615
+ center = np.array([0.0, 0.0, 0.0])
616
+ rad = 2.5
617
+ sphere_sdf_np = np.zeros(tuple(nums))
618
+ for x in range(nums[0]):
619
+ for y in range(nums[1]):
620
+ for z in range(nums[2]):
621
+ pos = mins + voxel_size * np.array([x, y, z])
622
+ dis = np.linalg.norm(pos - center)
623
+ sphere_sdf_np[x, y, z] = dis - rad
624
+ sphere_vdb = wp.Volume.load_from_numpy(sphere_sdf_np, mins, voxel_size, rad + 3.0 * voxel_size, device=device)
625
+
626
+ test.assertNotEqual(sphere_vdb.id, 0)
627
+
628
+ sphere_vdb_array = sphere_vdb.array()
629
+ test.assertEqual(sphere_vdb_array.dtype, wp.uint8)
630
+ test.assertFalse(sphere_vdb_array.owner)
631
+
632
+
633
+ class TestVolume(unittest.TestCase):
634
+ pass
635
+
636
+
637
+ add_function_test(
638
+ TestVolume, "test_volume_sample_linear_f_gradient", test_volume_sample_linear_f_gradient, devices=devices
639
+ )
640
+ add_function_test(
641
+ TestVolume, "test_volume_sample_grad_linear_f_gradient", test_volume_sample_grad_linear_f_gradient, devices=devices
642
+ )
643
+ add_function_test(
644
+ TestVolume, "test_volume_sample_linear_v_gradient", test_volume_sample_linear_v_gradient, devices=devices
645
+ )
646
+ add_function_test(TestVolume, "test_volume_transform_gradient", test_volume_transform_gradient, devices=devices)
647
+ add_function_test(TestVolume, "test_volume_store", test_volume_store, devices=devices)
648
+ add_function_test(
649
+ TestVolume, "test_volume_allocation_f", test_volume_allocation_f, devices=get_unique_cuda_test_devices()
650
+ )
651
+ add_function_test(
652
+ TestVolume, "test_volume_allocation_v", test_volume_allocation_v, devices=get_unique_cuda_test_devices()
653
+ )
654
+ add_function_test(
655
+ TestVolume, "test_volume_allocation_i", test_volume_allocation_i, devices=get_unique_cuda_test_devices()
656
+ )
657
+ add_function_test(TestVolume, "test_volume_introspection", test_volume_introspection, devices=devices)
658
+ add_function_test(TestVolume, "test_volume_from_numpy", test_volume_from_numpy, devices=get_unique_cuda_test_devices())
659
+
660
+ points = {}
661
+ points_jittered = {}
662
+ for device in devices:
663
+ points_jittered_np = point_grid + rng.uniform(-0.5, 0.5, size=point_grid.shape)
664
+ points[device.alias] = wp.array(point_grid, dtype=wp.vec3, device=device)
665
+ points_jittered[device.alias] = wp.array(points_jittered_np, dtype=wp.vec3, device=device)
666
+
667
+ add_kernel_test(
668
+ TestVolume,
669
+ test_volume_lookup_f,
670
+ dim=len(point_grid),
671
+ inputs=[volumes["float"][device.alias].id, points[device.alias]],
672
+ devices=[device],
673
+ )
674
+ add_kernel_test(
675
+ TestVolume,
676
+ test_volume_sample_closest_f,
677
+ dim=len(point_grid),
678
+ inputs=[volumes["float"][device.alias].id, points_jittered[device.alias]],
679
+ devices=[device.alias],
680
+ )
681
+ add_kernel_test(
682
+ TestVolume,
683
+ test_volume_sample_linear_f,
684
+ dim=len(point_grid),
685
+ inputs=[volumes["float"][device.alias].id, points_jittered[device.alias]],
686
+ devices=[device.alias],
687
+ )
688
+ add_kernel_test(
689
+ TestVolume,
690
+ test_volume_sample_grad_linear_f,
691
+ dim=len(point_grid),
692
+ inputs=[volumes["float"][device.alias].id, points_jittered[device.alias]],
693
+ devices=[device.alias],
694
+ )
648
695
 
649
- for device in devices:
650
- points_jittered_np = point_grid + rng.uniform(-0.5, 0.5, size=point_grid.shape)
651
- points[device.alias] = wp.array(point_grid, dtype=wp.vec3, device=device)
652
- points_jittered[device.alias] = wp.array(points_jittered_np, dtype=wp.vec3, device=device)
653
-
654
- add_kernel_test(
655
- TestVolumes,
656
- test_volume_lookup_f,
657
- dim=len(point_grid),
658
- inputs=[volumes["float"][device.alias].id, points[device.alias]],
659
- devices=[device],
660
- )
661
- add_kernel_test(
662
- TestVolumes,
663
- test_volume_sample_closest_f,
664
- dim=len(point_grid),
665
- inputs=[volumes["float"][device.alias].id, points_jittered[device.alias]],
666
- devices=[device.alias],
667
- )
668
- add_kernel_test(
669
- TestVolumes,
670
- test_volume_sample_linear_f,
671
- dim=len(point_grid),
672
- inputs=[volumes["float"][device.alias].id, points_jittered[device.alias]],
673
- devices=[device.alias],
674
- )
675
- add_kernel_test(
676
- TestVolumes,
677
- test_volume_sample_grad_linear_f,
678
- dim=len(point_grid),
679
- inputs=[volumes["float"][device.alias].id, points_jittered[device.alias]],
680
- devices=[device.alias],
681
- )
682
-
683
- add_kernel_test(
684
- TestVolumes,
685
- test_volume_lookup_v,
686
- dim=len(point_grid),
687
- inputs=[volumes["vec3f"][device.alias].id, points[device.alias]],
688
- devices=[device.alias],
689
- )
690
- add_kernel_test(
691
- TestVolumes,
692
- test_volume_sample_closest_v,
693
- dim=len(point_grid),
694
- inputs=[volumes["vec3f"][device.alias].id, points_jittered[device.alias]],
695
- devices=[device.alias],
696
- )
697
- add_kernel_test(
698
- TestVolumes,
699
- test_volume_sample_linear_v,
700
- dim=len(point_grid),
701
- inputs=[volumes["vec3f"][device.alias].id, points_jittered[device.alias]],
702
- devices=[device.alias],
703
- )
704
-
705
- add_kernel_test(
706
- TestVolumes,
707
- test_volume_lookup_i,
708
- dim=len(point_grid),
709
- inputs=[volumes["int32"][device.alias].id, points[device.alias]],
710
- devices=[device.alias],
711
- )
712
- add_kernel_test(
713
- TestVolumes,
714
- test_volume_sample_i,
715
- dim=len(point_grid),
716
- inputs=[volumes["int32"][device.alias].id, points_jittered[device.alias]],
717
- devices=[device.alias],
718
- )
719
-
720
- return TestVolumes
696
+ add_kernel_test(
697
+ TestVolume,
698
+ test_volume_lookup_v,
699
+ dim=len(point_grid),
700
+ inputs=[volumes["vec3f"][device.alias].id, points[device.alias]],
701
+ devices=[device.alias],
702
+ )
703
+ add_kernel_test(
704
+ TestVolume,
705
+ test_volume_sample_closest_v,
706
+ dim=len(point_grid),
707
+ inputs=[volumes["vec3f"][device.alias].id, points_jittered[device.alias]],
708
+ devices=[device.alias],
709
+ )
710
+ add_kernel_test(
711
+ TestVolume,
712
+ test_volume_sample_linear_v,
713
+ dim=len(point_grid),
714
+ inputs=[volumes["vec3f"][device.alias].id, points_jittered[device.alias]],
715
+ devices=[device.alias],
716
+ )
717
+
718
+ add_kernel_test(
719
+ TestVolume,
720
+ test_volume_lookup_i,
721
+ dim=len(point_grid),
722
+ inputs=[volumes["int32"][device.alias].id, points[device.alias]],
723
+ devices=[device.alias],
724
+ )
725
+ add_kernel_test(
726
+ TestVolume,
727
+ test_volume_sample_i,
728
+ dim=len(point_grid),
729
+ inputs=[volumes["int32"][device.alias].id, points_jittered[device.alias]],
730
+ devices=[device.alias],
731
+ )
721
732
 
722
733
 
723
734
  if __name__ == "__main__":
724
735
  wp.build.clear_kernel_cache()
725
- wp.force_load()
726
- _ = register(unittest.TestCase)
727
736
  unittest.main(verbosity=2)