warp-lang 1.7.0__py3-none-macosx_10_13_universal2.whl → 1.7.2rc1__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 (60) hide show
  1. warp/autograd.py +12 -2
  2. warp/bin/libwarp-clang.dylib +0 -0
  3. warp/bin/libwarp.dylib +0 -0
  4. warp/build.py +1 -1
  5. warp/builtins.py +103 -66
  6. warp/codegen.py +48 -27
  7. warp/config.py +1 -1
  8. warp/context.py +112 -49
  9. warp/examples/benchmarks/benchmark_cloth.py +1 -1
  10. warp/examples/distributed/example_jacobi_mpi.py +507 -0
  11. warp/fem/cache.py +1 -1
  12. warp/fem/field/field.py +11 -1
  13. warp/fem/field/nodal_field.py +36 -22
  14. warp/fem/geometry/adaptive_nanogrid.py +7 -3
  15. warp/fem/geometry/trimesh.py +4 -12
  16. warp/jax_experimental/custom_call.py +14 -2
  17. warp/jax_experimental/ffi.py +100 -67
  18. warp/native/builtin.h +91 -65
  19. warp/native/svd.h +59 -49
  20. warp/native/tile.h +55 -26
  21. warp/native/volume.cpp +2 -2
  22. warp/native/volume_builder.cu +33 -22
  23. warp/native/warp.cu +1 -1
  24. warp/render/render_opengl.py +41 -34
  25. warp/render/render_usd.py +96 -6
  26. warp/sim/collide.py +11 -9
  27. warp/sim/inertia.py +189 -156
  28. warp/sim/integrator_euler.py +3 -0
  29. warp/sim/integrator_xpbd.py +3 -0
  30. warp/sim/model.py +56 -31
  31. warp/sim/render.py +4 -0
  32. warp/sparse.py +1 -1
  33. warp/stubs.py +73 -25
  34. warp/tests/assets/torus.usda +1 -1
  35. warp/tests/cuda/test_streams.py +1 -1
  36. warp/tests/sim/test_collision.py +237 -206
  37. warp/tests/sim/test_inertia.py +161 -0
  38. warp/tests/sim/test_model.py +5 -3
  39. warp/tests/sim/{flaky_test_sim_grad.py → test_sim_grad.py} +1 -4
  40. warp/tests/sim/test_xpbd.py +399 -0
  41. warp/tests/test_array.py +8 -7
  42. warp/tests/test_atomic.py +181 -2
  43. warp/tests/test_builtins_resolution.py +38 -38
  44. warp/tests/test_codegen.py +24 -3
  45. warp/tests/test_examples.py +16 -6
  46. warp/tests/test_fem.py +93 -14
  47. warp/tests/test_func.py +1 -1
  48. warp/tests/test_mat.py +416 -119
  49. warp/tests/test_quat.py +321 -137
  50. warp/tests/test_struct.py +116 -0
  51. warp/tests/test_vec.py +320 -174
  52. warp/tests/tile/test_tile.py +27 -0
  53. warp/tests/tile/test_tile_load.py +124 -0
  54. warp/tests/unittest_suites.py +2 -5
  55. warp/types.py +107 -9
  56. {warp_lang-1.7.0.dist-info → warp_lang-1.7.2rc1.dist-info}/METADATA +41 -19
  57. {warp_lang-1.7.0.dist-info → warp_lang-1.7.2rc1.dist-info}/RECORD +60 -57
  58. {warp_lang-1.7.0.dist-info → warp_lang-1.7.2rc1.dist-info}/WHEEL +1 -1
  59. {warp_lang-1.7.0.dist-info → warp_lang-1.7.2rc1.dist-info}/licenses/LICENSE.md +0 -26
  60. {warp_lang-1.7.0.dist-info → warp_lang-1.7.2rc1.dist-info}/top_level.txt +0 -0
@@ -84,25 +84,25 @@ def test_int_int_args_support(test, device, dtype):
84
84
  else:
85
85
  with test.assertRaisesRegex(
86
86
  RuntimeError,
87
- rf"Couldn't find a function 'mul' compatible with " rf"the arguments '{dtype.__name__}, int'$",
87
+ rf"Couldn't find a function 'mul' compatible with the arguments '{dtype.__name__}, int'$",
88
88
  ):
89
89
  wp.mul(dtype(value), value)
90
90
 
91
91
  with test.assertRaisesRegex(
92
92
  RuntimeError,
93
- rf"Couldn't find a function 'mul' compatible with " rf"the arguments '{np_type.__name__}, int'$",
93
+ rf"Couldn't find a function 'mul' compatible with the arguments '{np_type.__name__}, int'$",
94
94
  ):
95
95
  wp.mul(nps(np_type, value), value)
96
96
 
97
97
  with test.assertRaisesRegex(
98
98
  RuntimeError,
99
- rf"Couldn't find a function 'mul' compatible with " rf"the arguments 'int, {dtype.__name__}'$",
99
+ rf"Couldn't find a function 'mul' compatible with the arguments 'int, {dtype.__name__}'$",
100
100
  ):
101
101
  wp.mul(value, dtype(value))
102
102
 
103
103
  with test.assertRaisesRegex(
104
104
  RuntimeError,
105
- rf"Couldn't find a function 'mul' compatible with " rf"the arguments 'int, {np_type.__name__}'$",
105
+ rf"Couldn't find a function 'mul' compatible with the arguments 'int, {np_type.__name__}'$",
106
106
  ):
107
107
  wp.mul(value, nps(np_type, value))
108
108
 
@@ -189,73 +189,73 @@ def test_mat_mat_args_support(test, device, dtype):
189
189
  else:
190
190
  with test.assertRaisesRegex(
191
191
  RuntimeError,
192
- r"Couldn't find a function 'ddot' compatible with " r"the arguments 'mat_t, tuple'$",
192
+ r"Couldn't find a function 'ddot' compatible with the arguments 'mat_t, tuple'$",
193
193
  ):
194
194
  wp.ddot(mat_cls(*a_values), b_values)
195
195
 
196
196
  with test.assertRaisesRegex(
197
197
  RuntimeError,
198
- r"Couldn't find a function 'ddot' compatible with " r"the arguments 'tuple, tuple'$",
198
+ r"Couldn't find a function 'ddot' compatible with the arguments 'tuple, tuple'$",
199
199
  ):
200
200
  wp.ddot(wpv(dtype, a_values), b_values)
201
201
 
202
202
  with test.assertRaisesRegex(
203
203
  RuntimeError,
204
- r"Couldn't find a function 'ddot' compatible with " r"the arguments 'tuple, tuple'$",
204
+ r"Couldn't find a function 'ddot' compatible with the arguments 'tuple, tuple'$",
205
205
  ):
206
206
  wp.ddot(wpm(dtype, 3, a_values), b_values)
207
207
 
208
208
  with test.assertRaisesRegex(
209
209
  RuntimeError,
210
- r"Couldn't find a function 'ddot' compatible with " r"the arguments 'tuple, tuple'$",
210
+ r"Couldn't find a function 'ddot' compatible with the arguments 'tuple, tuple'$",
211
211
  ):
212
212
  wp.ddot(npv(np_type, a_values), b_values)
213
213
 
214
214
  with test.assertRaisesRegex(
215
215
  RuntimeError,
216
- r"Couldn't find a function 'ddot' compatible with " r"the arguments 'tuple, tuple'$",
216
+ r"Couldn't find a function 'ddot' compatible with the arguments 'tuple, tuple'$",
217
217
  ):
218
218
  wp.ddot(npm(np_type, 3, a_values), b_values)
219
219
 
220
220
  with test.assertRaisesRegex(
221
221
  RuntimeError,
222
- r"Couldn't find a function 'ddot' compatible with " r"the arguments 'ndarray, tuple'$",
222
+ r"Couldn't find a function 'ddot' compatible with the arguments 'ndarray, tuple'$",
223
223
  ):
224
224
  wp.ddot(np.array(npv(np_type, a_values)), b_values)
225
225
 
226
226
  with test.assertRaisesRegex(
227
227
  RuntimeError,
228
- r"Couldn't find a function 'ddot' compatible with " r"the arguments 'tuple, mat_t'$",
228
+ r"Couldn't find a function 'ddot' compatible with the arguments 'tuple, mat_t'$",
229
229
  ):
230
230
  wp.ddot(a_values, mat_cls(*b_values))
231
231
 
232
232
  with test.assertRaisesRegex(
233
233
  RuntimeError,
234
- r"Couldn't find a function 'ddot' compatible with " r"the arguments 'tuple, tuple'$",
234
+ r"Couldn't find a function 'ddot' compatible with the arguments 'tuple, tuple'$",
235
235
  ):
236
236
  wp.ddot(a_values, wpv(dtype, b_values))
237
237
 
238
238
  with test.assertRaisesRegex(
239
239
  RuntimeError,
240
- r"Couldn't find a function 'ddot' compatible with " r"the arguments 'tuple, tuple'$",
240
+ r"Couldn't find a function 'ddot' compatible with the arguments 'tuple, tuple'$",
241
241
  ):
242
242
  wp.ddot(a_values, wpm(dtype, 3, b_values))
243
243
 
244
244
  with test.assertRaisesRegex(
245
245
  RuntimeError,
246
- r"Couldn't find a function 'ddot' compatible with " r"the arguments 'tuple, tuple'$",
246
+ r"Couldn't find a function 'ddot' compatible with the arguments 'tuple, tuple'$",
247
247
  ):
248
248
  wp.ddot(a_values, npv(np_type, b_values))
249
249
 
250
250
  with test.assertRaisesRegex(
251
251
  RuntimeError,
252
- r"Couldn't find a function 'ddot' compatible with " r"the arguments 'tuple, tuple'$",
252
+ r"Couldn't find a function 'ddot' compatible with the arguments 'tuple, tuple'$",
253
253
  ):
254
254
  wp.ddot(a_values, npm(np_type, 3, b_values))
255
255
 
256
256
  with test.assertRaisesRegex(
257
257
  RuntimeError,
258
- r"Couldn't find a function 'ddot' compatible with " r"the arguments 'tuple, ndarray'$",
258
+ r"Couldn't find a function 'ddot' compatible with the arguments 'tuple, ndarray'$",
259
259
  ):
260
260
  wp.ddot(a_values, np.array(npv(np_type, b_values)))
261
261
 
@@ -300,49 +300,49 @@ def test_mat_float_args_support(test, device, dtype):
300
300
  else:
301
301
  with test.assertRaisesRegex(
302
302
  RuntimeError,
303
- r"Couldn't find a function 'mul' compatible with " r"the arguments 'mat_t, float'$",
303
+ r"Couldn't find a function 'mul' compatible with the arguments 'mat_t, float'$",
304
304
  ):
305
305
  wp.mul(mat_cls(*a_values), b_value)
306
306
 
307
307
  with test.assertRaisesRegex(
308
308
  RuntimeError,
309
- r"Couldn't find a function 'mul' compatible with " r"the arguments 'tuple, float'$",
309
+ r"Couldn't find a function 'mul' compatible with the arguments 'tuple, float'$",
310
310
  ):
311
311
  wp.mul(wpv(dtype, a_values), b_value)
312
312
 
313
313
  with test.assertRaisesRegex(
314
314
  RuntimeError,
315
- r"Couldn't find a function 'mul' compatible with " r"the arguments 'tuple, float'$",
315
+ r"Couldn't find a function 'mul' compatible with the arguments 'tuple, float'$",
316
316
  ):
317
317
  wp.mul(wpm(dtype, 3, a_values), b_value)
318
318
 
319
319
  with test.assertRaisesRegex(
320
320
  RuntimeError,
321
- r"Couldn't find a function 'mul' compatible with " r"the arguments 'tuple, float'$",
321
+ r"Couldn't find a function 'mul' compatible with the arguments 'tuple, float'$",
322
322
  ):
323
323
  wp.mul(npv(np_type, a_values), b_value)
324
324
 
325
325
  with test.assertRaisesRegex(
326
326
  RuntimeError,
327
- r"Couldn't find a function 'mul' compatible with " r"the arguments 'tuple, float'$",
327
+ r"Couldn't find a function 'mul' compatible with the arguments 'tuple, float'$",
328
328
  ):
329
329
  wp.mul(npm(np_type, 3, a_values), b_value)
330
330
 
331
331
  with test.assertRaisesRegex(
332
332
  RuntimeError,
333
- r"Couldn't find a function 'mul' compatible with " r"the arguments 'ndarray, float'$",
333
+ r"Couldn't find a function 'mul' compatible with the arguments 'ndarray, float'$",
334
334
  ):
335
335
  wp.mul(np.array(npv(np_type, a_values)), b_value)
336
336
 
337
337
  with test.assertRaisesRegex(
338
338
  RuntimeError,
339
- rf"Couldn't find a function 'mul' compatible with " rf"the arguments 'tuple, {dtype.__name__}'$",
339
+ rf"Couldn't find a function 'mul' compatible with the arguments 'tuple, {dtype.__name__}'$",
340
340
  ):
341
341
  wp.mul(a_values, dtype(b_value))
342
342
 
343
343
  with test.assertRaisesRegex(
344
344
  RuntimeError,
345
- rf"Couldn't find a function 'mul' compatible with " rf"the arguments 'tuple, {np_type.__name__}'$",
345
+ rf"Couldn't find a function 'mul' compatible with the arguments 'tuple, {np_type.__name__}'$",
346
346
  ):
347
347
  wp.mul(a_values, nps(np_type, b_value))
348
348
 
@@ -401,49 +401,49 @@ def test_vec_vec_args_support(test, device, dtype):
401
401
  else:
402
402
  with test.assertRaisesRegex(
403
403
  RuntimeError,
404
- r"Couldn't find a function 'dot' compatible with " r"the arguments 'vec_t, tuple'$",
404
+ r"Couldn't find a function 'dot' compatible with the arguments 'vec_t, tuple'$",
405
405
  ):
406
406
  wp.dot(vec_cls(*a_values), b_values)
407
407
 
408
408
  with test.assertRaisesRegex(
409
409
  RuntimeError,
410
- r"Couldn't find a function 'dot' compatible with " r"the arguments 'tuple, tuple'$",
410
+ r"Couldn't find a function 'dot' compatible with the arguments 'tuple, tuple'$",
411
411
  ):
412
412
  wp.dot(wpv(dtype, a_values), b_values)
413
413
 
414
414
  with test.assertRaisesRegex(
415
415
  RuntimeError,
416
- r"Couldn't find a function 'dot' compatible with " r"the arguments 'tuple, tuple'$",
416
+ r"Couldn't find a function 'dot' compatible with the arguments 'tuple, tuple'$",
417
417
  ):
418
418
  wp.dot(npv(np_type, a_values), b_values)
419
419
 
420
420
  with test.assertRaisesRegex(
421
421
  RuntimeError,
422
- r"Couldn't find a function 'dot' compatible with " r"the arguments 'ndarray, tuple'$",
422
+ r"Couldn't find a function 'dot' compatible with the arguments 'ndarray, tuple'$",
423
423
  ):
424
424
  wp.dot(np.array(npv(np_type, a_values)), b_values)
425
425
 
426
426
  with test.assertRaisesRegex(
427
427
  RuntimeError,
428
- r"Couldn't find a function 'dot' compatible with " r"the arguments 'tuple, vec_t'$",
428
+ r"Couldn't find a function 'dot' compatible with the arguments 'tuple, vec_t'$",
429
429
  ):
430
430
  wp.dot(a_values, vec_cls(*b_values))
431
431
 
432
432
  with test.assertRaisesRegex(
433
433
  RuntimeError,
434
- r"Couldn't find a function 'dot' compatible with " r"the arguments 'tuple, tuple'$",
434
+ r"Couldn't find a function 'dot' compatible with the arguments 'tuple, tuple'$",
435
435
  ):
436
436
  wp.dot(a_values, wpv(dtype, b_values))
437
437
 
438
438
  with test.assertRaisesRegex(
439
439
  RuntimeError,
440
- r"Couldn't find a function 'dot' compatible with " r"the arguments 'tuple, tuple'$",
440
+ r"Couldn't find a function 'dot' compatible with the arguments 'tuple, tuple'$",
441
441
  ):
442
442
  wp.dot(a_values, npv(np_type, b_values))
443
443
 
444
444
  with test.assertRaisesRegex(
445
445
  RuntimeError,
446
- r"Couldn't find a function 'dot' compatible with " r"the arguments 'tuple, ndarray'$",
446
+ r"Couldn't find a function 'dot' compatible with the arguments 'tuple, ndarray'$",
447
447
  ):
448
448
  wp.dot(a_values, np.array(npv(np_type, b_values)))
449
449
 
@@ -480,37 +480,37 @@ def test_vec_float_args_support(test, device, dtype):
480
480
  else:
481
481
  with test.assertRaisesRegex(
482
482
  RuntimeError,
483
- r"Couldn't find a function 'mul' compatible with " r"the arguments 'vec_t, float'$",
483
+ r"Couldn't find a function 'mul' compatible with the arguments 'vec_t, float'$",
484
484
  ):
485
485
  wp.mul(vec_cls(*a_values), b_value)
486
486
 
487
487
  with test.assertRaisesRegex(
488
488
  RuntimeError,
489
- r"Couldn't find a function 'mul' compatible with " r"the arguments 'tuple, float'$",
489
+ r"Couldn't find a function 'mul' compatible with the arguments 'tuple, float'$",
490
490
  ):
491
491
  wp.mul(wpv(dtype, a_values), b_value)
492
492
 
493
493
  with test.assertRaisesRegex(
494
494
  RuntimeError,
495
- r"Couldn't find a function 'mul' compatible with " r"the arguments 'tuple, float'$",
495
+ r"Couldn't find a function 'mul' compatible with the arguments 'tuple, float'$",
496
496
  ):
497
497
  wp.mul(npv(np_type, a_values), b_value)
498
498
 
499
499
  with test.assertRaisesRegex(
500
500
  RuntimeError,
501
- r"Couldn't find a function 'mul' compatible with " r"the arguments 'ndarray, float'$",
501
+ r"Couldn't find a function 'mul' compatible with the arguments 'ndarray, float'$",
502
502
  ):
503
503
  wp.mul(np.array(npv(np_type, a_values)), b_value)
504
504
 
505
505
  with test.assertRaisesRegex(
506
506
  RuntimeError,
507
- rf"Couldn't find a function 'mul' compatible with " rf"the arguments 'tuple, {dtype.__name__}'$",
507
+ rf"Couldn't find a function 'mul' compatible with the arguments 'tuple, {dtype.__name__}'$",
508
508
  ):
509
509
  wp.mul(a_values, dtype(b_value))
510
510
 
511
511
  with test.assertRaisesRegex(
512
512
  RuntimeError,
513
- rf"Couldn't find a function 'mul' compatible with " rf"the arguments 'tuple, {np_type.__name__}'$",
513
+ rf"Couldn't find a function 'mul' compatible with the arguments 'tuple, {np_type.__name__}'$",
514
514
  ):
515
515
  wp.mul(a_values, nps(np_type, b_value))
516
516
 
@@ -482,7 +482,7 @@ def test_error_unmatched_arguments(test, device):
482
482
  kernel = wp.Kernel(func=kernel_2_fn)
483
483
  with test.assertRaisesRegex(
484
484
  RuntimeError,
485
- r"Input types must be exactly the same, got \[\"vector\(length=2, dtype=<class 'warp.types.float32'>\)\", \"vector\(length=2, dtype=<class 'warp.types.float16'>\)\"\]",
485
+ r"Input types must be exactly the same, got \['vec2f', 'vector\(length=2, dtype=float16\)'\]",
486
486
  ):
487
487
  wp.launch(kernel, dim=1, device=device)
488
488
 
@@ -672,6 +672,27 @@ def test_while_condition_eval():
672
672
  it.valid = False
673
673
 
674
674
 
675
+ @wp.kernel
676
+ def conditional_return_or_sum(result: wp.array(dtype=wp.int32)):
677
+ tid = wp.tid()
678
+
679
+ if tid < 256:
680
+ return
681
+
682
+ wp.atomic_add(result, 0, 1)
683
+
684
+
685
+ def test_codegen_return_in_kernel(test, device):
686
+ result = wp.zeros(1, dtype=wp.int32, device=device)
687
+
688
+ grid_size = 1024
689
+
690
+ # On CUDA devices, this becomes a grid-stride loop
691
+ wp.launch(conditional_return_or_sum, dim=grid_size, inputs=[result], block_dim=256, max_blocks=1, device=device)
692
+
693
+ test.assertEqual(result.numpy()[0], grid_size - 256)
694
+
695
+
675
696
  class TestCodeGen(unittest.TestCase):
676
697
  pass
677
698
 
@@ -803,8 +824,8 @@ add_function_test(
803
824
  add_kernel_test(TestCodeGen, name="test_call_syntax", kernel=test_call_syntax, dim=1, devices=devices)
804
825
  add_kernel_test(TestCodeGen, name="test_shadow_builtin", kernel=test_shadow_builtin, dim=1, devices=devices)
805
826
  add_kernel_test(TestCodeGen, name="test_while_condition_eval", kernel=test_while_condition_eval, dim=1, devices=devices)
806
-
827
+ add_function_test(TestCodeGen, "test_codegen_return_in_kernel", test_codegen_return_in_kernel, devices=devices)
807
828
 
808
829
  if __name__ == "__main__":
809
830
  wp.clear_kernel_cache()
810
- unittest.main(verbosity=2, failfast=True)
831
+ unittest.main(verbosity=2)
@@ -36,6 +36,7 @@ Use "test_timeout" to override the default test timeout threshold of 600 seconds
36
36
  """
37
37
 
38
38
  import os
39
+ import platform
39
40
  import subprocess
40
41
  import sys
41
42
  import unittest
@@ -239,12 +240,21 @@ add_example_test(
239
240
  devices=test_devices,
240
241
  test_options={"usd_required": True, "headless": True},
241
242
  )
242
- add_example_test(
243
- TestCoreExamples,
244
- name="core.example_raymarch",
245
- devices=test_devices,
246
- test_options={"height": 512, "width": 1024, "headless": True},
247
- )
243
+ if platform.system() == "Windows":
244
+ # Skip GPU testing because of obscure NVRTC bug with illegal memory access
245
+ add_example_test(
246
+ TestCoreExamples,
247
+ name="core.example_raymarch",
248
+ devices=[wp.get_device("cpu")],
249
+ test_options={"height": 512, "width": 1024, "headless": True},
250
+ )
251
+ else:
252
+ add_example_test(
253
+ TestCoreExamples,
254
+ name="core.example_raymarch",
255
+ devices=test_devices,
256
+ test_options={"height": 512, "width": 1024, "headless": True},
257
+ )
248
258
  add_example_test(
249
259
  TestCoreExamples,
250
260
  name="core.example_sample_mesh",
warp/tests/test_fem.py CHANGED
@@ -14,6 +14,7 @@
14
14
  # limitations under the License.
15
15
 
16
16
  import math
17
+ import platform
17
18
  import unittest
18
19
  from typing import Any
19
20
 
@@ -475,6 +476,22 @@ def _test_geo_cells(
475
476
  wp.atomic_add(cell_measures, s.element_index, fem.measure(domain, s) * s.qp_weight)
476
477
 
477
478
 
479
+ @fem.integrand(kernel_options={"enable_backward": False})
480
+ def _test_cell_lookup(
481
+ s: fem.Sample,
482
+ domain: fem.Domain,
483
+ ):
484
+ pos = domain(s)
485
+
486
+ s_guess = fem.lookup(domain, pos, s)
487
+ wp.expect_eq(s_guess.element_index, s.element_index)
488
+ wp.expect_near(domain(s_guess), pos, 0.001)
489
+
490
+ s_noguess = fem.lookup(domain, pos)
491
+ wp.expect_eq(s_noguess.element_index, s.element_index)
492
+ wp.expect_near(domain(s_noguess), pos, 0.001)
493
+
494
+
478
495
  @fem.integrand(kernel_options={"enable_backward": False, "max_unroll": 1})
479
496
  def _test_geo_sides(
480
497
  s: fem.Sample,
@@ -527,7 +544,7 @@ def _test_side_normals(
527
544
  wp.expect_near(F_cross[k], nor[k], 0.0001)
528
545
 
529
546
 
530
- def _launch_test_geometry_kernel(geo: fem.Geometry, device):
547
+ def _launch_test_geometry_kernel(geo: fem.Geometry, device, test_cell_lookup: bool = True):
531
548
  cell_measures = wp.zeros(dtype=float, device=device, shape=geo.cell_count())
532
549
  cell_quadrature = fem.RegularQuadrature(fem.Cells(geo), order=2)
533
550
 
@@ -540,6 +557,12 @@ def _launch_test_geometry_kernel(geo: fem.Geometry, device):
540
557
  quadrature=cell_quadrature,
541
558
  values={"cell_measures": cell_measures},
542
559
  )
560
+ if test_cell_lookup:
561
+ fem.interpolate(
562
+ _test_cell_lookup,
563
+ quadrature=cell_quadrature,
564
+ )
565
+
543
566
  fem.interpolate(
544
567
  _test_geo_sides,
545
568
  quadrature=side_quadrature,
@@ -577,7 +600,7 @@ def test_triangle_mesh(test, device):
577
600
  with wp.ScopedDevice(device):
578
601
  positions, tri_vidx = _gen_trimesh(N, N)
579
602
 
580
- geo = fem.Trimesh2D(tri_vertex_indices=tri_vidx, positions=positions)
603
+ geo = fem.Trimesh2D(tri_vertex_indices=tri_vidx, positions=positions, build_bvh=True)
581
604
 
582
605
  test.assertEqual(geo.cell_count(), 2 * (N) ** 2)
583
606
  test.assertEqual(geo.vertex_count(), (N + 1) ** 2)
@@ -595,7 +618,7 @@ def test_triangle_mesh(test, device):
595
618
  positions = np.hstack((positions, np.ones((positions.shape[0], 1))))
596
619
  positions = wp.array(positions, device=device, dtype=wp.vec3)
597
620
 
598
- geo = fem.Trimesh3D(tri_vertex_indices=tri_vidx, positions=positions)
621
+ geo = fem.Trimesh3D(tri_vertex_indices=tri_vidx, positions=positions, build_bvh=True)
599
622
 
600
623
  test.assertEqual(geo.cell_count(), 2 * (N) ** 2)
601
624
  test.assertEqual(geo.vertex_count(), (N + 1) ** 2)
@@ -621,7 +644,7 @@ def test_quad_mesh(test, device):
621
644
  test.assertEqual(geo.side_count(), 2 * (N + 1) * N)
622
645
  test.assertEqual(geo.boundary_side_count(), 4 * N)
623
646
 
624
- side_measures, cell_measures = _launch_test_geometry_kernel(geo, device)
647
+ side_measures, cell_measures = _launch_test_geometry_kernel(geo, device, test_cell_lookup=False)
625
648
 
626
649
  assert_np_equal(side_measures.numpy(), np.full(side_measures.shape, 1.0 / (N)), tol=1.0e-4)
627
650
  assert_np_equal(cell_measures.numpy(), np.full(cell_measures.shape, 1.0 / (N**2)), tol=1.0e-4)
@@ -639,7 +662,7 @@ def test_quad_mesh(test, device):
639
662
  test.assertEqual(geo.side_count(), 2 * (N + 1) * N)
640
663
  test.assertEqual(geo.boundary_side_count(), 4 * N)
641
664
 
642
- side_measures, cell_measures = _launch_test_geometry_kernel(geo, device)
665
+ side_measures, cell_measures = _launch_test_geometry_kernel(geo, device, test_cell_lookup=False)
643
666
 
644
667
  assert_np_equal(side_measures.numpy(), np.full(side_measures.shape, 1.0 / (N)), tol=1.0e-4)
645
668
  assert_np_equal(cell_measures.numpy(), np.full(cell_measures.shape, 1.0 / (N**2)), tol=1.0e-4)
@@ -668,7 +691,7 @@ def test_tet_mesh(test, device):
668
691
  with wp.ScopedDevice(device):
669
692
  positions, tet_vidx = _gen_tetmesh(N, N, N)
670
693
 
671
- geo = fem.Tetmesh(tet_vertex_indices=tet_vidx, positions=positions)
694
+ geo = fem.Tetmesh(tet_vertex_indices=tet_vidx, positions=positions, build_bvh=True)
672
695
 
673
696
  test.assertEqual(geo.cell_count(), 5 * (N) ** 3)
674
697
  test.assertEqual(geo.vertex_count(), (N + 1) ** 3)
@@ -696,7 +719,7 @@ def test_hex_mesh(test, device):
696
719
  test.assertEqual(geo.boundary_side_count(), 6 * N * N)
697
720
  test.assertEqual(geo.edge_count(), 3 * N * (N + 1) ** 2)
698
721
 
699
- side_measures, cell_measures = _launch_test_geometry_kernel(geo, device)
722
+ side_measures, cell_measures = _launch_test_geometry_kernel(geo, device, test_cell_lookup=False)
700
723
 
701
724
  assert_np_equal(side_measures.numpy(), np.full(side_measures.shape, 1.0 / (N**2)), tol=1.0e-4)
702
725
  assert_np_equal(cell_measures.numpy(), np.full(cell_measures.shape, 1.0 / (N**3)), tol=1.0e-4)
@@ -732,6 +755,9 @@ def _refinement_field(x: wp.vec3):
732
755
  def test_adaptive_nanogrid(test, device):
733
756
  # 3 res-1 voxels, 8 res-0 voxels
734
757
 
758
+ if platform.system() == "Windows" or (device.is_cuda and wp.context.runtime.toolkit_version[0] == 11):
759
+ test.skipTest("Skipping test due to NVRTC bug on CUDA 11 and Windows")
760
+
735
761
  res0 = wp.array(
736
762
  [
737
763
  [2, 2, 0],
@@ -756,7 +782,6 @@ def test_adaptive_nanogrid(test, device):
756
782
  dtype=int,
757
783
  device=device,
758
784
  )
759
-
760
785
  grid0 = wp.Volume.allocate_by_voxels(res0, 0.5, device=device)
761
786
  grid1 = wp.Volume.allocate_by_voxels(res1, 1.0, device=device)
762
787
  geo = fem.adaptive_nanogrid_from_hierarchy([grid0, grid1])
@@ -793,15 +818,15 @@ def _rigid_deformation_field(s: Sample, domain: Domain, translation: wp.vec3, ro
793
818
  def test_deformed_geometry(test, device):
794
819
  N = 3
795
820
 
821
+ translation = [1.0, 2.0, 3.0]
822
+ rotation = [0.0, math.pi / 4.0, 0.0]
823
+ scale = 2.0
824
+
796
825
  with wp.ScopedDevice(device):
797
826
  positions, tet_vidx = _gen_tetmesh(N, N, N)
798
827
 
799
828
  geo = fem.Tetmesh(tet_vertex_indices=tet_vidx, positions=positions)
800
829
 
801
- translation = [1.0, 2.0, 3.0]
802
- rotation = [0.0, math.pi / 4.0, 0.0]
803
- scale = 2.0
804
-
805
830
  vector_space = fem.make_polynomial_space(geo, dtype=wp.vec3, degree=2)
806
831
  pos_field = vector_space.make_field()
807
832
  fem.interpolate(
@@ -819,7 +844,7 @@ def test_deformed_geometry(test, device):
819
844
  test.assertEqual(geo.side_count(), 6 * (N + 1) * N**2 + (N**3) * 4)
820
845
  test.assertEqual(geo.boundary_side_count(), 12 * N * N)
821
846
 
822
- side_measures, cell_measures = _launch_test_geometry_kernel(deformed_geo, wp.get_device())
847
+ side_measures, cell_measures = _launch_test_geometry_kernel(deformed_geo, device, test_cell_lookup=False)
823
848
 
824
849
  test.assertAlmostEqual(
825
850
  np.sum(cell_measures.numpy()), scale**3, places=4, msg=f"cell_measures = {cell_measures.numpy()}"
@@ -853,6 +878,56 @@ def test_deformed_geometry(test, device):
853
878
  ],
854
879
  )
855
880
 
881
+
882
+ def test_deformed_geometry_codimensional(test, device):
883
+ N = 3
884
+
885
+ translation = [1.0, 2.0, 3.0]
886
+ rotation = [0.0, math.pi / 4.0, 0.0]
887
+ scale = 2.0
888
+
889
+ with wp.ScopedDevice(device):
890
+ # Test with Trimesh3d (different space and cell dimensions)
891
+ positions, tri_vidx = _gen_trimesh(N, N)
892
+ positions = positions.numpy()
893
+ positions = np.hstack((positions, np.ones((positions.shape[0], 1))))
894
+ positions = wp.array(positions, device=device, dtype=wp.vec3)
895
+
896
+ geo = fem.Trimesh3D(tri_vertex_indices=tri_vidx, positions=positions)
897
+
898
+ vector_space = fem.make_polynomial_space(geo, dtype=wp.vec3, degree=1)
899
+ pos_field = vector_space.make_field()
900
+ fem.interpolate(
901
+ _rigid_deformation_field,
902
+ dest=pos_field,
903
+ values={"translation": translation, "rotation": rotation, "scale": scale},
904
+ )
905
+
906
+ deformed_geo = pos_field.make_deformed_geometry()
907
+
908
+ @wp.kernel
909
+ def _test_deformed_geometry_normal_codimensional(
910
+ geo_arg: geo.CellArg, def_arg: deformed_geo.CellArg, rotation: wp.vec3
911
+ ):
912
+ i = wp.tid()
913
+
914
+ s = make_free_sample(i, Coords(0.5, 0.5, 0.0))
915
+ geo_n = geo.cell_normal(geo_arg, s)
916
+ def_n = deformed_geo.cell_normal(def_arg, s)
917
+
918
+ q = wp.quat_from_axis_angle(wp.normalize(rotation), wp.length(rotation))
919
+ wp.expect_near(wp.quat_rotate(q, geo_n), def_n, 0.001)
920
+
921
+ wp.launch(
922
+ _test_deformed_geometry_normal_codimensional,
923
+ dim=geo.cell_count(),
924
+ inputs=[
925
+ geo.cell_arg_value(wp.get_device()),
926
+ deformed_geo.cell_arg_value(wp.get_device()),
927
+ rotation,
928
+ ],
929
+ )
930
+
856
931
  wp.synchronize()
857
932
 
858
933
 
@@ -1847,7 +1922,7 @@ def test_vector_spaces(test, device):
1847
1922
 
1848
1923
  @wp.kernel
1849
1924
  def test_qr_eigenvalues():
1850
- tol = 1.0e-8
1925
+ tol = 5.0e-7
1851
1926
 
1852
1927
  # zero
1853
1928
  Zero = wp.mat33(0.0)
@@ -1971,6 +2046,9 @@ add_function_test(TestFem, "test_hex_mesh", test_hex_mesh, devices=devices)
1971
2046
  add_function_test(TestFem, "test_nanogrid", test_nanogrid, devices=cuda_devices)
1972
2047
  add_function_test(TestFem, "test_adaptive_nanogrid", test_adaptive_nanogrid, devices=cuda_devices)
1973
2048
  add_function_test(TestFem, "test_deformed_geometry", test_deformed_geometry, devices=devices)
2049
+ add_function_test(
2050
+ TestFem, "test_deformed_geometry_codimensional", test_deformed_geometry_codimensional, devices=devices
2051
+ )
1974
2052
  add_function_test(TestFem, "test_vector_spaces", test_vector_spaces, devices=devices)
1975
2053
  add_function_test(TestFem, "test_dof_mapper", test_dof_mapper)
1976
2054
  add_function_test(TestFem, "test_point_basis", test_point_basis)
@@ -1984,6 +2062,7 @@ class TestFemUtilities(unittest.TestCase):
1984
2062
 
1985
2063
 
1986
2064
  add_kernel_test(TestFemUtilities, test_qr_eigenvalues, dim=1, devices=devices)
2065
+
1987
2066
  add_kernel_test(TestFemUtilities, test_qr_inverse, dim=100, devices=devices)
1988
2067
  add_function_test(TestFemUtilities, "test_array_axpy", test_array_axpy)
1989
2068
 
warp/tests/test_func.py CHANGED
@@ -421,7 +421,7 @@ class TestFunc(unittest.TestCase):
421
421
  b = wp.mat22d(1.0, 2.0, 3.0, 4.0)
422
422
  with self.assertRaisesRegex(
423
423
  RuntimeError,
424
- r"^Couldn't find a function 'mul' compatible with " r"the arguments 'mat22f, mat22d'$",
424
+ r"^Couldn't find a function 'mul' compatible with the arguments 'mat22f, mat22d'$",
425
425
  ):
426
426
  a * b
427
427