warp-lang 1.1.0__py3-none-win_amd64.whl → 1.2.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 (218) hide show
  1. warp/bin/warp-clang.dll +0 -0
  2. warp/bin/warp.dll +0 -0
  3. warp/build.py +10 -37
  4. warp/build_dll.py +2 -2
  5. warp/builtins.py +274 -6
  6. warp/codegen.py +51 -4
  7. warp/config.py +2 -2
  8. warp/constants.py +4 -0
  9. warp/context.py +418 -203
  10. warp/examples/benchmarks/benchmark_api.py +0 -2
  11. warp/examples/benchmarks/benchmark_cloth_warp.py +0 -1
  12. warp/examples/benchmarks/benchmark_launches.py +0 -2
  13. warp/examples/core/example_dem.py +0 -2
  14. warp/examples/core/example_fluid.py +0 -2
  15. warp/examples/core/example_graph_capture.py +0 -2
  16. warp/examples/core/example_marching_cubes.py +0 -2
  17. warp/examples/core/example_mesh.py +0 -2
  18. warp/examples/core/example_mesh_intersect.py +0 -2
  19. warp/examples/core/example_nvdb.py +0 -2
  20. warp/examples/core/example_raycast.py +0 -2
  21. warp/examples/core/example_raymarch.py +0 -2
  22. warp/examples/core/example_render_opengl.py +0 -2
  23. warp/examples/core/example_sph.py +0 -2
  24. warp/examples/core/example_torch.py +0 -3
  25. warp/examples/core/example_wave.py +0 -2
  26. warp/examples/fem/example_apic_fluid.py +140 -115
  27. warp/examples/fem/example_burgers.py +262 -0
  28. warp/examples/fem/example_convection_diffusion.py +0 -2
  29. warp/examples/fem/example_convection_diffusion_dg.py +0 -2
  30. warp/examples/fem/example_deformed_geometry.py +0 -2
  31. warp/examples/fem/example_diffusion.py +0 -2
  32. warp/examples/fem/example_diffusion_3d.py +5 -4
  33. warp/examples/fem/example_diffusion_mgpu.py +0 -2
  34. warp/examples/fem/example_mixed_elasticity.py +0 -2
  35. warp/examples/fem/example_navier_stokes.py +0 -2
  36. warp/examples/fem/example_stokes.py +0 -2
  37. warp/examples/fem/example_stokes_transfer.py +0 -2
  38. warp/examples/optim/example_bounce.py +0 -2
  39. warp/examples/optim/example_cloth_throw.py +0 -2
  40. warp/examples/optim/example_diffray.py +0 -2
  41. warp/examples/optim/example_drone.py +0 -2
  42. warp/examples/optim/example_inverse_kinematics.py +0 -2
  43. warp/examples/optim/example_inverse_kinematics_torch.py +0 -2
  44. warp/examples/optim/example_spring_cage.py +0 -2
  45. warp/examples/optim/example_trajectory.py +0 -2
  46. warp/examples/optim/example_walker.py +0 -2
  47. warp/examples/sim/example_cartpole.py +0 -2
  48. warp/examples/sim/example_cloth.py +0 -2
  49. warp/examples/sim/example_granular.py +0 -2
  50. warp/examples/sim/example_granular_collision_sdf.py +0 -2
  51. warp/examples/sim/example_jacobian_ik.py +0 -2
  52. warp/examples/sim/example_particle_chain.py +0 -2
  53. warp/examples/sim/example_quadruped.py +0 -2
  54. warp/examples/sim/example_rigid_chain.py +0 -2
  55. warp/examples/sim/example_rigid_contact.py +0 -2
  56. warp/examples/sim/example_rigid_force.py +0 -2
  57. warp/examples/sim/example_rigid_gyroscopic.py +0 -2
  58. warp/examples/sim/example_rigid_soft_contact.py +0 -2
  59. warp/examples/sim/example_soft_body.py +0 -2
  60. warp/fem/__init__.py +1 -0
  61. warp/fem/cache.py +3 -1
  62. warp/fem/geometry/__init__.py +1 -0
  63. warp/fem/geometry/element.py +4 -0
  64. warp/fem/geometry/grid_3d.py +0 -4
  65. warp/fem/geometry/nanogrid.py +455 -0
  66. warp/fem/integrate.py +63 -9
  67. warp/fem/space/__init__.py +43 -158
  68. warp/fem/space/basis_space.py +34 -0
  69. warp/fem/space/collocated_function_space.py +1 -1
  70. warp/fem/space/grid_2d_function_space.py +13 -132
  71. warp/fem/space/grid_3d_function_space.py +16 -154
  72. warp/fem/space/hexmesh_function_space.py +37 -134
  73. warp/fem/space/nanogrid_function_space.py +202 -0
  74. warp/fem/space/quadmesh_2d_function_space.py +12 -119
  75. warp/fem/space/restriction.py +4 -1
  76. warp/fem/space/shape/__init__.py +77 -0
  77. warp/fem/space/shape/cube_shape_function.py +5 -15
  78. warp/fem/space/tetmesh_function_space.py +6 -76
  79. warp/fem/space/trimesh_2d_function_space.py +6 -76
  80. warp/native/array.h +12 -3
  81. warp/native/builtin.h +48 -5
  82. warp/native/bvh.cpp +14 -10
  83. warp/native/bvh.cu +23 -15
  84. warp/native/bvh.h +1 -0
  85. warp/native/clang/clang.cpp +2 -1
  86. warp/native/crt.cpp +11 -1
  87. warp/native/crt.h +18 -1
  88. warp/native/exports.h +187 -0
  89. warp/native/mat.h +47 -0
  90. warp/native/mesh.cpp +1 -1
  91. warp/native/mesh.cu +1 -2
  92. warp/native/nanovdb/GridHandle.h +366 -0
  93. warp/native/nanovdb/HostBuffer.h +590 -0
  94. warp/native/nanovdb/NanoVDB.h +3999 -2157
  95. warp/native/nanovdb/PNanoVDB.h +936 -99
  96. warp/native/quat.h +28 -1
  97. warp/native/rand.h +5 -1
  98. warp/native/vec.h +45 -1
  99. warp/native/volume.cpp +335 -103
  100. warp/native/volume.cu +39 -13
  101. warp/native/volume.h +725 -303
  102. warp/native/volume_builder.cu +381 -360
  103. warp/native/volume_builder.h +16 -1
  104. warp/native/volume_impl.h +61 -0
  105. warp/native/warp.cu +8 -2
  106. warp/native/warp.h +15 -7
  107. warp/render/render_opengl.py +191 -52
  108. warp/sim/integrator_featherstone.py +10 -3
  109. warp/sim/integrator_xpbd.py +16 -22
  110. warp/sparse.py +89 -27
  111. warp/stubs.py +83 -0
  112. warp/tests/assets/test_index_grid.nvdb +0 -0
  113. warp/tests/aux_test_dependent.py +0 -2
  114. warp/tests/aux_test_grad_customs.py +0 -2
  115. warp/tests/aux_test_reference.py +0 -2
  116. warp/tests/aux_test_reference_reference.py +0 -2
  117. warp/tests/aux_test_square.py +0 -2
  118. warp/tests/disabled_kinematics.py +0 -2
  119. warp/tests/test_adam.py +0 -2
  120. warp/tests/test_arithmetic.py +0 -36
  121. warp/tests/test_array.py +9 -11
  122. warp/tests/test_array_reduce.py +0 -2
  123. warp/tests/test_async.py +0 -2
  124. warp/tests/test_atomic.py +0 -2
  125. warp/tests/test_bool.py +58 -50
  126. warp/tests/test_builtins_resolution.py +0 -2
  127. warp/tests/test_bvh.py +0 -2
  128. warp/tests/test_closest_point_edge_edge.py +0 -1
  129. warp/tests/test_codegen.py +0 -4
  130. warp/tests/test_compile_consts.py +130 -10
  131. warp/tests/test_conditional.py +0 -2
  132. warp/tests/test_copy.py +0 -2
  133. warp/tests/test_ctypes.py +6 -8
  134. warp/tests/test_dense.py +0 -2
  135. warp/tests/test_devices.py +0 -2
  136. warp/tests/test_dlpack.py +9 -11
  137. warp/tests/test_examples.py +42 -39
  138. warp/tests/test_fabricarray.py +0 -3
  139. warp/tests/test_fast_math.py +0 -2
  140. warp/tests/test_fem.py +75 -54
  141. warp/tests/test_fp16.py +0 -2
  142. warp/tests/test_func.py +0 -2
  143. warp/tests/test_generics.py +27 -2
  144. warp/tests/test_grad.py +147 -8
  145. warp/tests/test_grad_customs.py +0 -2
  146. warp/tests/test_hash_grid.py +1 -3
  147. warp/tests/test_import.py +0 -2
  148. warp/tests/test_indexedarray.py +0 -2
  149. warp/tests/test_intersect.py +0 -2
  150. warp/tests/test_jax.py +0 -2
  151. warp/tests/test_large.py +11 -9
  152. warp/tests/test_launch.py +0 -2
  153. warp/tests/test_lerp.py +10 -54
  154. warp/tests/test_linear_solvers.py +3 -5
  155. warp/tests/test_lvalue.py +0 -2
  156. warp/tests/test_marching_cubes.py +0 -2
  157. warp/tests/test_mat.py +0 -2
  158. warp/tests/test_mat_lite.py +0 -2
  159. warp/tests/test_mat_scalar_ops.py +0 -2
  160. warp/tests/test_math.py +0 -2
  161. warp/tests/test_matmul.py +35 -37
  162. warp/tests/test_matmul_lite.py +29 -31
  163. warp/tests/test_mempool.py +0 -2
  164. warp/tests/test_mesh.py +0 -3
  165. warp/tests/test_mesh_query_aabb.py +0 -2
  166. warp/tests/test_mesh_query_point.py +0 -2
  167. warp/tests/test_mesh_query_ray.py +0 -2
  168. warp/tests/test_mlp.py +0 -2
  169. warp/tests/test_model.py +0 -2
  170. warp/tests/test_module_hashing.py +111 -0
  171. warp/tests/test_modules_lite.py +0 -3
  172. warp/tests/test_multigpu.py +0 -2
  173. warp/tests/test_noise.py +0 -4
  174. warp/tests/test_operators.py +0 -2
  175. warp/tests/test_options.py +0 -2
  176. warp/tests/test_peer.py +0 -2
  177. warp/tests/test_pinned.py +0 -2
  178. warp/tests/test_print.py +0 -2
  179. warp/tests/test_quat.py +0 -2
  180. warp/tests/test_rand.py +41 -5
  181. warp/tests/test_reload.py +0 -10
  182. warp/tests/test_rounding.py +0 -2
  183. warp/tests/test_runlength_encode.py +0 -2
  184. warp/tests/test_sim_grad.py +0 -2
  185. warp/tests/test_sim_kinematics.py +0 -2
  186. warp/tests/test_smoothstep.py +0 -2
  187. warp/tests/test_snippet.py +0 -2
  188. warp/tests/test_sparse.py +0 -2
  189. warp/tests/test_spatial.py +0 -2
  190. warp/tests/test_special_values.py +362 -0
  191. warp/tests/test_streams.py +0 -2
  192. warp/tests/test_struct.py +0 -2
  193. warp/tests/test_tape.py +0 -2
  194. warp/tests/test_torch.py +0 -2
  195. warp/tests/test_transient_module.py +0 -2
  196. warp/tests/test_types.py +0 -2
  197. warp/tests/test_utils.py +0 -2
  198. warp/tests/test_vec.py +0 -2
  199. warp/tests/test_vec_lite.py +0 -2
  200. warp/tests/test_vec_scalar_ops.py +0 -2
  201. warp/tests/test_verify_fp.py +0 -2
  202. warp/tests/test_volume.py +237 -13
  203. warp/tests/test_volume_write.py +86 -3
  204. warp/tests/unittest_serial.py +10 -9
  205. warp/tests/unittest_suites.py +6 -2
  206. warp/tests/unittest_utils.py +2 -171
  207. warp/tests/unused_test_misc.py +0 -2
  208. warp/tests/walkthrough_debug.py +1 -1
  209. warp/thirdparty/unittest_parallel.py +37 -40
  210. warp/types.py +514 -77
  211. {warp_lang-1.1.0.dist-info → warp_lang-1.2.0.dist-info}/METADATA +57 -30
  212. warp_lang-1.2.0.dist-info/RECORD +359 -0
  213. warp/examples/fem/example_convection_diffusion_dg0.py +0 -204
  214. warp/native/nanovdb/PNanoVDBWrite.h +0 -295
  215. warp_lang-1.1.0.dist-info/RECORD +0 -352
  216. {warp_lang-1.1.0.dist-info → warp_lang-1.2.0.dist-info}/LICENSE.md +0 -0
  217. {warp_lang-1.1.0.dist-info → warp_lang-1.2.0.dist-info}/WHEEL +0 -0
  218. {warp_lang-1.1.0.dist-info → warp_lang-1.2.0.dist-info}/top_level.txt +0 -0
@@ -27,7 +27,7 @@ import os
27
27
  import subprocess
28
28
  import sys
29
29
  import unittest
30
- from typing import Any, Dict
30
+ from typing import Any, Dict, Optional, Type
31
31
 
32
32
  import warp as wp
33
33
  import warp.tests.unittest_utils
@@ -38,10 +38,9 @@ from warp.tests.unittest_utils import (
38
38
  sanitize_identifier,
39
39
  )
40
40
 
41
- wp.init()
42
-
43
41
 
44
42
  def _build_command_line_options(test_options: Dict[str, Any]) -> list:
43
+ """Helper function to build command-line options from the test options dictionary."""
45
44
  additional_options = []
46
45
 
47
46
  for key, value in test_options.items():
@@ -54,8 +53,25 @@ def _build_command_line_options(test_options: Dict[str, Any]) -> list:
54
53
  return additional_options
55
54
 
56
55
 
57
- # registers an example to run as a TestCase
58
- def add_example_test(cls, name, devices=None, test_options=None, test_options_cpu=None, test_options_cuda=None):
56
+ def _merge_options(base_options: Dict[str, Any], device_options: Dict[str, Any]) -> Dict[str, Any]:
57
+ """Helper function to merge base test options with device-specific test options."""
58
+ merged_options = base_options.copy()
59
+
60
+ # Update options with device-specific dictionary, overwriting existing keys with the more-specific values
61
+ merged_options.update(device_options)
62
+ return merged_options
63
+
64
+
65
+ def add_example_test(
66
+ cls: Type,
67
+ name: str,
68
+ devices: Optional[list] = None,
69
+ test_options: Optional[Dict[str, Any]] = None,
70
+ test_options_cpu: Optional[Dict[str, Any]] = None,
71
+ test_options_cuda: Optional[Dict[str, Any]] = None,
72
+ ):
73
+ """Registers a Warp example to run on ``devices`` as a TestCase."""
74
+
59
75
  if test_options is None:
60
76
  test_options = {}
61
77
  if test_options_cpu is None:
@@ -64,7 +80,11 @@ def add_example_test(cls, name, devices=None, test_options=None, test_options_cp
64
80
  test_options_cuda = {}
65
81
 
66
82
  def run(test, device):
67
- options = test_options.copy()
83
+ if wp.get_device(device).is_cuda:
84
+ options = _merge_options(test_options, test_options_cuda)
85
+ else:
86
+ options = _merge_options(test_options, test_options_cpu)
87
+
68
88
  # Mark the test as skipped if Torch is not installed but required
69
89
  torch_required = options.pop("torch_required", False)
70
90
  if torch_required:
@@ -99,11 +119,7 @@ def add_example_test(cls, name, devices=None, test_options=None, test_options_cp
99
119
  ) as coverage_file:
100
120
  pass
101
121
 
102
- command = [
103
- "coverage",
104
- "run",
105
- f"--data-file={coverage_file.name}",
106
- ]
122
+ command = ["coverage", "run", f"--data-file={coverage_file.name}"]
107
123
 
108
124
  if warp.tests.unittest_utils.coverage_branch:
109
125
  command.append("--branch")
@@ -132,13 +148,6 @@ def add_example_test(cls, name, devices=None, test_options=None, test_options_cp
132
148
 
133
149
  command.extend(_build_command_line_options(options))
134
150
 
135
- if wp.get_device(device).is_cuda:
136
- # Overrides when testing on a CUDA device
137
- command.extend(_build_command_line_options(test_options_cuda))
138
- else:
139
- # Overrides when testing on a CPU device
140
- command.extend(_build_command_line_options(test_options_cpu))
141
-
142
151
  # with wp.ScopedTimer(f"{name}_{sanitize_identifier(device)}"):
143
152
  # Run the script as a subprocess
144
153
  result = subprocess.run(command, capture_output=True, text=True, env=env_vars)
@@ -176,12 +185,7 @@ class TestCoreExamples(unittest.TestCase):
176
185
  # Exclude unless we can run headless somehow
177
186
  # add_example_test(TestCoreExamples, name="example_render_opengl")
178
187
 
179
- add_example_test(
180
- TestCoreExamples,
181
- name="core.example_dem",
182
- devices=test_devices,
183
- test_options_cpu={"num_frames": 2},
184
- )
188
+ add_example_test(TestCoreExamples, name="core.example_dem", devices=test_devices, test_options_cpu={"num_frames": 2})
185
189
  add_example_test(
186
190
  TestCoreExamples,
187
191
  name="core.example_fluid",
@@ -261,12 +265,16 @@ add_example_test(
261
265
  devices=test_devices,
262
266
  test_options={"headless": True, "train_iters": 50},
263
267
  )
268
+ # NOTE: This example uses CUTLASS and will run orders of magnitude slower when Warp is built in debug mode
264
269
  add_example_test(
265
270
  TestOptimExamples,
266
271
  name="optim.example_walker",
267
272
  devices=test_devices,
268
273
  test_options={"usd_required": True},
269
- test_options_cuda={"train_iters": 3, "num_frames": 60},
274
+ test_options_cuda={
275
+ "train_iters": 1 if warp.context.runtime.core.is_debug_enabled() else 3,
276
+ "num_frames": 1 if warp.context.runtime.core.is_debug_enabled() else 60,
277
+ },
270
278
  test_options_cpu={"train_iters": 1, "num_frames": 30},
271
279
  )
272
280
 
@@ -301,11 +309,8 @@ add_example_test(
301
309
  test_options_cpu={"num_frames": 3},
302
310
  )
303
311
  add_example_test(
304
- TestSimExamples,
305
- name="sim.example_rigid_soft_contact",
306
- devices=cuda_test_devices,
307
- test_options_cpu={"num_frames": 10},
308
- ) # TODO: Segfaults on CPU in some cases, add back in CPU testing when fixed
312
+ TestSimExamples, name="sim.example_rigid_soft_contact", devices=test_devices, test_options_cpu={"num_frames": 10}
313
+ )
309
314
  add_example_test(TestSimExamples, name="sim.example_rigid_force", devices=test_devices)
310
315
  add_example_test(TestSimExamples, name="sim.example_rigid_gyroscopic", devices=test_devices)
311
316
  add_example_test(
@@ -328,13 +333,14 @@ add_example_test(
328
333
  test_options={"headless": True},
329
334
  )
330
335
 
331
- # The following examples do not need CUDA
332
336
  add_example_test(
333
337
  TestFemExamples,
334
338
  name="fem.example_apic_fluid",
335
- devices=test_devices,
336
- test_options={"num_frames": 1, "res": "16,16,16"},
339
+ devices=get_selected_cuda_test_devices(),
340
+ test_options={"num_frames": 5, "voxel_size": 2.0},
337
341
  )
342
+
343
+ # The following examples do not need CUDA
338
344
  add_example_test(
339
345
  TestFemDiffusionExamples,
340
346
  name="fem.example_diffusion",
@@ -342,10 +348,7 @@ add_example_test(
342
348
  test_options={"resolution": 10, "mesh": "tri", "headless": True},
343
349
  )
344
350
  add_example_test(
345
- TestFemDiffusionExamples,
346
- name="fem.example_diffusion_3d",
347
- devices=test_devices,
348
- test_options={"headless": True},
351
+ TestFemDiffusionExamples, name="fem.example_diffusion_3d", devices=test_devices, test_options={"headless": True}
349
352
  )
350
353
  add_example_test(
351
354
  TestFemExamples,
@@ -361,9 +364,9 @@ add_example_test(
361
364
  )
362
365
  add_example_test(
363
366
  TestFemExamples,
364
- name="fem.example_convection_diffusion_dg0",
367
+ name="fem.example_burgers",
365
368
  devices=test_devices,
366
- test_options={"resolution": 20, "num_frames": 25, "mesh": "quad", "headless": True},
369
+ test_options={"resolution": 20, "num_frames": 25, "degree": 1, "headless": True},
367
370
  )
368
371
  add_example_test(
369
372
  TestFemExamples,
@@ -14,9 +14,6 @@ import numpy as np
14
14
  import warp as wp
15
15
  from warp.tests.unittest_utils import *
16
16
 
17
- wp.init()
18
-
19
-
20
17
  # types to test fabric arrays
21
18
  _fabric_types = [
22
19
  *wp.types.scalar_types,
@@ -10,8 +10,6 @@ import unittest
10
10
  import warp as wp
11
11
  from warp.tests.unittest_utils import *
12
12
 
13
- wp.init()
14
-
15
13
 
16
14
  @wp.kernel
17
15
  def test_pow(e: float, result: float):
warp/tests/test_fem.py CHANGED
@@ -21,8 +21,6 @@ from warp.fem.types import make_free_sample
21
21
  from warp.fem.utils import grid_to_hexes, grid_to_quads, grid_to_tets, grid_to_tris
22
22
  from warp.tests.unittest_utils import *
23
23
 
24
- wp.init()
25
-
26
24
 
27
25
  @integrand
28
26
  def linear_form(s: Sample, u: Field):
@@ -435,13 +433,13 @@ def _launch_test_geometry_kernel(geo: fem.Geometry, device):
435
433
  wp.expect_near(coords, inner_side_coords, 0.0001)
436
434
  wp.expect_near(coords, outer_side_coords, 0.0001)
437
435
 
438
- vol = geo.side_measure(side_arg, s)
439
- wp.atomic_add(side_measures, side_index, vol * qp_weights[q])
436
+ area = geo.side_measure(side_arg, s)
437
+ wp.atomic_add(side_measures, side_index, area * qp_weights[q])
440
438
 
441
439
  # test consistency of side normal, measure, and deformation gradient
442
440
  F = geo.side_deformation_gradient(side_arg, s)
443
441
  F_det = DeformedGeometry._side_measure(F)
444
- wp.expect_near(F_det * REF_MEASURE, vol)
442
+ wp.expect_near(F_det * REF_MEASURE, area)
445
443
 
446
444
  nor = geo.side_normal(side_arg, s)
447
445
  F_cross = DeformedGeometry._side_normal(F)
@@ -589,6 +587,28 @@ def test_hex_mesh(test, device):
589
587
  assert_np_equal(cell_measures.numpy(), np.full(cell_measures.shape, 1.0 / (N**3)), tol=1.0e-4)
590
588
 
591
589
 
590
+ def test_nanogrid(test, device):
591
+ N = 8
592
+
593
+ points = wp.array([[0.5, 0.5, 0.5]], dtype=float, device=device)
594
+ volume = wp.Volume.allocate_by_tiles(
595
+ tile_points=points, voxel_size=1.0 / N, translation=(0.0, 0.0, 0.0), bg_value=None, device=device
596
+ )
597
+
598
+ geo = fem.Nanogrid(volume)
599
+
600
+ test.assertEqual(geo.cell_count(), (N) ** 3)
601
+ test.assertEqual(geo.vertex_count(), (N + 1) ** 3)
602
+ test.assertEqual(geo.side_count(), 3 * (N + 1) * N**2)
603
+ test.assertEqual(geo.boundary_side_count(), 6 * N * N)
604
+ test.assertEqual(geo.edge_count(), 3 * N * (N + 1) ** 2)
605
+
606
+ side_measures, cell_measures = _launch_test_geometry_kernel(geo, device)
607
+
608
+ assert_np_equal(side_measures.numpy(), np.full(side_measures.shape, 1.0 / (N**2)), tol=1.0e-4)
609
+ assert_np_equal(cell_measures.numpy(), np.full(cell_measures.shape, 1.0 / (N**3)), tol=1.0e-4)
610
+
611
+
592
612
  @integrand
593
613
  def _rigid_deformation_field(s: Sample, domain: Domain, translation: wp.vec3, rotation: wp.vec3, scale: float):
594
614
  q = wp.quat_from_axis_angle(wp.normalize(rotation), wp.length(rotation))
@@ -601,63 +621,62 @@ def test_deformed_geometry(test, device):
601
621
  with wp.ScopedDevice(device):
602
622
  positions, tet_vidx = _gen_tetmesh(N)
603
623
 
604
- geo = fem.Tetmesh(tet_vertex_indices=tet_vidx, positions=positions)
624
+ geo = fem.Tetmesh(tet_vertex_indices=tet_vidx, positions=positions)
605
625
 
606
- translation = [1.0, 2.0, 3.0]
607
- rotation = [0.0, math.pi / 4.0, 0.0]
608
- scale = 2.0
626
+ translation = [1.0, 2.0, 3.0]
627
+ rotation = [0.0, math.pi / 4.0, 0.0]
628
+ scale = 2.0
609
629
 
610
- vector_space = fem.make_polynomial_space(geo, dtype=wp.vec3, degree=2)
611
- pos_field = vector_space.make_field()
612
- fem.interpolate(
613
- _rigid_deformation_field,
614
- dest=pos_field,
615
- values={"translation": translation, "rotation": rotation, "scale": scale},
616
- )
617
-
618
- deformed_geo = pos_field.make_deformed_geometry()
619
-
620
- # rigidly-deformed geometry
621
-
622
- test.assertEqual(geo.cell_count(), 5 * (N) ** 3)
623
- test.assertEqual(geo.vertex_count(), (N + 1) ** 3)
624
- test.assertEqual(geo.side_count(), 6 * (N + 1) * N**2 + (N**3) * 4)
625
- test.assertEqual(geo.boundary_side_count(), 12 * N * N)
630
+ vector_space = fem.make_polynomial_space(geo, dtype=wp.vec3, degree=2)
631
+ pos_field = vector_space.make_field()
632
+ fem.interpolate(
633
+ _rigid_deformation_field,
634
+ dest=pos_field,
635
+ values={"translation": translation, "rotation": rotation, "scale": scale},
636
+ )
626
637
 
627
- side_measures, cell_measures = _launch_test_geometry_kernel(deformed_geo, device)
638
+ deformed_geo = pos_field.make_deformed_geometry()
628
639
 
629
- test.assertAlmostEqual(
630
- np.sum(cell_measures.numpy()), scale**3, places=4, msg=f"cell_measures = {cell_measures.numpy()}"
631
- )
632
- test.assertAlmostEqual(
633
- np.sum(side_measures.numpy()), scale**2 * (0.5 * 6 * (N + 1) + N * 2 * math.sqrt(3.0)), places=4
634
- )
640
+ # rigidly-deformed geometry
635
641
 
636
- @wp.kernel
637
- def _test_deformed_geometry_normal(
638
- geo_index_arg: geo.SideIndexArg, geo_arg: geo.SideArg, def_arg: deformed_geo.SideArg, rotation: wp.vec3
639
- ):
640
- i = wp.tid()
641
- side_index = deformed_geo.boundary_side_index(geo_index_arg, i)
642
+ test.assertEqual(geo.cell_count(), 5 * (N) ** 3)
643
+ test.assertEqual(geo.vertex_count(), (N + 1) ** 3)
644
+ test.assertEqual(geo.side_count(), 6 * (N + 1) * N**2 + (N**3) * 4)
645
+ test.assertEqual(geo.boundary_side_count(), 12 * N * N)
642
646
 
643
- s = make_free_sample(side_index, Coords(0.5, 0.5, 0.0))
644
- geo_n = geo.side_normal(geo_arg, s)
645
- def_n = deformed_geo.side_normal(def_arg, s)
647
+ side_measures, cell_measures = _launch_test_geometry_kernel(deformed_geo, wp.get_device())
646
648
 
647
- q = wp.quat_from_axis_angle(wp.normalize(rotation), wp.length(rotation))
648
- wp.expect_near(wp.quat_rotate(q, geo_n), def_n, 0.001)
649
+ test.assertAlmostEqual(
650
+ np.sum(cell_measures.numpy()), scale**3, places=4, msg=f"cell_measures = {cell_measures.numpy()}"
651
+ )
652
+ test.assertAlmostEqual(
653
+ np.sum(side_measures.numpy()), scale**2 * (0.5 * 6 * (N + 1) + N * 2 * math.sqrt(3.0)), places=4
654
+ )
649
655
 
650
- wp.launch(
651
- _test_deformed_geometry_normal,
652
- dim=geo.boundary_side_count(),
653
- device=device,
654
- inputs=[
655
- geo.side_index_arg_value(device),
656
- geo.side_arg_value(device),
657
- deformed_geo.side_arg_value(device),
658
- rotation,
659
- ],
660
- )
656
+ @wp.kernel
657
+ def _test_deformed_geometry_normal(
658
+ geo_index_arg: geo.SideIndexArg, geo_arg: geo.SideArg, def_arg: deformed_geo.SideArg, rotation: wp.vec3
659
+ ):
660
+ i = wp.tid()
661
+ side_index = deformed_geo.boundary_side_index(geo_index_arg, i)
662
+
663
+ s = make_free_sample(side_index, Coords(0.5, 0.5, 0.0))
664
+ geo_n = geo.side_normal(geo_arg, s)
665
+ def_n = deformed_geo.side_normal(def_arg, s)
666
+
667
+ q = wp.quat_from_axis_angle(wp.normalize(rotation), wp.length(rotation))
668
+ wp.expect_near(wp.quat_rotate(q, geo_n), def_n, 0.001)
669
+
670
+ wp.launch(
671
+ _test_deformed_geometry_normal,
672
+ dim=geo.boundary_side_count(),
673
+ inputs=[
674
+ geo.side_index_arg_value(wp.get_device()),
675
+ geo.side_arg_value(wp.get_device()),
676
+ deformed_geo.side_arg_value(wp.get_device()),
677
+ rotation,
678
+ ],
679
+ )
661
680
 
662
681
  wp.synchronize()
663
682
 
@@ -1237,6 +1256,7 @@ def test_particle_quadratures(test, device):
1237
1256
 
1238
1257
 
1239
1258
  devices = get_test_devices()
1259
+ cuda_devices = get_selected_cuda_test_devices()
1240
1260
 
1241
1261
 
1242
1262
  class TestFem(unittest.TestCase):
@@ -1256,6 +1276,7 @@ add_function_test(TestFem, "test_quad_mesh", test_quad_mesh, devices=devices)
1256
1276
  add_function_test(TestFem, "test_grid_3d", test_grid_3d, devices=devices)
1257
1277
  add_function_test(TestFem, "test_tet_mesh", test_tet_mesh, devices=devices)
1258
1278
  add_function_test(TestFem, "test_hex_mesh", test_hex_mesh, devices=devices)
1279
+ add_function_test(TestFem, "test_nanogrid", test_nanogrid, devices=cuda_devices)
1259
1280
  add_function_test(TestFem, "test_deformed_geometry", test_deformed_geometry, devices=devices)
1260
1281
  add_function_test(TestFem, "test_dof_mapper", test_dof_mapper)
1261
1282
  add_function_test(TestFem, "test_point_basis", test_point_basis)
warp/tests/test_fp16.py CHANGED
@@ -12,8 +12,6 @@ import numpy as np
12
12
  import warp as wp
13
13
  from warp.tests.unittest_utils import *
14
14
 
15
- wp.init()
16
-
17
15
 
18
16
  @wp.kernel
19
17
  def load_store_half(f32: wp.array(dtype=wp.float32), f16: wp.array(dtype=wp.float16)):
warp/tests/test_func.py CHANGED
@@ -13,8 +13,6 @@ import numpy as np
13
13
  import warp as wp
14
14
  from warp.tests.unittest_utils import *
15
15
 
16
- wp.init()
17
-
18
16
 
19
17
  @wp.func
20
18
  def sqr(x: float):
@@ -13,8 +13,6 @@ import numpy as np
13
13
  import warp as wp
14
14
  from warp.tests.unittest_utils import *
15
15
 
16
- wp.init()
17
-
18
16
 
19
17
  @wp.func
20
18
  def generic_adder(a: Any, b: Any):
@@ -240,6 +238,32 @@ def test_generic_fill_overloads(test, device):
240
238
  assert_np_equal(a3b.numpy(), np.full((n, 3), True, dtype=np.bool_))
241
239
 
242
240
 
241
+ # generic kernel used to test generic types mixed with specialized types
242
+ @wp.func
243
+ def generic_conditional_setter_func(a: wp.array(dtype=Any), i: int, value: Any, relative: bool):
244
+ if relative:
245
+ a[i] += value
246
+ else:
247
+ a[i] = value
248
+
249
+
250
+ @wp.kernel
251
+ def generic_conditional_setter(a: wp.array(dtype=Any), i: int, value: Any, relative: bool):
252
+ generic_conditional_setter_func(a, i, value, relative)
253
+
254
+
255
+ def test_generic_conditional_setter(test, device):
256
+ with wp.ScopedDevice(device):
257
+ n = 10
258
+ ai = wp.zeros(n, dtype=int)
259
+
260
+ wp.launch(generic_conditional_setter, dim=1, inputs=[ai, 1, 42, False])
261
+ wp.launch(generic_conditional_setter, dim=1, inputs=[ai, 1, 5, True])
262
+ ai_true = np.zeros(n, dtype=np.int32)
263
+ ai_true[1] = 47
264
+ assert_np_equal(ai.numpy(), ai_true)
265
+
266
+
243
267
  # custom vector/matrix types
244
268
  my_vec5 = wp.vec(length=5, dtype=wp.float32)
245
269
  my_mat55 = wp.mat(shape=(5, 5), dtype=wp.float32)
@@ -511,6 +535,7 @@ add_function_test(TestGenerics, "test_generic_array_kernel", test_generic_array_
511
535
  add_function_test(TestGenerics, "test_generic_accumulator_kernel", test_generic_accumulator_kernel, devices=devices)
512
536
  add_function_test(TestGenerics, "test_generic_fill", test_generic_fill, devices=devices)
513
537
  add_function_test(TestGenerics, "test_generic_fill_overloads", test_generic_fill_overloads, devices=devices)
538
+ add_function_test(TestGenerics, "test_generic_conditional_setter", test_generic_conditional_setter, devices=devices)
514
539
  add_function_test(TestGenerics, "test_generic_transform_kernel", test_generic_transform_kernel, devices=devices)
515
540
  add_function_test(
516
541
  TestGenerics, "test_generic_transform_array_kernel", test_generic_transform_array_kernel, devices=devices
warp/tests/test_grad.py CHANGED
@@ -13,8 +13,6 @@ import numpy as np
13
13
  import warp as wp
14
14
  from warp.tests.unittest_utils import *
15
15
 
16
- wp.init()
17
-
18
16
 
19
17
  @wp.kernel
20
18
  def scalar_grad(x: wp.array(dtype=float), y: wp.array(dtype=float)):
@@ -665,16 +663,40 @@ def square_kernel(x: wp.array(dtype=float), y: wp.array(dtype=float)):
665
663
  y[tid] = x[tid] ** 2.0
666
664
 
667
665
 
666
+ @wp.kernel
667
+ def square_slice_2d_kernel(x: wp.array2d(dtype=float), y: wp.array2d(dtype=float), row_idx: int):
668
+ tid = wp.tid()
669
+ x_slice = x[row_idx]
670
+ y_slice = y[row_idx]
671
+ y_slice[tid] = x_slice[tid] ** 2.0
672
+
673
+
674
+ @wp.kernel
675
+ def square_slice_3d_1d_kernel(x: wp.array3d(dtype=float), y: wp.array3d(dtype=float), slice_idx: int):
676
+ i, j = wp.tid()
677
+ x_slice = x[slice_idx]
678
+ y_slice = y[slice_idx]
679
+ y_slice[i, j] = x_slice[i, j] ** 2.0
680
+
681
+
682
+ @wp.kernel
683
+ def square_slice_3d_2d_kernel(x: wp.array3d(dtype=float), y: wp.array3d(dtype=float), slice_i: int, slice_j: int):
684
+ tid = wp.tid()
685
+ x_slice = x[slice_i, slice_j]
686
+ y_slice = y[slice_i, slice_j]
687
+ y_slice[tid] = x_slice[tid] ** 2.0
688
+
689
+
668
690
  def test_gradient_internal(test, device):
669
691
  with wp.ScopedDevice(device):
670
692
  a = wp.array([1.0, 2.0, 3.0], dtype=float, requires_grad=True)
671
693
  b = wp.array([0.0, 0.0, 0.0], dtype=float, requires_grad=True)
672
694
 
673
- wp.launch(square_kernel, a.size, inputs=[a, b])
695
+ wp.launch(square_kernel, dim=a.size, inputs=[a, b])
674
696
 
675
697
  # use internal gradients (.grad), adj_inputs are None
676
698
  b.grad = wp.array([1.0, 1.0, 1.0], dtype=float)
677
- wp.launch(square_kernel, a.shape[0], inputs=[a, b], adjoint=True, adj_inputs=[None, None])
699
+ wp.launch(square_kernel, dim=a.size, inputs=[a, b], adjoint=True, adj_inputs=[None, None])
678
700
 
679
701
  assert_np_equal(a.grad.numpy(), np.array([2.0, 4.0, 6.0]))
680
702
 
@@ -684,12 +706,12 @@ def test_gradient_external(test, device):
684
706
  a = wp.array([1.0, 2.0, 3.0], dtype=float, requires_grad=False)
685
707
  b = wp.array([0.0, 0.0, 0.0], dtype=float, requires_grad=False)
686
708
 
687
- wp.launch(square_kernel, a.size, inputs=[a, b])
709
+ wp.launch(square_kernel, dim=a.size, inputs=[a, b])
688
710
 
689
711
  # use external gradients passed in adj_inputs
690
712
  a_grad = wp.array([0.0, 0.0, 0.0], dtype=float)
691
713
  b_grad = wp.array([1.0, 1.0, 1.0], dtype=float)
692
- wp.launch(square_kernel, a.shape[0], inputs=[a, b], adjoint=True, adj_inputs=[a_grad, b_grad])
714
+ wp.launch(square_kernel, dim=a.size, inputs=[a, b], adjoint=True, adj_inputs=[a_grad, b_grad])
693
715
 
694
716
  assert_np_equal(a_grad.numpy(), np.array([2.0, 4.0, 6.0]))
695
717
 
@@ -699,18 +721,132 @@ def test_gradient_precedence(test, device):
699
721
  a = wp.array([1.0, 2.0, 3.0], dtype=float, requires_grad=True)
700
722
  b = wp.array([0.0, 0.0, 0.0], dtype=float, requires_grad=True)
701
723
 
702
- wp.launch(square_kernel, a.size, inputs=[a, b])
724
+ wp.launch(square_kernel, dim=a.size, inputs=[a, b])
703
725
 
704
726
  # if both internal and external gradients are present, the external one takes precedence,
705
727
  # because it's explicitly passed by the user in adj_inputs
706
728
  a_grad = wp.array([0.0, 0.0, 0.0], dtype=float)
707
729
  b_grad = wp.array([1.0, 1.0, 1.0], dtype=float)
708
- wp.launch(square_kernel, a.shape[0], inputs=[a, b], adjoint=True, adj_inputs=[a_grad, b_grad])
730
+ wp.launch(square_kernel, dim=a.size, inputs=[a, b], adjoint=True, adj_inputs=[a_grad, b_grad])
709
731
 
710
732
  assert_np_equal(a_grad.numpy(), np.array([2.0, 4.0, 6.0])) # used
711
733
  assert_np_equal(a.grad.numpy(), np.array([0.0, 0.0, 0.0])) # unused
712
734
 
713
735
 
736
+ def test_gradient_slice_2d(test, device):
737
+ with wp.ScopedDevice(device):
738
+ a = wp.array([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]], dtype=float, requires_grad=True)
739
+ b = wp.zeros_like(a, requires_grad=False)
740
+ b.grad = wp.ones_like(a, requires_grad=False)
741
+
742
+ wp.launch(square_slice_2d_kernel, dim=a.shape[1], inputs=[a, b, 1])
743
+
744
+ # use internal gradients (.grad), adj_inputs are None
745
+ wp.launch(square_slice_2d_kernel, dim=a.shape[1], inputs=[a, b, 1], adjoint=True, adj_inputs=[None, None, 1])
746
+
747
+ assert_np_equal(a.grad.numpy(), np.array([[0.0, 0.0], [6.0, 8.0], [0.0, 0.0]]))
748
+
749
+
750
+ def test_gradient_slice_3d_1d(test, device):
751
+ with wp.ScopedDevice(device):
752
+ data = [
753
+ [
754
+ [1, 2, 3],
755
+ [4, 5, 6],
756
+ [7, 8, 9],
757
+ ],
758
+ [
759
+ [11, 12, 13],
760
+ [14, 15, 16],
761
+ [17, 18, 19],
762
+ ],
763
+ [
764
+ [21, 22, 23],
765
+ [24, 25, 26],
766
+ [27, 28, 29],
767
+ ],
768
+ ]
769
+ a = wp.array(data, dtype=float, requires_grad=True)
770
+ b = wp.zeros_like(a, requires_grad=False)
771
+ b.grad = wp.ones_like(a, requires_grad=False)
772
+
773
+ wp.launch(square_slice_3d_1d_kernel, dim=a.shape[1:], inputs=[a, b, 1])
774
+
775
+ # use internal gradients (.grad), adj_inputs are None
776
+ wp.launch(
777
+ square_slice_3d_1d_kernel, dim=a.shape[1:], inputs=[a, b, 1], adjoint=True, adj_inputs=[None, None, 1]
778
+ )
779
+
780
+ expected_grad = [
781
+ [
782
+ [0, 0, 0],
783
+ [0, 0, 0],
784
+ [0, 0, 0],
785
+ ],
786
+ [
787
+ [11 * 2, 12 * 2, 13 * 2],
788
+ [14 * 2, 15 * 2, 16 * 2],
789
+ [17 * 2, 18 * 2, 19 * 2],
790
+ ],
791
+ [
792
+ [0, 0, 0],
793
+ [0, 0, 0],
794
+ [0, 0, 0],
795
+ ],
796
+ ]
797
+ assert_np_equal(a.grad.numpy(), np.array(expected_grad))
798
+
799
+
800
+ def test_gradient_slice_3d_2d(test, device):
801
+ with wp.ScopedDevice(device):
802
+ data = [
803
+ [
804
+ [1, 2, 3],
805
+ [4, 5, 6],
806
+ [7, 8, 9],
807
+ ],
808
+ [
809
+ [11, 12, 13],
810
+ [14, 15, 16],
811
+ [17, 18, 19],
812
+ ],
813
+ [
814
+ [21, 22, 23],
815
+ [24, 25, 26],
816
+ [27, 28, 29],
817
+ ],
818
+ ]
819
+ a = wp.array(data, dtype=float, requires_grad=True)
820
+ b = wp.zeros_like(a, requires_grad=False)
821
+ b.grad = wp.ones_like(a, requires_grad=False)
822
+
823
+ wp.launch(square_slice_3d_2d_kernel, dim=a.shape[2], inputs=[a, b, 1, 1])
824
+
825
+ # use internal gradients (.grad), adj_inputs are None
826
+ wp.launch(
827
+ square_slice_3d_2d_kernel, dim=a.shape[2], inputs=[a, b, 1, 1], adjoint=True, adj_inputs=[None, None, 1, 1]
828
+ )
829
+
830
+ expected_grad = [
831
+ [
832
+ [0, 0, 0],
833
+ [0, 0, 0],
834
+ [0, 0, 0],
835
+ ],
836
+ [
837
+ [0, 0, 0],
838
+ [14 * 2, 15 * 2, 16 * 2],
839
+ [0, 0, 0],
840
+ ],
841
+ [
842
+ [0, 0, 0],
843
+ [0, 0, 0],
844
+ [0, 0, 0],
845
+ ],
846
+ ]
847
+ assert_np_equal(a.grad.numpy(), np.array(expected_grad))
848
+
849
+
714
850
  devices = get_test_devices()
715
851
 
716
852
 
@@ -739,6 +875,9 @@ add_function_test(TestGrad, "test_aliasing", test_aliasing, devices=devices)
739
875
  add_function_test(TestGrad, "test_gradient_internal", test_gradient_internal, devices=devices)
740
876
  add_function_test(TestGrad, "test_gradient_external", test_gradient_external, devices=devices)
741
877
  add_function_test(TestGrad, "test_gradient_precedence", test_gradient_precedence, devices=devices)
878
+ add_function_test(TestGrad, "test_gradient_slice_2d", test_gradient_slice_2d, devices=devices)
879
+ add_function_test(TestGrad, "test_gradient_slice_3d_1d", test_gradient_slice_3d_1d, devices=devices)
880
+ add_function_test(TestGrad, "test_gradient_slice_3d_2d", test_gradient_slice_3d_2d, devices=devices)
742
881
 
743
882
 
744
883
  if __name__ == "__main__":
@@ -12,8 +12,6 @@ import numpy as np
12
12
  import warp as wp
13
13
  from warp.tests.unittest_utils import *
14
14
 
15
- wp.init()
16
-
17
15
 
18
16
  # atomic add function that memorizes which thread incremented the counter
19
17
  # so that the correct counter value per thread can be used in the replay
@@ -12,8 +12,6 @@ import numpy as np
12
12
  import warp as wp
13
13
  from warp.tests.unittest_utils import *
14
14
 
15
- wp.init()
16
-
17
15
  num_points = 4096
18
16
  dim_x = 128
19
17
  dim_y = 128
@@ -128,7 +126,7 @@ def test_hashgrid_query(test, device):
128
126
 
129
127
  print(f"Passed: {np.array_equal(counts, counts_ref)}")
130
128
 
131
- test.assertTrue(np.array_equal(counts, counts_ref))
129
+ assert_np_equal(counts, counts_ref)
132
130
 
133
131
 
134
132
  def test_hashgrid_inputs(test, device):