warp-lang 1.3.3__py3-none-manylinux2014_aarch64.whl → 1.4.1__py3-none-manylinux2014_aarch64.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 (110) hide show
  1. warp/__init__.py +6 -0
  2. warp/autograd.py +59 -6
  3. warp/bin/warp.so +0 -0
  4. warp/build_dll.py +8 -10
  5. warp/builtins.py +103 -3
  6. warp/codegen.py +447 -53
  7. warp/config.py +1 -1
  8. warp/context.py +682 -405
  9. warp/dlpack.py +2 -0
  10. warp/examples/benchmarks/benchmark_cloth.py +10 -0
  11. warp/examples/core/example_render_opengl.py +12 -10
  12. warp/examples/fem/example_adaptive_grid.py +251 -0
  13. warp/examples/fem/example_apic_fluid.py +1 -1
  14. warp/examples/fem/example_diffusion_3d.py +2 -2
  15. warp/examples/fem/example_magnetostatics.py +1 -1
  16. warp/examples/fem/example_streamlines.py +1 -0
  17. warp/examples/fem/utils.py +25 -5
  18. warp/examples/sim/example_cloth.py +50 -6
  19. warp/fem/__init__.py +2 -0
  20. warp/fem/adaptivity.py +493 -0
  21. warp/fem/field/field.py +2 -1
  22. warp/fem/field/nodal_field.py +18 -26
  23. warp/fem/field/test.py +4 -4
  24. warp/fem/field/trial.py +4 -4
  25. warp/fem/geometry/__init__.py +1 -0
  26. warp/fem/geometry/adaptive_nanogrid.py +843 -0
  27. warp/fem/geometry/nanogrid.py +55 -28
  28. warp/fem/space/__init__.py +1 -1
  29. warp/fem/space/nanogrid_function_space.py +69 -35
  30. warp/fem/utils.py +118 -107
  31. warp/jax_experimental.py +28 -15
  32. warp/native/array.h +0 -1
  33. warp/native/builtin.h +103 -6
  34. warp/native/bvh.cu +4 -2
  35. warp/native/cuda_util.cpp +14 -0
  36. warp/native/cuda_util.h +2 -0
  37. warp/native/error.cpp +4 -2
  38. warp/native/exports.h +99 -0
  39. warp/native/mat.h +97 -0
  40. warp/native/mesh.cpp +36 -0
  41. warp/native/mesh.cu +52 -1
  42. warp/native/mesh.h +1 -0
  43. warp/native/quat.h +43 -0
  44. warp/native/range.h +11 -2
  45. warp/native/spatial.h +6 -0
  46. warp/native/vec.h +74 -0
  47. warp/native/warp.cpp +2 -1
  48. warp/native/warp.cu +10 -3
  49. warp/native/warp.h +8 -1
  50. warp/paddle.py +382 -0
  51. warp/sim/__init__.py +1 -0
  52. warp/sim/collide.py +519 -0
  53. warp/sim/integrator_euler.py +18 -5
  54. warp/sim/integrator_featherstone.py +5 -5
  55. warp/sim/integrator_vbd.py +1026 -0
  56. warp/sim/integrator_xpbd.py +2 -6
  57. warp/sim/model.py +50 -25
  58. warp/sparse.py +9 -7
  59. warp/stubs.py +459 -0
  60. warp/tape.py +2 -0
  61. warp/tests/aux_test_dependent.py +1 -0
  62. warp/tests/aux_test_name_clash1.py +32 -0
  63. warp/tests/aux_test_name_clash2.py +32 -0
  64. warp/tests/aux_test_square.py +1 -0
  65. warp/tests/test_array.py +188 -0
  66. warp/tests/test_async.py +3 -3
  67. warp/tests/test_atomic.py +6 -0
  68. warp/tests/test_closest_point_edge_edge.py +93 -1
  69. warp/tests/test_codegen.py +93 -15
  70. warp/tests/test_codegen_instancing.py +1457 -0
  71. warp/tests/test_collision.py +486 -0
  72. warp/tests/test_compile_consts.py +3 -28
  73. warp/tests/test_dlpack.py +170 -0
  74. warp/tests/test_examples.py +22 -8
  75. warp/tests/test_fast_math.py +10 -4
  76. warp/tests/test_fem.py +81 -1
  77. warp/tests/test_func.py +46 -0
  78. warp/tests/test_implicit_init.py +49 -0
  79. warp/tests/test_jax.py +58 -0
  80. warp/tests/test_mat.py +84 -0
  81. warp/tests/test_mesh_query_point.py +188 -0
  82. warp/tests/test_model.py +13 -0
  83. warp/tests/test_module_hashing.py +40 -0
  84. warp/tests/test_multigpu.py +3 -3
  85. warp/tests/test_overwrite.py +8 -0
  86. warp/tests/test_paddle.py +852 -0
  87. warp/tests/test_print.py +89 -0
  88. warp/tests/test_quat.py +111 -0
  89. warp/tests/test_reload.py +31 -1
  90. warp/tests/test_scalar_ops.py +2 -0
  91. warp/tests/test_static.py +568 -0
  92. warp/tests/test_streams.py +64 -3
  93. warp/tests/test_struct.py +4 -4
  94. warp/tests/test_torch.py +24 -0
  95. warp/tests/test_triangle_closest_point.py +137 -0
  96. warp/tests/test_types.py +1 -1
  97. warp/tests/test_vbd.py +386 -0
  98. warp/tests/test_vec.py +143 -0
  99. warp/tests/test_vec_scalar_ops.py +139 -0
  100. warp/tests/unittest_suites.py +12 -0
  101. warp/tests/unittest_utils.py +9 -5
  102. warp/thirdparty/dlpack.py +3 -1
  103. warp/types.py +167 -36
  104. warp/utils.py +37 -14
  105. {warp_lang-1.3.3.dist-info → warp_lang-1.4.1.dist-info}/METADATA +10 -8
  106. {warp_lang-1.3.3.dist-info → warp_lang-1.4.1.dist-info}/RECORD +109 -97
  107. warp/tests/test_point_triangle_closest_point.py +0 -143
  108. {warp_lang-1.3.3.dist-info → warp_lang-1.4.1.dist-info}/LICENSE.md +0 -0
  109. {warp_lang-1.3.3.dist-info → warp_lang-1.4.1.dist-info}/WHEEL +0 -0
  110. {warp_lang-1.3.3.dist-info → warp_lang-1.4.1.dist-info}/top_level.txt +0 -0
warp/tests/test_torch.py CHANGED
@@ -382,6 +382,27 @@ def test_array_ctype_from_torch(test, device):
382
382
  wrap_vec_tensor_with_warp_grad(wp.transform)
383
383
 
384
384
 
385
+ def test_cuda_array_interface(test, device):
386
+ # We should be able to construct Torch tensors from Warp arrays via __cuda_array_interface__ on GPU.
387
+ # Note that Torch does not support __array_interface__ on CPU.
388
+
389
+ torch_device = wp.device_to_torch(device)
390
+ n = 10
391
+
392
+ # test the types supported by both Warp and Torch
393
+ scalar_types = [wp.float16, wp.float32, wp.float64, wp.int8, wp.int16, wp.int32, wp.int64, wp.uint8]
394
+
395
+ for dtype in scalar_types:
396
+ # test round trip
397
+ a1 = wp.zeros(n, dtype=dtype, device=device)
398
+ t = torch.tensor(a1, device=torch_device)
399
+ a2 = wp.array(t, device=device)
400
+
401
+ assert a1.dtype == a2.dtype
402
+ assert a1.shape == a2.shape
403
+ assert a1.strides == a2.strides
404
+
405
+
385
406
  def test_to_torch(test, device):
386
407
  import torch
387
408
 
@@ -918,6 +939,9 @@ try:
918
939
  test_warp_graph_torch_stream,
919
940
  devices=torch_compatible_cuda_devices,
920
941
  )
942
+ add_function_test(
943
+ TestTorch, "test_cuda_array_interface", test_cuda_array_interface, devices=torch_compatible_cuda_devices
944
+ )
921
945
 
922
946
  # multi-GPU tests
923
947
  if len(torch_compatible_cuda_devices) > 1:
@@ -0,0 +1,137 @@
1
+ # Copyright (c) 2024 NVIDIA CORPORATION. All rights reserved.
2
+ # NVIDIA CORPORATION and its licensors retain all intellectual property
3
+ # and proprietary rights in and to this software, related documentation
4
+ # and any modifications thereto. Any use, reproduction, disclosure or
5
+ # distribution of this software and related documentation without an express
6
+ # license agreement from NVIDIA CORPORATION is strictly prohibited.
7
+
8
+ import unittest
9
+
10
+ from warp.sim.collide import triangle_closest_point_barycentric
11
+ from warp.tests.unittest_utils import *
12
+
13
+
14
+ # a-b is the edge where the closest point is located at
15
+ @wp.func
16
+ def check_edge_feasible_region(p: wp.vec3, a: wp.vec3, b: wp.vec3, c: wp.vec3, eps: float):
17
+ ap = p - a
18
+ bp = p - b
19
+ ab = b - a
20
+
21
+ if wp.dot(ap, ab) < -eps:
22
+ return False
23
+
24
+ if wp.dot(bp, ab) > eps:
25
+ return False
26
+
27
+ ab_sqr_norm = wp.dot(ab, ab)
28
+ if ab_sqr_norm < eps:
29
+ return False
30
+
31
+ t = wp.dot(ab, c - a) / ab_sqr_norm
32
+
33
+ perpendicular_foot = a + t * ab
34
+
35
+ if wp.dot(c - perpendicular_foot, p - perpendicular_foot) > eps:
36
+ return False
37
+
38
+ return True
39
+
40
+
41
+ # closest point is a
42
+ @wp.func
43
+ def check_vertex_feasible_region(p: wp.vec3, a: wp.vec3, b: wp.vec3, c: wp.vec3, eps: float):
44
+ ap = p - a
45
+ ba = a - b
46
+ ca = a - c
47
+
48
+ if wp.dot(ap, ba) < -eps:
49
+ return False
50
+
51
+ if wp.dot(p, ca) < -eps:
52
+ return False
53
+
54
+ return True
55
+
56
+
57
+ @wp.kernel
58
+ def test_triangle_closest_point_kernel(tri: wp.array(dtype=wp.vec3), passed: wp.array(dtype=wp.bool)):
59
+ state = wp.uint32(wp.rand_init(wp.int32(123), wp.int32(0)))
60
+ eps = 1e-5
61
+
62
+ a = tri[0]
63
+ b = tri[1]
64
+ c = tri[2]
65
+
66
+ for _i in range(1000):
67
+ l = wp.float32(0.0)
68
+ while l < eps:
69
+ p = wp.vec3(wp.randn(state), wp.randn(state), wp.randn(state))
70
+ l = wp.length(p)
71
+
72
+ # project to a sphere with r=2
73
+ p = 2.0 * p / l
74
+
75
+ bary = triangle_closest_point_barycentric(tri[0], tri[1], tri[2], p)
76
+
77
+ for dim in range(3):
78
+ v1_index = (dim + 1) % 3
79
+ v2_index = (dim + 2) % 3
80
+ v1 = tri[v1_index]
81
+ v2 = tri[v2_index]
82
+ v3 = tri[dim]
83
+
84
+ # on edge
85
+ if bary[dim] == 0.0 and bary[v1_index] != 0.0 and bary[v2_index] != 0.0:
86
+ if not check_edge_feasible_region(p, v1, v2, v3, eps):
87
+ passed[0] = False
88
+ return
89
+
90
+ # p-closest_p must be perpendicular to v1-v2
91
+ closest_p = a * bary[0] + b * bary[1] + c * bary[2]
92
+ e = v1 - v2
93
+ err = wp.dot(e, closest_p - p)
94
+ if wp.abs(err) > eps:
95
+ passed[0] = False
96
+ return
97
+
98
+ if bary[v1_index] == 0.0 and bary[v2_index] == 0.0:
99
+ if not check_vertex_feasible_region(p, v3, v1, v2, eps):
100
+ passed[0] = False
101
+ return
102
+
103
+ if bary[dim] != 0.0 and bary[v1_index] != 0.0 and bary[v2_index] != 0.0:
104
+ closest_p = a * bary[0] + b * bary[1] + c * bary[2]
105
+ e1 = v1 - v2
106
+ e2 = v1 - v3
107
+ if wp.abs(wp.dot(e1, closest_p - p)) > eps or wp.abs(wp.dot(e2, closest_p - p)) > eps:
108
+ passed[0] = False
109
+ return
110
+
111
+
112
+ def test_triangle_closest_point(test, device):
113
+ passed = wp.array([True], dtype=wp.bool, device=device)
114
+
115
+ a = wp.vec3(1.0, 0.0, 0.0)
116
+ b = wp.vec3(0.0, 0.0, 0.0)
117
+ c = wp.vec3(0.0, 1.0, 0.0)
118
+
119
+ tri = wp.array([a, b, c], dtype=wp.vec3, device=device)
120
+ wp.launch(test_triangle_closest_point_kernel, dim=1, inputs=[tri, passed], device=device)
121
+ passed = passed.numpy()
122
+
123
+ test.assertTrue(passed.all())
124
+
125
+
126
+ devices = get_test_devices()
127
+
128
+
129
+ class TestTriangleClosestPoint(unittest.TestCase):
130
+ pass
131
+
132
+
133
+ add_function_test(TestTriangleClosestPoint, "test_triangle_closest_point", test_triangle_closest_point, devices=devices)
134
+
135
+ if __name__ == "__main__":
136
+ wp.clear_kernel_cache()
137
+ unittest.main(verbosity=2)
warp/tests/test_types.py CHANGED
@@ -215,7 +215,7 @@ class TestTypes(unittest.TestCase):
215
215
  self.assertEqual(const, wp.vec3i(1, 2, 3))
216
216
 
217
217
  def test_constant_error_invalid_type(self):
218
- with self.assertRaisesRegex(RuntimeError, r"Invalid constant type: <class 'tuple'>$"):
218
+ with self.assertRaisesRegex(TypeError, r"Invalid constant type: <class 'tuple'>$"):
219
219
  wp.constant((1, 2, 3))
220
220
 
221
221
  def test_vector_assign(self):
warp/tests/test_vbd.py ADDED
@@ -0,0 +1,386 @@
1
+ # Copyright (c) 2024 NVIDIA CORPORATION. All rights reserved.
2
+ # NVIDIA CORPORATION and its licensors retain all intellectual property
3
+ # and proprietary rights in and to this software, related documentation
4
+ # and any modifications thereto. Any use, reproduction, disclosure or
5
+ # distribution of this software and related documentation without an express
6
+ # license agreement from NVIDIA CORPORATION is strictly prohibited.
7
+
8
+ import unittest
9
+
10
+ import warp as wp
11
+ import warp.optim
12
+ import warp.sim
13
+ from warp.sim.model import (
14
+ PARTICLE_FLAG_ACTIVE,
15
+ )
16
+ from warp.tests.unittest_utils import *
17
+
18
+
19
+ class VBDClothSim:
20
+ def __init__(self, device):
21
+ # fmt: off
22
+ self.pts = [
23
+ (-50.0000000, 0.0000000, -50.0000000),
24
+ (-38.8888893, 11.1111107, -50.0000000),
25
+ (-27.7777786, 22.2222214, -50.0000000),
26
+ (-16.6666679, 33.3333321, -50.0000000),
27
+ (-5.5555558, 44.4444427, -50.0000000),
28
+ (5.5555558, 55.5555573, -50.0000000),
29
+ (16.6666679, 66.6666641, -50.0000000),
30
+ (27.7777786, 77.7777786, -50.0000000),
31
+ (38.8888893, 88.8888855, -50.0000000),
32
+ (50.0000000, 100.0000000, -50.0000000),
33
+ (-50.0000000, 0.0000000, -38.8888893),
34
+ (-38.8888893, 11.1111107, -38.8888893),
35
+ (-27.7777786, 22.2222214, -38.8888893),
36
+ (-16.6666679, 33.3333321, -38.8888893),
37
+ (-5.5555558, 44.4444427, -38.8888893),
38
+ (5.5555558, 55.5555573, -38.8888893),
39
+ (16.6666679, 66.6666641, -38.8888893),
40
+ (27.7777786, 77.7777786, -38.8888893),
41
+ (38.8888893, 88.8888855, -38.8888893),
42
+ (50.0000000, 100.0000000, -38.8888893),
43
+ (-50.0000000, 0.0000000, -27.7777786),
44
+ (-38.8888893, 11.1111107, -27.7777786),
45
+ (-27.7777786, 22.2222214, -27.7777786),
46
+ (-16.6666679, 33.3333321, -27.7777786),
47
+ (-5.5555558, 44.4444427, -27.7777786),
48
+ (5.5555558, 55.5555573, -27.7777786),
49
+ (16.6666679, 66.6666641, -27.7777786),
50
+ (27.7777786, 77.7777786, -27.7777786),
51
+ (38.8888893, 88.8888855, -27.7777786),
52
+ (50.0000000, 100.0000000, -27.7777786),
53
+ (-50.0000000, 0.0000000, -16.6666679),
54
+ (-38.8888893, 11.1111107, -16.6666679),
55
+ (-27.7777786, 22.2222214, -16.6666679),
56
+ (-16.6666679, 33.3333321, -16.6666679),
57
+ (-5.5555558, 44.4444427, -16.6666679),
58
+ (5.5555558, 55.5555573, -16.6666679),
59
+ (16.6666679, 66.6666641, -16.6666679),
60
+ (27.7777786, 77.7777786, -16.6666679),
61
+ (38.8888893, 88.8888855, -16.6666679),
62
+ (50.0000000, 100.0000000, -16.6666679),
63
+ (-50.0000000, 0.0000000, -5.5555558),
64
+ (-38.8888893, 11.1111107, -5.5555558),
65
+ (-27.7777786, 22.2222214, -5.5555558),
66
+ (-16.6666679, 33.3333321, -5.5555558),
67
+ (-5.5555558, 44.4444427, -5.5555558),
68
+ (5.5555558, 55.5555573, -5.5555558),
69
+ (16.6666679, 66.6666641, -5.5555558),
70
+ (27.7777786, 77.7777786, -5.5555558),
71
+ (38.8888893, 88.8888855, -5.5555558),
72
+ (50.0000000, 100.0000000, -5.5555558),
73
+ (-50.0000000, 0.0000000, 5.5555558),
74
+ (-38.8888893, 11.1111107, 5.5555558),
75
+ (-27.7777786, 22.2222214, 5.5555558),
76
+ (-16.6666679, 33.3333321, 5.5555558),
77
+ (-5.5555558, 44.4444427, 5.5555558),
78
+ (5.5555558, 55.5555573, 5.5555558),
79
+ (16.6666679, 66.6666641, 5.5555558),
80
+ (27.7777786, 77.7777786, 5.5555558),
81
+ (38.8888893, 88.8888855, 5.5555558),
82
+ (50.0000000, 100.0000000, 5.5555558),
83
+ (-50.0000000, 0.0000000, 16.6666679),
84
+ (-38.8888893, 11.1111107, 16.6666679),
85
+ (-27.7777786, 22.2222214, 16.6666679),
86
+ (-16.6666679, 33.3333321, 16.6666679),
87
+ (-5.5555558, 44.4444427, 16.6666679),
88
+ (5.5555558, 55.5555573, 16.6666679),
89
+ (16.6666679, 66.6666641, 16.6666679),
90
+ (27.7777786, 77.7777786, 16.6666679),
91
+ (38.8888893, 88.8888855, 16.6666679),
92
+ (50.0000000, 100.0000000, 16.6666679),
93
+ (-50.0000000, 0.0000000, 27.7777786),
94
+ (-38.8888893, 11.1111107, 27.7777786),
95
+ (-27.7777786, 22.2222214, 27.7777786),
96
+ (-16.6666679, 33.3333321, 27.7777786),
97
+ (-5.5555558, 44.4444427, 27.7777786),
98
+ (5.5555558, 55.5555573, 27.7777786),
99
+ (16.6666679, 66.6666641, 27.7777786),
100
+ (27.7777786, 77.7777786, 27.7777786),
101
+ (38.8888893, 88.8888855, 27.7777786),
102
+ (50.0000000, 100.0000000, 27.7777786),
103
+ (-50.0000000, 0.0000000, 38.8888893),
104
+ (-38.8888893, 11.1111107, 38.8888893),
105
+ (-27.7777786, 22.2222214, 38.8888893),
106
+ (-16.6666679, 33.3333321, 38.8888893),
107
+ (-5.5555558, 44.4444427, 38.8888893),
108
+ (5.5555558, 55.5555573, 38.8888893),
109
+ (16.6666679, 66.6666641, 38.8888893),
110
+ (27.7777786, 77.7777786, 38.8888893),
111
+ (38.8888893, 88.8888855, 38.8888893),
112
+ (50.0000000, 100.0000000, 38.8888893),
113
+ (-50.0000000, 0.0000000, 50.0000000),
114
+ (-38.8888893, 11.1111107, 50.0000000),
115
+ (-27.7777786, 22.2222214, 50.0000000),
116
+ (-16.6666679, 33.3333321, 50.0000000),
117
+ (-5.5555558, 44.4444427, 50.0000000),
118
+ (5.5555558, 55.5555573, 50.0000000),
119
+ (16.6666679, 66.6666641, 50.0000000),
120
+ (27.7777786, 77.7777786, 50.0000000),
121
+ (38.8888893, 88.8888855, 50.0000000),
122
+ (50.0000000, 100.0000000, 50.0000000),
123
+ ]
124
+
125
+ self.faces = [
126
+ 1, 12, 2,
127
+ 1, 11, 12,
128
+ 2, 12, 3,
129
+ 12, 13, 3,
130
+ 3, 14, 4,
131
+ 3, 13, 14,
132
+ 4, 14, 5,
133
+ 14, 15, 5,
134
+ 5, 16, 6,
135
+ 5, 15, 16,
136
+ 6, 16, 7,
137
+ 16, 17, 7,
138
+ 7, 18, 8,
139
+ 7, 17, 18,
140
+ 8, 18, 9,
141
+ 18, 19, 9,
142
+ 9, 20, 10,
143
+ 9, 19, 20,
144
+ 11, 21, 12,
145
+ 21, 22, 12,
146
+ 12, 23, 13,
147
+ 12, 22, 23,
148
+ 13, 23, 14,
149
+ 23, 24, 14,
150
+ 14, 25, 15,
151
+ 14, 24, 25,
152
+ 15, 25, 16,
153
+ 25, 26, 16,
154
+ 16, 27, 17,
155
+ 16, 26, 27,
156
+ 17, 27, 18,
157
+ 27, 28, 18,
158
+ 18, 29, 19,
159
+ 18, 28, 29,
160
+ 19, 29, 20,
161
+ 29, 30, 20,
162
+ 21, 32, 22,
163
+ 21, 31, 32,
164
+ 22, 32, 23,
165
+ 32, 33, 23,
166
+ 23, 34, 24,
167
+ 23, 33, 34,
168
+ 24, 34, 25,
169
+ 34, 35, 25,
170
+ 25, 36, 26,
171
+ 25, 35, 36,
172
+ 26, 36, 27,
173
+ 36, 37, 27,
174
+ 27, 38, 28,
175
+ 27, 37, 38,
176
+ 28, 38, 29,
177
+ 38, 39, 29,
178
+ 29, 40, 30,
179
+ 29, 39, 40,
180
+ 31, 41, 32,
181
+ 41, 42, 32,
182
+ 32, 43, 33,
183
+ 32, 42, 43,
184
+ 33, 43, 34,
185
+ 43, 44, 34,
186
+ 34, 45, 35,
187
+ 34, 44, 45,
188
+ 35, 45, 36,
189
+ 45, 46, 36,
190
+ 36, 47, 37,
191
+ 36, 46, 47,
192
+ 37, 47, 38,
193
+ 47, 48, 38,
194
+ 38, 49, 39,
195
+ 38, 48, 49,
196
+ 39, 49, 40,
197
+ 49, 50, 40,
198
+ 41, 52, 42,
199
+ 41, 51, 52,
200
+ 42, 52, 43,
201
+ 52, 53, 43,
202
+ 43, 54, 44,
203
+ 43, 53, 54,
204
+ 44, 54, 45,
205
+ 54, 55, 45,
206
+ 45, 56, 46,
207
+ 45, 55, 56,
208
+ 46, 56, 47,
209
+ 56, 57, 47,
210
+ 47, 58, 48,
211
+ 47, 57, 58,
212
+ 48, 58, 49,
213
+ 58, 59, 49,
214
+ 49, 60, 50,
215
+ 49, 59, 60,
216
+ 51, 61, 52,
217
+ 61, 62, 52,
218
+ 52, 63, 53,
219
+ 52, 62, 63,
220
+ 53, 63, 54,
221
+ 63, 64, 54,
222
+ 54, 65, 55,
223
+ 54, 64, 65,
224
+ 55, 65, 56,
225
+ 65, 66, 56,
226
+ 56, 67, 57,
227
+ 56, 66, 67,
228
+ 57, 67, 58,
229
+ 67, 68, 58,
230
+ 58, 69, 59,
231
+ 58, 68, 69,
232
+ 59, 69, 60,
233
+ 69, 70, 60,
234
+ 61, 72, 62,
235
+ 61, 71, 72,
236
+ 62, 72, 63,
237
+ 72, 73, 63,
238
+ 63, 74, 64,
239
+ 63, 73, 74,
240
+ 64, 74, 65,
241
+ 74, 75, 65,
242
+ 65, 76, 66,
243
+ 65, 75, 76,
244
+ 66, 76, 67,
245
+ 76, 77, 67,
246
+ 67, 78, 68,
247
+ 67, 77, 78,
248
+ 68, 78, 69,
249
+ 78, 79, 69,
250
+ 69, 80, 70,
251
+ 69, 79, 80,
252
+ 71, 81, 72,
253
+ 81, 82, 72,
254
+ 72, 83, 73,
255
+ 72, 82, 83,
256
+ 73, 83, 74,
257
+ 83, 84, 74,
258
+ 74, 85, 75,
259
+ 74, 84, 85,
260
+ 75, 85, 76,
261
+ 85, 86, 76,
262
+ 76, 87, 77,
263
+ 76, 86, 87,
264
+ 77, 87, 78,
265
+ 87, 88, 78,
266
+ 78, 89, 79,
267
+ 78, 88, 89,
268
+ 79, 89, 80,
269
+ 89, 90, 80,
270
+ 81, 92, 82,
271
+ 81, 91, 92,
272
+ 82, 92, 83,
273
+ 92, 93, 83,
274
+ 83, 94, 84,
275
+ 83, 93, 94,
276
+ 84, 94, 85,
277
+ 94, 95, 85,
278
+ 85, 96, 86,
279
+ 85, 95, 96,
280
+ 86, 96, 87,
281
+ 96, 97, 87,
282
+ 87, 98, 88,
283
+ 87, 97, 98,
284
+ 88, 98, 89,
285
+ 98, 99, 89,
286
+ 89, 100, 90,
287
+ 89, 99, 100
288
+ ]
289
+
290
+ self.coloring = [
291
+ [9, 12, 17, 24, 31, 38, 43, 46, 50, 62, 65, 68, 80, 84, 89, 92],
292
+ [6, 20, 25, 32, 37, 44, 51, 56, 59, 63, 70, 75, 82, 88, 90, 94, 96],
293
+ [2, 8, 10, 14, 26, 29, 33, 40, 48, 52, 55, 67, 73, 79, 86, 91, 98],
294
+ [4, 11, 16, 23, 28, 30, 35, 42, 49, 54, 57, 71, 74, 76, 78, 93, 97],
295
+ [3, 15, 18, 22, 34, 36, 39, 41, 53, 58, 60, 66, 72, 85, 99, 0, 87],
296
+ [7, 21, 27, 45, 47, 61, 64, 69, 77, 81, 83, 95, 1, 5, 13, 19],
297
+ ]
298
+ # fmt: on
299
+
300
+ self.dt = 1 / 60
301
+ self.num_test_frames = 100
302
+ self.num_substeps = 10
303
+ self.iterations = 10
304
+
305
+ stiffness = 1e5
306
+ kd = 1.0e-7
307
+
308
+ self.input_scale_factor = 1.0
309
+ self.renderer_scale_factor = 0.01
310
+ vertices = [wp.vec3(v) * self.input_scale_factor for v in self.pts]
311
+ fs_flatten = [fv - 1 for fv in self.faces]
312
+
313
+ builder = wp.sim.ModelBuilder()
314
+ builder.add_cloth_mesh(
315
+ pos=wp.vec3(0.0, 200.0, 0.0),
316
+ rot=wp.quat_from_axis_angle(wp.vec3(1.0, 0.0, 0.0), 0.0),
317
+ scale=1.0,
318
+ vertices=vertices,
319
+ indices=fs_flatten,
320
+ vel=wp.vec3(0.0, 0.0, 0.0),
321
+ density=0.02,
322
+ tri_ke=stiffness,
323
+ tri_ka=stiffness,
324
+ tri_kd=kd,
325
+ )
326
+
327
+ self.model = builder.finalize(device=device)
328
+ self.model.ground = True
329
+ self.model.gravity = wp.vec3(0, -1000.0, 0)
330
+
331
+ self.model.soft_contact_ke = 1.0e4
332
+ self.model.soft_contact_kd = 1.0e2
333
+
334
+ coloring_wp = []
335
+ for color in self.coloring:
336
+ coloring_wp.append(wp.array(color, dtype=wp.int32, device=self.model.device))
337
+ self.model.coloring = coloring_wp
338
+
339
+ self.dt = self.dt / self.num_substeps
340
+ self.fixed_particles = [0, 9]
341
+
342
+ self.set_points_fixed(self.model, self.fixed_particles)
343
+
344
+ self.integrator = wp.sim.VBDIntegrator(self.model, self.iterations)
345
+ self.state0 = self.model.state()
346
+ self.state1 = self.model.state()
347
+
348
+ self.init_pos = np.array(self.state0.particle_q.numpy(), copy=True)
349
+
350
+ def run(self, test):
351
+ for _step in range(self.num_substeps * self.num_test_frames):
352
+ self.integrator.simulate(self.model, self.state0, self.state1, self.dt, None)
353
+ (self.state0, self.state1) = (self.state1, self.state0)
354
+
355
+ # examine that the simulation does not explode
356
+ final_pos = self.state0.particle_q.numpy()
357
+ test.assertTrue((final_pos < 1e5).all())
358
+ # examine that the simulation have moved
359
+ test.assertTrue((self.init_pos != final_pos).any())
360
+
361
+ def set_points_fixed(self, model, fixed_particles):
362
+ if len(fixed_particles):
363
+ flags = model.particle_flags.numpy()
364
+ for fixed_v_id in fixed_particles:
365
+ flags[fixed_v_id] = wp.uint32(int(flags[fixed_v_id]) & ~int(PARTICLE_FLAG_ACTIVE))
366
+
367
+ model.particle_flags = wp.array(flags, device=model.device)
368
+
369
+
370
+ def test_vbd_cloth(test, device):
371
+ example = VBDClothSim(device)
372
+ example.run(test)
373
+
374
+
375
+ devices = get_test_devices()
376
+
377
+
378
+ class TestVBD(unittest.TestCase):
379
+ pass
380
+
381
+
382
+ add_function_test(TestVBD, "test_vbd_cloth", test_vbd_cloth, devices=devices)
383
+
384
+ if __name__ == "__main__":
385
+ wp.clear_kernel_cache()
386
+ unittest.main(verbosity=2)