warp-lang 0.11.0__py3-none-manylinux2014_x86_64.whl → 1.0.0__py3-none-manylinux2014_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of warp-lang might be problematic. Click here for more details.

Files changed (170) hide show
  1. warp/__init__.py +8 -0
  2. warp/bin/warp-clang.so +0 -0
  3. warp/bin/warp.so +0 -0
  4. warp/build.py +7 -6
  5. warp/build_dll.py +70 -79
  6. warp/builtins.py +10 -6
  7. warp/codegen.py +51 -19
  8. warp/config.py +7 -8
  9. warp/constants.py +3 -0
  10. warp/context.py +948 -245
  11. warp/dlpack.py +198 -113
  12. warp/examples/assets/bunny.usd +0 -0
  13. warp/examples/assets/cartpole.urdf +110 -0
  14. warp/examples/assets/crazyflie.usd +0 -0
  15. warp/examples/assets/cube.usda +42 -0
  16. warp/examples/assets/nv_ant.xml +92 -0
  17. warp/examples/assets/nv_humanoid.xml +183 -0
  18. warp/examples/assets/quadruped.urdf +268 -0
  19. warp/examples/assets/rocks.nvdb +0 -0
  20. warp/examples/assets/rocks.usd +0 -0
  21. warp/examples/assets/sphere.usda +56 -0
  22. warp/examples/assets/torus.usda +105 -0
  23. warp/examples/benchmarks/benchmark_api.py +383 -0
  24. warp/examples/benchmarks/benchmark_cloth.py +279 -0
  25. warp/examples/benchmarks/benchmark_cloth_cupy.py +88 -0
  26. warp/examples/benchmarks/benchmark_cloth_jax.py +100 -0
  27. warp/examples/benchmarks/benchmark_cloth_numba.py +142 -0
  28. warp/examples/benchmarks/benchmark_cloth_numpy.py +77 -0
  29. warp/examples/benchmarks/benchmark_cloth_pytorch.py +86 -0
  30. warp/examples/benchmarks/benchmark_cloth_taichi.py +112 -0
  31. warp/examples/benchmarks/benchmark_cloth_warp.py +146 -0
  32. warp/examples/benchmarks/benchmark_launches.py +295 -0
  33. warp/examples/core/example_dem.py +221 -0
  34. warp/examples/core/example_fluid.py +267 -0
  35. warp/examples/core/example_graph_capture.py +129 -0
  36. warp/examples/core/example_marching_cubes.py +177 -0
  37. warp/examples/core/example_mesh.py +154 -0
  38. warp/examples/core/example_mesh_intersect.py +193 -0
  39. warp/examples/core/example_nvdb.py +169 -0
  40. warp/examples/core/example_raycast.py +89 -0
  41. warp/examples/core/example_raymarch.py +178 -0
  42. warp/examples/core/example_render_opengl.py +141 -0
  43. warp/examples/core/example_sph.py +389 -0
  44. warp/examples/core/example_torch.py +181 -0
  45. warp/examples/core/example_wave.py +249 -0
  46. warp/examples/fem/bsr_utils.py +380 -0
  47. warp/examples/fem/example_apic_fluid.py +391 -0
  48. warp/examples/fem/example_convection_diffusion.py +168 -0
  49. warp/examples/fem/example_convection_diffusion_dg.py +209 -0
  50. warp/examples/fem/example_convection_diffusion_dg0.py +194 -0
  51. warp/examples/fem/example_deformed_geometry.py +159 -0
  52. warp/examples/fem/example_diffusion.py +173 -0
  53. warp/examples/fem/example_diffusion_3d.py +152 -0
  54. warp/examples/fem/example_diffusion_mgpu.py +214 -0
  55. warp/examples/fem/example_mixed_elasticity.py +222 -0
  56. warp/examples/fem/example_navier_stokes.py +243 -0
  57. warp/examples/fem/example_stokes.py +192 -0
  58. warp/examples/fem/example_stokes_transfer.py +249 -0
  59. warp/examples/fem/mesh_utils.py +109 -0
  60. warp/examples/fem/plot_utils.py +287 -0
  61. warp/examples/optim/example_bounce.py +248 -0
  62. warp/examples/optim/example_cloth_throw.py +210 -0
  63. warp/examples/optim/example_diffray.py +535 -0
  64. warp/examples/optim/example_drone.py +850 -0
  65. warp/examples/optim/example_inverse_kinematics.py +169 -0
  66. warp/examples/optim/example_inverse_kinematics_torch.py +170 -0
  67. warp/examples/optim/example_spring_cage.py +234 -0
  68. warp/examples/optim/example_trajectory.py +201 -0
  69. warp/examples/sim/example_cartpole.py +128 -0
  70. warp/examples/sim/example_cloth.py +184 -0
  71. warp/examples/sim/example_granular.py +113 -0
  72. warp/examples/sim/example_granular_collision_sdf.py +185 -0
  73. warp/examples/sim/example_jacobian_ik.py +213 -0
  74. warp/examples/sim/example_particle_chain.py +106 -0
  75. warp/examples/sim/example_quadruped.py +179 -0
  76. warp/examples/sim/example_rigid_chain.py +191 -0
  77. warp/examples/sim/example_rigid_contact.py +176 -0
  78. warp/examples/sim/example_rigid_force.py +126 -0
  79. warp/examples/sim/example_rigid_gyroscopic.py +97 -0
  80. warp/examples/sim/example_rigid_soft_contact.py +124 -0
  81. warp/examples/sim/example_soft_body.py +178 -0
  82. warp/fabric.py +29 -20
  83. warp/fem/cache.py +0 -1
  84. warp/fem/dirichlet.py +0 -2
  85. warp/fem/integrate.py +0 -1
  86. warp/jax.py +45 -0
  87. warp/jax_experimental.py +339 -0
  88. warp/native/builtin.h +12 -0
  89. warp/native/bvh.cu +18 -18
  90. warp/native/clang/clang.cpp +8 -3
  91. warp/native/cuda_util.cpp +94 -5
  92. warp/native/cuda_util.h +35 -6
  93. warp/native/cutlass_gemm.cpp +1 -1
  94. warp/native/cutlass_gemm.cu +4 -1
  95. warp/native/error.cpp +66 -0
  96. warp/native/error.h +27 -0
  97. warp/native/mesh.cu +2 -2
  98. warp/native/reduce.cu +4 -4
  99. warp/native/runlength_encode.cu +2 -2
  100. warp/native/scan.cu +2 -2
  101. warp/native/sparse.cu +0 -1
  102. warp/native/temp_buffer.h +2 -2
  103. warp/native/warp.cpp +95 -60
  104. warp/native/warp.cu +1053 -218
  105. warp/native/warp.h +49 -32
  106. warp/optim/linear.py +33 -16
  107. warp/render/render_opengl.py +202 -101
  108. warp/render/render_usd.py +82 -40
  109. warp/sim/__init__.py +13 -4
  110. warp/sim/articulation.py +4 -5
  111. warp/sim/collide.py +320 -175
  112. warp/sim/import_mjcf.py +25 -30
  113. warp/sim/import_urdf.py +94 -63
  114. warp/sim/import_usd.py +51 -36
  115. warp/sim/inertia.py +3 -2
  116. warp/sim/integrator.py +233 -0
  117. warp/sim/integrator_euler.py +447 -469
  118. warp/sim/integrator_featherstone.py +1991 -0
  119. warp/sim/integrator_xpbd.py +1420 -640
  120. warp/sim/model.py +765 -487
  121. warp/sim/particles.py +2 -1
  122. warp/sim/render.py +35 -13
  123. warp/sim/utils.py +222 -11
  124. warp/stubs.py +8 -0
  125. warp/tape.py +16 -1
  126. warp/tests/aux_test_grad_customs.py +23 -0
  127. warp/tests/test_array.py +190 -1
  128. warp/tests/test_async.py +656 -0
  129. warp/tests/test_bool.py +50 -0
  130. warp/tests/test_dlpack.py +164 -11
  131. warp/tests/test_examples.py +166 -74
  132. warp/tests/test_fem.py +8 -1
  133. warp/tests/test_generics.py +15 -5
  134. warp/tests/test_grad.py +1 -1
  135. warp/tests/test_grad_customs.py +172 -12
  136. warp/tests/test_jax.py +254 -0
  137. warp/tests/test_large.py +29 -6
  138. warp/tests/test_launch.py +25 -0
  139. warp/tests/test_linear_solvers.py +20 -3
  140. warp/tests/test_matmul.py +61 -16
  141. warp/tests/test_matmul_lite.py +13 -13
  142. warp/tests/test_mempool.py +186 -0
  143. warp/tests/test_multigpu.py +3 -0
  144. warp/tests/test_options.py +16 -2
  145. warp/tests/test_peer.py +137 -0
  146. warp/tests/test_print.py +3 -1
  147. warp/tests/test_quat.py +23 -0
  148. warp/tests/test_sim_kinematics.py +97 -0
  149. warp/tests/test_snippet.py +126 -3
  150. warp/tests/test_streams.py +108 -79
  151. warp/tests/test_torch.py +16 -8
  152. warp/tests/test_utils.py +32 -27
  153. warp/tests/test_verify_fp.py +65 -0
  154. warp/tests/test_volume.py +1 -1
  155. warp/tests/unittest_serial.py +2 -0
  156. warp/tests/unittest_suites.py +12 -0
  157. warp/tests/unittest_utils.py +14 -7
  158. warp/thirdparty/unittest_parallel.py +15 -3
  159. warp/torch.py +10 -8
  160. warp/types.py +363 -246
  161. warp/utils.py +143 -19
  162. warp_lang-1.0.0.dist-info/LICENSE.md +126 -0
  163. warp_lang-1.0.0.dist-info/METADATA +394 -0
  164. {warp_lang-0.11.0.dist-info → warp_lang-1.0.0.dist-info}/RECORD +167 -86
  165. warp/sim/optimizer.py +0 -138
  166. warp_lang-0.11.0.dist-info/LICENSE.md +0 -36
  167. warp_lang-0.11.0.dist-info/METADATA +0 -238
  168. /warp/tests/{walkthough_debug.py → walkthrough_debug.py} +0 -0
  169. {warp_lang-0.11.0.dist-info → warp_lang-1.0.0.dist-info}/WHEEL +0 -0
  170. {warp_lang-0.11.0.dist-info → warp_lang-1.0.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,146 @@
1
+ # Copyright (c) 2022 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 warp as wp
9
+
10
+ wp.init()
11
+ wp.build.clear_kernel_cache()
12
+
13
+
14
+ @wp.kernel
15
+ def eval_springs(
16
+ x: wp.array(dtype=wp.vec3),
17
+ v: wp.array(dtype=wp.vec3),
18
+ spring_indices: wp.array(dtype=int),
19
+ spring_rest_lengths: wp.array(dtype=float),
20
+ spring_stiffness: wp.array(dtype=float),
21
+ spring_damping: wp.array(dtype=float),
22
+ f: wp.array(dtype=wp.vec3),
23
+ ):
24
+ tid = wp.tid()
25
+
26
+ i = spring_indices[tid * 2 + 0]
27
+ j = spring_indices[tid * 2 + 1]
28
+
29
+ ke = spring_stiffness[tid]
30
+ kd = spring_damping[tid]
31
+ rest = spring_rest_lengths[tid]
32
+
33
+ xi = x[i]
34
+ xj = x[j]
35
+
36
+ vi = v[i]
37
+ vj = v[j]
38
+
39
+ xij = xi - xj
40
+ vij = vi - vj
41
+
42
+ l = wp.length(xij)
43
+ l_inv = 1.0 / l
44
+
45
+ # normalized spring direction
46
+ dir = xij * l_inv
47
+
48
+ c = l - rest
49
+ dcdt = wp.dot(dir, vij)
50
+
51
+ # damping based on relative velocity.
52
+ fs = dir * (ke * c + kd * dcdt)
53
+
54
+ wp.atomic_sub(f, i, fs)
55
+ wp.atomic_add(f, j, fs)
56
+
57
+
58
+ @wp.kernel
59
+ def integrate_particles(
60
+ x: wp.array(dtype=wp.vec3),
61
+ v: wp.array(dtype=wp.vec3),
62
+ f: wp.array(dtype=wp.vec3),
63
+ w: wp.array(dtype=float),
64
+ dt: float,
65
+ ):
66
+ tid = wp.tid()
67
+
68
+ x0 = x[tid]
69
+ v0 = v[tid]
70
+ f0 = f[tid]
71
+ inv_mass = w[tid]
72
+
73
+ g = wp.vec3()
74
+
75
+ # treat particles with inv_mass == 0 as kinematic
76
+ if inv_mass > 0.0:
77
+ g = wp.vec3(0.0, 0.0 - 9.81, 0.0)
78
+
79
+ # simple semi-implicit Euler. v1 = v0 + a dt, x1 = x0 + v1 dt
80
+ v1 = v0 + (f0 * inv_mass + g) * dt
81
+ x1 = x0 + v1 * dt
82
+
83
+ x[tid] = x1
84
+ v[tid] = v1
85
+
86
+ # clear forces
87
+ f[tid] = wp.vec3()
88
+
89
+
90
+ class WpIntegrator:
91
+ def __init__(self, cloth, device):
92
+ self.device = wp.get_device(device)
93
+
94
+ with wp.ScopedDevice(self.device):
95
+ self.positions = wp.from_numpy(cloth.positions, dtype=wp.vec3)
96
+ self.positions_host = wp.from_numpy(cloth.positions, dtype=wp.vec3, device="cpu")
97
+ self.invmass = wp.from_numpy(cloth.inv_masses, dtype=float)
98
+
99
+ self.velocities = wp.zeros(cloth.num_particles, dtype=wp.vec3)
100
+ self.forces = wp.zeros(cloth.num_particles, dtype=wp.vec3)
101
+
102
+ self.spring_indices = wp.from_numpy(cloth.spring_indices, dtype=int)
103
+ self.spring_lengths = wp.from_numpy(cloth.spring_lengths, dtype=float)
104
+ self.spring_stiffness = wp.from_numpy(cloth.spring_stiffness, dtype=float)
105
+ self.spring_damping = wp.from_numpy(cloth.spring_damping, dtype=float)
106
+
107
+ self.cloth = cloth
108
+
109
+ def simulate(self, dt, substeps):
110
+ sim_dt = dt / substeps
111
+
112
+ for s in range(substeps):
113
+ wp.launch(
114
+ kernel=eval_springs,
115
+ dim=self.cloth.num_springs,
116
+ inputs=[
117
+ self.positions,
118
+ self.velocities,
119
+ self.spring_indices,
120
+ self.spring_lengths,
121
+ self.spring_stiffness,
122
+ self.spring_damping,
123
+ self.forces,
124
+ ],
125
+ outputs=[],
126
+ device=self.device,
127
+ )
128
+
129
+ # integrate
130
+ wp.launch(
131
+ kernel=integrate_particles,
132
+ dim=self.cloth.num_particles,
133
+ inputs=[self.positions, self.velocities, self.forces, self.invmass, sim_dt],
134
+ outputs=[],
135
+ device=self.device,
136
+ )
137
+
138
+ # copy data back to host
139
+ if self.device.is_cuda:
140
+ wp.copy(self.positions_host, self.positions)
141
+ wp.synchronize()
142
+
143
+ return self.positions_host.numpy()
144
+
145
+ else:
146
+ return self.positions.numpy()
@@ -0,0 +1,295 @@
1
+ # Copyright (c) 2023 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
+ ###########################################################################
9
+ # Benchmarks for kernel launches with different types of args
10
+ ###########################################################################
11
+
12
+ import warp as wp
13
+
14
+
15
+ @wp.struct
16
+ class S0:
17
+ pass
18
+
19
+
20
+ @wp.struct
21
+ class Sf:
22
+ x: float
23
+ y: float
24
+ z: float
25
+
26
+
27
+ @wp.struct
28
+ class Sv:
29
+ u: wp.vec3
30
+ v: wp.vec3
31
+ w: wp.vec3
32
+
33
+
34
+ @wp.struct
35
+ class Sm:
36
+ M: wp.mat33
37
+ N: wp.mat33
38
+ O: wp.mat33
39
+
40
+
41
+ @wp.struct
42
+ class Sa:
43
+ a: wp.array(dtype=float)
44
+ b: wp.array(dtype=float)
45
+ c: wp.array(dtype=float)
46
+
47
+
48
+ @wp.struct
49
+ class Sz:
50
+ a: wp.array(dtype=float)
51
+ b: wp.array(dtype=float)
52
+ c: wp.array(dtype=float)
53
+ x: float
54
+ y: float
55
+ z: float
56
+ u: wp.vec3
57
+ v: wp.vec3
58
+ w: wp.vec3
59
+
60
+
61
+ @wp.kernel
62
+ def k0():
63
+ tid = wp.tid()
64
+
65
+
66
+ @wp.kernel
67
+ def kf(x: float, y: float, z: float):
68
+ tid = wp.tid()
69
+
70
+
71
+ @wp.kernel
72
+ def kv(u: wp.vec3, v: wp.vec3, w: wp.vec3):
73
+ tid = wp.tid()
74
+
75
+
76
+ @wp.kernel
77
+ def km(M: wp.mat33, N: wp.mat33, O: wp.mat33):
78
+ tid = wp.tid()
79
+
80
+
81
+ @wp.kernel
82
+ def ka(a: wp.array(dtype=float), b: wp.array(dtype=float), c: wp.array(dtype=float)):
83
+ tid = wp.tid()
84
+
85
+
86
+ @wp.kernel
87
+ def kz(
88
+ a: wp.array(dtype=float),
89
+ b: wp.array(dtype=float),
90
+ c: wp.array(dtype=float),
91
+ x: float,
92
+ y: float,
93
+ z: float,
94
+ u: wp.vec3,
95
+ v: wp.vec3,
96
+ w: wp.vec3,
97
+ ):
98
+ tid = wp.tid()
99
+
100
+
101
+ @wp.kernel
102
+ def ks0(s: S0):
103
+ tid = wp.tid()
104
+
105
+
106
+ @wp.kernel
107
+ def ksf(s: Sf):
108
+ tid = wp.tid()
109
+
110
+
111
+ @wp.kernel
112
+ def ksv(s: Sv):
113
+ tid = wp.tid()
114
+
115
+
116
+ @wp.kernel
117
+ def ksm(s: Sm):
118
+ tid = wp.tid()
119
+
120
+
121
+ @wp.kernel
122
+ def ksa(s: Sa):
123
+ tid = wp.tid()
124
+
125
+
126
+ @wp.kernel
127
+ def ksz(s: Sz):
128
+ tid = wp.tid()
129
+
130
+
131
+ wp.init()
132
+
133
+ wp.build.clear_kernel_cache()
134
+
135
+ devices = wp.get_devices()
136
+ num_launches = 100000
137
+
138
+ for device in devices:
139
+ with wp.ScopedDevice(device):
140
+ print(f"\n=================== Device '{device}' ===================")
141
+
142
+ wp.force_load(device)
143
+
144
+ n = 1
145
+ a = wp.zeros(n, dtype=float)
146
+ b = wp.zeros(n, dtype=float)
147
+ c = wp.zeros(n, dtype=float)
148
+ x = 17.0
149
+ y = 42.0
150
+ z = 99.0
151
+ u = wp.vec3(1, 2, 3)
152
+ v = wp.vec3(10, 20, 30)
153
+ w = wp.vec3(100, 200, 300)
154
+ M = wp.mat33()
155
+ N = wp.mat33()
156
+ O = wp.mat33()
157
+
158
+ s0 = S0()
159
+
160
+ sf = Sf()
161
+ sf.x = x
162
+ sf.y = y
163
+ sf.z = z
164
+
165
+ sv = Sv()
166
+ sv.u = u
167
+ sv.v = v
168
+ sv.w = w
169
+
170
+ sm = Sm()
171
+ sm.M = M
172
+ sm.N = N
173
+ sm.O = O
174
+
175
+ sa = Sa()
176
+ sa.a = a
177
+ sa.b = b
178
+ sa.c = c
179
+
180
+ sz = Sz()
181
+ sz.a = a
182
+ sz.b = b
183
+ sz.c = c
184
+ sz.x = x
185
+ sz.y = y
186
+ sz.z = z
187
+ sz.u = u
188
+ sz.v = v
189
+ sz.w = w
190
+
191
+ tk0 = wp.ScopedTimer("k0")
192
+ tkf = wp.ScopedTimer("kf")
193
+ tkv = wp.ScopedTimer("kv")
194
+ tkm = wp.ScopedTimer("km")
195
+ tka = wp.ScopedTimer("ka")
196
+ tkz = wp.ScopedTimer("kz")
197
+
198
+ ts0 = wp.ScopedTimer("s0")
199
+ tsf = wp.ScopedTimer("sf")
200
+ tsv = wp.ScopedTimer("sv")
201
+ tsm = wp.ScopedTimer("sm")
202
+ tsa = wp.ScopedTimer("sa")
203
+ tsz = wp.ScopedTimer("sz")
204
+
205
+ wp.synchronize_device()
206
+
207
+ with tk0:
208
+ for _ in range(num_launches):
209
+ wp.launch(k0, dim=1, inputs=[])
210
+
211
+ wp.synchronize_device()
212
+
213
+ with tkf:
214
+ for _ in range(num_launches):
215
+ wp.launch(kf, dim=1, inputs=[x, y, z])
216
+
217
+ wp.synchronize_device()
218
+
219
+ with tkv:
220
+ for _ in range(num_launches):
221
+ wp.launch(kv, dim=1, inputs=[u, v, w])
222
+
223
+ wp.synchronize_device()
224
+
225
+ with tkm:
226
+ for _ in range(num_launches):
227
+ wp.launch(km, dim=1, inputs=[M, N, O])
228
+
229
+ wp.synchronize_device()
230
+
231
+ with tka:
232
+ for _ in range(num_launches):
233
+ wp.launch(ka, dim=1, inputs=[a, b, c])
234
+
235
+ wp.synchronize_device()
236
+
237
+ with tkz:
238
+ for _ in range(num_launches):
239
+ wp.launch(kz, dim=1, inputs=[a, b, c, x, y, z, u, v, w])
240
+
241
+ # structs
242
+
243
+ wp.synchronize_device()
244
+
245
+ with ts0:
246
+ for _ in range(num_launches):
247
+ wp.launch(ks0, dim=1, inputs=[s0])
248
+
249
+ wp.synchronize_device()
250
+
251
+ with tsf:
252
+ for _ in range(num_launches):
253
+ wp.launch(ksf, dim=1, inputs=[sf])
254
+
255
+ wp.synchronize_device()
256
+
257
+ with tsv:
258
+ for _ in range(num_launches):
259
+ wp.launch(ksv, dim=1, inputs=[sv])
260
+
261
+ wp.synchronize_device()
262
+
263
+ with tsm:
264
+ for _ in range(num_launches):
265
+ wp.launch(ksm, dim=1, inputs=[sm])
266
+
267
+ wp.synchronize_device()
268
+
269
+ with tsa:
270
+ for _ in range(num_launches):
271
+ wp.launch(ksa, dim=1, inputs=[sa])
272
+
273
+ wp.synchronize_device()
274
+
275
+ with tsz:
276
+ for _ in range(num_launches):
277
+ wp.launch(ksz, dim=1, inputs=[sz])
278
+
279
+ wp.synchronize_device()
280
+
281
+ timers = [
282
+ [tk0, ts0],
283
+ [tkf, tsf],
284
+ [tkv, tsv],
285
+ [tkm, tsm],
286
+ [tka, tsa],
287
+ [tkz, tsz],
288
+ ]
289
+
290
+ print("--------------------------------")
291
+ print("| args | direct | struct |")
292
+ print("--------------------------------")
293
+ for tk, ts in timers:
294
+ print(f"| {tk.name} |{tk.elapsed:10.0f} |{ts.elapsed:10.0f} |")
295
+ print("--------------------------------")
@@ -0,0 +1,221 @@
1
+ # Copyright (c) 2022 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
+ ###########################################################################
9
+ # Example DEM
10
+ #
11
+ # Shows how to implement a DEM particle simulation with cohesion between
12
+ # particles. Neighbors are found using the wp.HashGrid class, and
13
+ # wp.hash_grid_query(), wp.hash_grid_query_next() kernel methods.
14
+ #
15
+ ###########################################################################
16
+
17
+ import os
18
+
19
+ import numpy as np
20
+
21
+ import warp as wp
22
+ import warp.render
23
+
24
+ wp.init()
25
+
26
+
27
+ @wp.func
28
+ def contact_force(n: wp.vec3, v: wp.vec3, c: float, k_n: float, k_d: float, k_f: float, k_mu: float):
29
+ vn = wp.dot(n, v)
30
+ jn = c * k_n
31
+ jd = min(vn, 0.0) * k_d
32
+
33
+ # contact force
34
+ fn = jn + jd
35
+
36
+ # friction force
37
+ vt = v - n * vn
38
+ vs = wp.length(vt)
39
+
40
+ if vs > 0.0:
41
+ vt = vt / vs
42
+
43
+ # Coulomb condition
44
+ ft = wp.min(vs * k_f, k_mu * wp.abs(fn))
45
+
46
+ # total force
47
+ return -n * fn - vt * ft
48
+
49
+
50
+ @wp.kernel
51
+ def apply_forces(
52
+ grid: wp.uint64,
53
+ particle_x: wp.array(dtype=wp.vec3),
54
+ particle_v: wp.array(dtype=wp.vec3),
55
+ particle_f: wp.array(dtype=wp.vec3),
56
+ radius: float,
57
+ k_contact: float,
58
+ k_damp: float,
59
+ k_friction: float,
60
+ k_mu: float,
61
+ ):
62
+ tid = wp.tid()
63
+
64
+ # order threads by cell
65
+ i = wp.hash_grid_point_id(grid, tid)
66
+
67
+ x = particle_x[i]
68
+ v = particle_v[i]
69
+
70
+ f = wp.vec3()
71
+
72
+ # ground contact
73
+ n = wp.vec3(0.0, 1.0, 0.0)
74
+ c = wp.dot(n, x)
75
+
76
+ cohesion_ground = 0.02
77
+ cohesion_particle = 0.0075
78
+
79
+ if c < cohesion_ground:
80
+ f = f + contact_force(n, v, c, k_contact, k_damp, 100.0, 0.5)
81
+
82
+ # particle contact
83
+ neighbors = wp.hash_grid_query(grid, x, radius * 5.0)
84
+
85
+ for index in neighbors:
86
+ if index != i:
87
+ # compute distance to point
88
+ n = x - particle_x[index]
89
+ d = wp.length(n)
90
+ err = d - radius * 2.0
91
+
92
+ if err <= cohesion_particle:
93
+ n = n / d
94
+ vrel = v - particle_v[index]
95
+
96
+ f = f + contact_force(n, vrel, err, k_contact, k_damp, k_friction, k_mu)
97
+
98
+ particle_f[i] = f
99
+
100
+
101
+ @wp.kernel
102
+ def integrate(
103
+ x: wp.array(dtype=wp.vec3),
104
+ v: wp.array(dtype=wp.vec3),
105
+ f: wp.array(dtype=wp.vec3),
106
+ gravity: wp.vec3,
107
+ dt: float,
108
+ inv_mass: float,
109
+ ):
110
+ tid = wp.tid()
111
+
112
+ v_new = v[tid] + f[tid] * inv_mass * dt + gravity * dt
113
+ x_new = x[tid] + v_new * dt
114
+
115
+ v[tid] = v_new
116
+ x[tid] = x_new
117
+
118
+
119
+ class Example:
120
+ def __init__(self, stage):
121
+ self.frame_dt = 1.0 / 60
122
+ self.frame_count = 400
123
+
124
+ self.sim_substeps = 64
125
+ self.sim_dt = self.frame_dt / self.sim_substeps
126
+ self.sim_steps = self.frame_count * self.sim_substeps
127
+ self.sim_time = 0.0
128
+
129
+ self.point_radius = 0.1
130
+
131
+ self.k_contact = 8000.0
132
+ self.k_damp = 2.0
133
+ self.k_friction = 1.0
134
+ self.k_mu = 100000.0 # for cohesive materials
135
+
136
+ self.inv_mass = 64.0
137
+
138
+ self.grid = wp.HashGrid(128, 128, 128)
139
+ self.grid_cell_size = self.point_radius * 5.0
140
+
141
+ self.points = self.particle_grid(32, 128, 32, (0.0, 0.3, 0.0), self.point_radius, 0.1)
142
+
143
+ self.x = wp.array(self.points, dtype=wp.vec3)
144
+ self.v = wp.array(np.ones([len(self.x), 3]) * np.array([0.0, 0.0, 10.0]), dtype=wp.vec3)
145
+ self.f = wp.zeros_like(self.v)
146
+
147
+ self.renderer = None
148
+ if stage is not None:
149
+ self.renderer = wp.render.UsdRenderer(stage)
150
+ self.renderer.render_ground()
151
+
152
+ self.use_graph = wp.get_device().is_cuda
153
+ if self.use_graph:
154
+ with wp.ScopedCapture() as capture:
155
+ self.simulate()
156
+ self.graph = capture.graph
157
+
158
+ def simulate(self):
159
+ for _ in range(self.sim_substeps):
160
+ wp.launch(
161
+ kernel=apply_forces,
162
+ dim=len(self.x),
163
+ inputs=[
164
+ self.grid.id,
165
+ self.x,
166
+ self.v,
167
+ self.f,
168
+ self.point_radius,
169
+ self.k_contact,
170
+ self.k_damp,
171
+ self.k_friction,
172
+ self.k_mu,
173
+ ],
174
+ )
175
+ wp.launch(
176
+ kernel=integrate,
177
+ dim=len(self.x),
178
+ inputs=[self.x, self.v, self.f, (0.0, -9.8, 0.0), self.sim_dt, self.inv_mass],
179
+ )
180
+
181
+ def step(self):
182
+ with wp.ScopedTimer("step", active=True):
183
+ with wp.ScopedTimer("grid build", active=False):
184
+ self.grid.build(self.x, self.grid_cell_size)
185
+
186
+ if self.use_graph:
187
+ wp.capture_launch(self.graph)
188
+ else:
189
+ self.simulate()
190
+
191
+ self.sim_time += self.frame_dt
192
+
193
+ def render(self):
194
+ if self.renderer is None:
195
+ return
196
+
197
+ with wp.ScopedTimer("render", active=True):
198
+ self.renderer.begin_frame(self.sim_time)
199
+ self.renderer.render_points(points=self.x.numpy(), radius=self.point_radius, name="points", colors=((0.8, 0.3, 0.2),) * len(self.x))
200
+ self.renderer.end_frame()
201
+
202
+ # creates a grid of particles
203
+ def particle_grid(self, dim_x, dim_y, dim_z, lower, radius, jitter):
204
+ points = np.meshgrid(np.linspace(0, dim_x, dim_x), np.linspace(0, dim_y, dim_y), np.linspace(0, dim_z, dim_z))
205
+ points_t = np.array((points[0], points[1], points[2])).T * radius * 2.0 + np.array(lower)
206
+ points_t = points_t + np.random.rand(*points_t.shape) * radius * jitter
207
+
208
+ return points_t.reshape((-1, 3))
209
+
210
+
211
+ if __name__ == "__main__":
212
+ stage_path = os.path.join(os.path.dirname(__file__), "example_dem.usd")
213
+
214
+ example = Example(stage_path)
215
+
216
+ for i in range(example.frame_count):
217
+ example.step()
218
+ example.render()
219
+
220
+ if example.renderer:
221
+ example.renderer.save()