warp-lang 1.7.0__py3-none-win_amd64.whl → 1.7.2rc1__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.
- warp/autograd.py +12 -2
- warp/bin/warp-clang.dll +0 -0
- warp/bin/warp.dll +0 -0
- warp/build.py +1 -1
- warp/builtins.py +103 -66
- warp/codegen.py +48 -27
- warp/config.py +1 -1
- warp/context.py +112 -49
- warp/examples/benchmarks/benchmark_cloth.py +1 -1
- warp/examples/distributed/example_jacobi_mpi.py +507 -0
- warp/fem/cache.py +1 -1
- warp/fem/field/field.py +11 -1
- warp/fem/field/nodal_field.py +36 -22
- warp/fem/geometry/adaptive_nanogrid.py +7 -3
- warp/fem/geometry/trimesh.py +4 -12
- warp/jax_experimental/custom_call.py +14 -2
- warp/jax_experimental/ffi.py +100 -67
- warp/native/builtin.h +91 -65
- warp/native/svd.h +59 -49
- warp/native/tile.h +55 -26
- warp/native/volume.cpp +2 -2
- warp/native/volume_builder.cu +33 -22
- warp/native/warp.cu +1 -1
- warp/render/render_opengl.py +41 -34
- warp/render/render_usd.py +96 -6
- warp/sim/collide.py +11 -9
- warp/sim/inertia.py +189 -156
- warp/sim/integrator_euler.py +3 -0
- warp/sim/integrator_xpbd.py +3 -0
- warp/sim/model.py +56 -31
- warp/sim/render.py +4 -0
- warp/sparse.py +1 -1
- warp/stubs.py +73 -25
- warp/tests/assets/torus.usda +1 -1
- warp/tests/cuda/test_streams.py +1 -1
- warp/tests/sim/test_collision.py +237 -206
- warp/tests/sim/test_inertia.py +161 -0
- warp/tests/sim/test_model.py +5 -3
- warp/tests/sim/{flaky_test_sim_grad.py → test_sim_grad.py} +1 -4
- warp/tests/sim/test_xpbd.py +399 -0
- warp/tests/test_array.py +8 -7
- warp/tests/test_atomic.py +181 -2
- warp/tests/test_builtins_resolution.py +38 -38
- warp/tests/test_codegen.py +24 -3
- warp/tests/test_examples.py +16 -6
- warp/tests/test_fem.py +93 -14
- warp/tests/test_func.py +1 -1
- warp/tests/test_mat.py +416 -119
- warp/tests/test_quat.py +321 -137
- warp/tests/test_struct.py +116 -0
- warp/tests/test_vec.py +320 -174
- warp/tests/tile/test_tile.py +27 -0
- warp/tests/tile/test_tile_load.py +124 -0
- warp/tests/unittest_suites.py +2 -5
- warp/types.py +107 -9
- {warp_lang-1.7.0.dist-info → warp_lang-1.7.2rc1.dist-info}/METADATA +41 -19
- {warp_lang-1.7.0.dist-info → warp_lang-1.7.2rc1.dist-info}/RECORD +60 -57
- {warp_lang-1.7.0.dist-info → warp_lang-1.7.2rc1.dist-info}/WHEEL +1 -1
- {warp_lang-1.7.0.dist-info → warp_lang-1.7.2rc1.dist-info}/licenses/LICENSE.md +0 -26
- {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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
warp/tests/test_codegen.py
CHANGED
|
@@ -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 \[
|
|
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
|
|
831
|
+
unittest.main(verbosity=2)
|
warp/tests/test_examples.py
CHANGED
|
@@ -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
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
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,
|
|
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 =
|
|
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
|
|
424
|
+
r"^Couldn't find a function 'mul' compatible with the arguments 'mat22f, mat22d'$",
|
|
425
425
|
):
|
|
426
426
|
a * b
|
|
427
427
|
|