warp-lang 1.0.0b2__py3-none-win_amd64.whl → 1.0.0b6__py3-none-win_amd64.whl

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

Potentially problematic release.


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

Files changed (271) hide show
  1. docs/conf.py +17 -5
  2. examples/env/env_ant.py +1 -1
  3. examples/env/env_cartpole.py +1 -1
  4. examples/env/env_humanoid.py +1 -1
  5. examples/env/env_usd.py +4 -1
  6. examples/env/environment.py +8 -9
  7. examples/example_dem.py +34 -33
  8. examples/example_diffray.py +364 -337
  9. examples/example_fluid.py +32 -23
  10. examples/example_jacobian_ik.py +97 -93
  11. examples/example_marching_cubes.py +6 -16
  12. examples/example_mesh.py +6 -16
  13. examples/example_mesh_intersect.py +16 -14
  14. examples/example_nvdb.py +14 -16
  15. examples/example_raycast.py +14 -13
  16. examples/example_raymarch.py +16 -23
  17. examples/example_render_opengl.py +19 -10
  18. examples/example_sim_cartpole.py +82 -78
  19. examples/example_sim_cloth.py +45 -48
  20. examples/example_sim_fk_grad.py +51 -44
  21. examples/example_sim_fk_grad_torch.py +47 -40
  22. examples/example_sim_grad_bounce.py +108 -133
  23. examples/example_sim_grad_cloth.py +99 -113
  24. examples/example_sim_granular.py +5 -6
  25. examples/{example_sim_sdf_shape.py → example_sim_granular_collision_sdf.py} +37 -26
  26. examples/example_sim_neo_hookean.py +51 -55
  27. examples/example_sim_particle_chain.py +4 -4
  28. examples/example_sim_quadruped.py +126 -81
  29. examples/example_sim_rigid_chain.py +54 -61
  30. examples/example_sim_rigid_contact.py +66 -70
  31. examples/example_sim_rigid_fem.py +3 -3
  32. examples/example_sim_rigid_force.py +1 -1
  33. examples/example_sim_rigid_gyroscopic.py +3 -4
  34. examples/example_sim_rigid_kinematics.py +28 -39
  35. examples/example_sim_trajopt.py +112 -110
  36. examples/example_sph.py +9 -8
  37. examples/example_wave.py +7 -7
  38. examples/fem/bsr_utils.py +30 -17
  39. examples/fem/example_apic_fluid.py +85 -69
  40. examples/fem/example_convection_diffusion.py +97 -93
  41. examples/fem/example_convection_diffusion_dg.py +142 -149
  42. examples/fem/example_convection_diffusion_dg0.py +141 -136
  43. examples/fem/example_deformed_geometry.py +146 -0
  44. examples/fem/example_diffusion.py +115 -84
  45. examples/fem/example_diffusion_3d.py +116 -86
  46. examples/fem/example_diffusion_mgpu.py +102 -79
  47. examples/fem/example_mixed_elasticity.py +139 -100
  48. examples/fem/example_navier_stokes.py +175 -162
  49. examples/fem/example_stokes.py +143 -111
  50. examples/fem/example_stokes_transfer.py +186 -157
  51. examples/fem/mesh_utils.py +59 -97
  52. examples/fem/plot_utils.py +138 -17
  53. tools/ci/publishing/build_nodes_info.py +54 -0
  54. warp/__init__.py +4 -3
  55. warp/__init__.pyi +1 -0
  56. warp/bin/warp-clang.dll +0 -0
  57. warp/bin/warp.dll +0 -0
  58. warp/build.py +5 -3
  59. warp/build_dll.py +29 -9
  60. warp/builtins.py +836 -492
  61. warp/codegen.py +864 -553
  62. warp/config.py +3 -1
  63. warp/context.py +389 -172
  64. warp/fem/__init__.py +24 -6
  65. warp/fem/cache.py +318 -25
  66. warp/fem/dirichlet.py +7 -3
  67. warp/fem/domain.py +14 -0
  68. warp/fem/field/__init__.py +30 -38
  69. warp/fem/field/field.py +149 -0
  70. warp/fem/field/nodal_field.py +244 -138
  71. warp/fem/field/restriction.py +8 -6
  72. warp/fem/field/test.py +127 -59
  73. warp/fem/field/trial.py +117 -60
  74. warp/fem/geometry/__init__.py +5 -1
  75. warp/fem/geometry/deformed_geometry.py +271 -0
  76. warp/fem/geometry/element.py +24 -1
  77. warp/fem/geometry/geometry.py +86 -14
  78. warp/fem/geometry/grid_2d.py +112 -54
  79. warp/fem/geometry/grid_3d.py +134 -65
  80. warp/fem/geometry/hexmesh.py +953 -0
  81. warp/fem/geometry/partition.py +85 -33
  82. warp/fem/geometry/quadmesh_2d.py +532 -0
  83. warp/fem/geometry/tetmesh.py +451 -115
  84. warp/fem/geometry/trimesh_2d.py +197 -92
  85. warp/fem/integrate.py +534 -268
  86. warp/fem/operator.py +58 -31
  87. warp/fem/polynomial.py +11 -0
  88. warp/fem/quadrature/__init__.py +1 -1
  89. warp/fem/quadrature/pic_quadrature.py +150 -58
  90. warp/fem/quadrature/quadrature.py +209 -57
  91. warp/fem/space/__init__.py +230 -53
  92. warp/fem/space/basis_space.py +489 -0
  93. warp/fem/space/collocated_function_space.py +105 -0
  94. warp/fem/space/dof_mapper.py +49 -2
  95. warp/fem/space/function_space.py +90 -39
  96. warp/fem/space/grid_2d_function_space.py +149 -496
  97. warp/fem/space/grid_3d_function_space.py +173 -538
  98. warp/fem/space/hexmesh_function_space.py +352 -0
  99. warp/fem/space/partition.py +129 -76
  100. warp/fem/space/quadmesh_2d_function_space.py +369 -0
  101. warp/fem/space/restriction.py +46 -34
  102. warp/fem/space/shape/__init__.py +15 -0
  103. warp/fem/space/shape/cube_shape_function.py +738 -0
  104. warp/fem/space/shape/shape_function.py +103 -0
  105. warp/fem/space/shape/square_shape_function.py +611 -0
  106. warp/fem/space/shape/tet_shape_function.py +567 -0
  107. warp/fem/space/shape/triangle_shape_function.py +429 -0
  108. warp/fem/space/tetmesh_function_space.py +132 -1039
  109. warp/fem/space/topology.py +295 -0
  110. warp/fem/space/trimesh_2d_function_space.py +104 -742
  111. warp/fem/types.py +13 -11
  112. warp/fem/utils.py +335 -60
  113. warp/native/array.h +120 -34
  114. warp/native/builtin.h +101 -72
  115. warp/native/bvh.cpp +73 -325
  116. warp/native/bvh.cu +406 -23
  117. warp/native/bvh.h +22 -40
  118. warp/native/clang/clang.cpp +1 -0
  119. warp/native/crt.h +2 -0
  120. warp/native/cuda_util.cpp +8 -3
  121. warp/native/cuda_util.h +1 -0
  122. warp/native/exports.h +1522 -1243
  123. warp/native/intersect.h +19 -4
  124. warp/native/intersect_adj.h +8 -8
  125. warp/native/mat.h +76 -17
  126. warp/native/mesh.cpp +33 -108
  127. warp/native/mesh.cu +114 -18
  128. warp/native/mesh.h +395 -40
  129. warp/native/noise.h +272 -329
  130. warp/native/quat.h +51 -8
  131. warp/native/rand.h +44 -34
  132. warp/native/reduce.cpp +1 -1
  133. warp/native/sparse.cpp +4 -4
  134. warp/native/sparse.cu +163 -155
  135. warp/native/spatial.h +2 -2
  136. warp/native/temp_buffer.h +18 -14
  137. warp/native/vec.h +103 -21
  138. warp/native/warp.cpp +2 -1
  139. warp/native/warp.cu +28 -3
  140. warp/native/warp.h +4 -3
  141. warp/render/render_opengl.py +261 -109
  142. warp/sim/__init__.py +1 -2
  143. warp/sim/articulation.py +385 -185
  144. warp/sim/import_mjcf.py +59 -48
  145. warp/sim/import_urdf.py +15 -15
  146. warp/sim/import_usd.py +174 -102
  147. warp/sim/inertia.py +17 -18
  148. warp/sim/integrator_xpbd.py +4 -3
  149. warp/sim/model.py +330 -250
  150. warp/sim/render.py +1 -1
  151. warp/sparse.py +625 -152
  152. warp/stubs.py +341 -309
  153. warp/tape.py +9 -6
  154. warp/tests/__main__.py +3 -6
  155. warp/tests/assets/curlnoise_golden.npy +0 -0
  156. warp/tests/assets/pnoise_golden.npy +0 -0
  157. warp/tests/{test_class_kernel.py → aux_test_class_kernel.py} +9 -1
  158. warp/tests/aux_test_conditional_unequal_types_kernels.py +21 -0
  159. warp/tests/{test_dependent.py → aux_test_dependent.py} +2 -2
  160. warp/tests/{test_reference.py → aux_test_reference.py} +1 -1
  161. warp/tests/aux_test_unresolved_func.py +14 -0
  162. warp/tests/aux_test_unresolved_symbol.py +14 -0
  163. warp/tests/disabled_kinematics.py +239 -0
  164. warp/tests/run_coverage_serial.py +31 -0
  165. warp/tests/test_adam.py +103 -106
  166. warp/tests/test_arithmetic.py +94 -74
  167. warp/tests/test_array.py +82 -101
  168. warp/tests/test_array_reduce.py +57 -23
  169. warp/tests/test_atomic.py +64 -28
  170. warp/tests/test_bool.py +22 -12
  171. warp/tests/test_builtins_resolution.py +1292 -0
  172. warp/tests/test_bvh.py +18 -18
  173. warp/tests/test_closest_point_edge_edge.py +54 -57
  174. warp/tests/test_codegen.py +165 -134
  175. warp/tests/test_compile_consts.py +28 -20
  176. warp/tests/test_conditional.py +108 -24
  177. warp/tests/test_copy.py +10 -12
  178. warp/tests/test_ctypes.py +112 -88
  179. warp/tests/test_dense.py +21 -14
  180. warp/tests/test_devices.py +98 -0
  181. warp/tests/test_dlpack.py +75 -75
  182. warp/tests/test_examples.py +237 -0
  183. warp/tests/test_fabricarray.py +22 -24
  184. warp/tests/test_fast_math.py +15 -11
  185. warp/tests/test_fem.py +1034 -124
  186. warp/tests/test_fp16.py +23 -16
  187. warp/tests/test_func.py +187 -86
  188. warp/tests/test_generics.py +194 -49
  189. warp/tests/test_grad.py +123 -181
  190. warp/tests/test_grad_customs.py +176 -0
  191. warp/tests/test_hash_grid.py +35 -34
  192. warp/tests/test_import.py +10 -23
  193. warp/tests/test_indexedarray.py +24 -25
  194. warp/tests/test_intersect.py +18 -9
  195. warp/tests/test_large.py +141 -0
  196. warp/tests/test_launch.py +14 -41
  197. warp/tests/test_lerp.py +64 -65
  198. warp/tests/test_lvalue.py +493 -0
  199. warp/tests/test_marching_cubes.py +12 -13
  200. warp/tests/test_mat.py +517 -2898
  201. warp/tests/test_mat_lite.py +115 -0
  202. warp/tests/test_mat_scalar_ops.py +2889 -0
  203. warp/tests/test_math.py +103 -9
  204. warp/tests/test_matmul.py +304 -69
  205. warp/tests/test_matmul_lite.py +410 -0
  206. warp/tests/test_mesh.py +60 -22
  207. warp/tests/test_mesh_query_aabb.py +21 -25
  208. warp/tests/test_mesh_query_point.py +111 -22
  209. warp/tests/test_mesh_query_ray.py +12 -24
  210. warp/tests/test_mlp.py +30 -22
  211. warp/tests/test_model.py +92 -89
  212. warp/tests/test_modules_lite.py +39 -0
  213. warp/tests/test_multigpu.py +88 -114
  214. warp/tests/test_noise.py +12 -11
  215. warp/tests/test_operators.py +16 -20
  216. warp/tests/test_options.py +11 -11
  217. warp/tests/test_pinned.py +17 -18
  218. warp/tests/test_print.py +32 -11
  219. warp/tests/test_quat.py +275 -129
  220. warp/tests/test_rand.py +18 -16
  221. warp/tests/test_reload.py +38 -34
  222. warp/tests/test_rounding.py +50 -43
  223. warp/tests/test_runlength_encode.py +168 -20
  224. warp/tests/test_smoothstep.py +9 -11
  225. warp/tests/test_snippet.py +143 -0
  226. warp/tests/test_sparse.py +261 -63
  227. warp/tests/test_spatial.py +276 -243
  228. warp/tests/test_streams.py +110 -85
  229. warp/tests/test_struct.py +268 -63
  230. warp/tests/test_tape.py +39 -21
  231. warp/tests/test_torch.py +90 -86
  232. warp/tests/test_transient_module.py +10 -12
  233. warp/tests/test_types.py +363 -0
  234. warp/tests/test_utils.py +451 -0
  235. warp/tests/test_vec.py +354 -2050
  236. warp/tests/test_vec_lite.py +73 -0
  237. warp/tests/test_vec_scalar_ops.py +2099 -0
  238. warp/tests/test_volume.py +418 -376
  239. warp/tests/test_volume_write.py +124 -134
  240. warp/tests/unittest_serial.py +35 -0
  241. warp/tests/unittest_suites.py +291 -0
  242. warp/tests/unittest_utils.py +342 -0
  243. warp/tests/{test_misc.py → unused_test_misc.py} +13 -5
  244. warp/tests/{test_debug.py → walkthough_debug.py} +3 -17
  245. warp/thirdparty/appdirs.py +36 -45
  246. warp/thirdparty/unittest_parallel.py +589 -0
  247. warp/types.py +622 -211
  248. warp/utils.py +54 -393
  249. warp_lang-1.0.0b6.dist-info/METADATA +238 -0
  250. warp_lang-1.0.0b6.dist-info/RECORD +409 -0
  251. {warp_lang-1.0.0b2.dist-info → warp_lang-1.0.0b6.dist-info}/WHEEL +1 -1
  252. examples/example_cache_management.py +0 -40
  253. examples/example_multigpu.py +0 -54
  254. examples/example_struct.py +0 -65
  255. examples/fem/example_stokes_transfer_3d.py +0 -210
  256. warp/bin/warp-clang.so +0 -0
  257. warp/bin/warp.so +0 -0
  258. warp/fem/field/discrete_field.py +0 -80
  259. warp/fem/space/nodal_function_space.py +0 -233
  260. warp/tests/test_all.py +0 -223
  261. warp/tests/test_array_scan.py +0 -60
  262. warp/tests/test_base.py +0 -208
  263. warp/tests/test_unresolved_func.py +0 -7
  264. warp/tests/test_unresolved_symbol.py +0 -7
  265. warp_lang-1.0.0b2.dist-info/METADATA +0 -26
  266. warp_lang-1.0.0b2.dist-info/RECORD +0 -380
  267. /warp/tests/{test_compile_consts_dummy.py → aux_test_compile_consts_dummy.py} +0 -0
  268. /warp/tests/{test_reference_reference.py → aux_test_reference_reference.py} +0 -0
  269. /warp/tests/{test_square.py → aux_test_square.py} +0 -0
  270. {warp_lang-1.0.0b2.dist-info → warp_lang-1.0.0b6.dist-info}/LICENSE.md +0 -0
  271. {warp_lang-1.0.0b2.dist-info → warp_lang-1.0.0b6.dist-info}/top_level.txt +0 -0
@@ -20,45 +20,60 @@
20
20
  import os
21
21
 
22
22
  import numpy as np
23
- import warp as wp
24
23
 
24
+ import warp as wp
25
25
  import warp.sim
26
26
  import warp.sim.render
27
27
 
28
28
  wp.init()
29
29
 
30
30
 
31
- class Bounce:
32
- # seconds
33
- sim_duration = 0.6
31
+ @wp.kernel
32
+ def loss_kernel(pos: wp.array(dtype=wp.vec3), target: wp.vec3, loss: wp.array(dtype=float)):
33
+ # distance to target
34
+ delta = pos[0] - target
35
+ loss[0] = wp.dot(delta, delta)
34
36
 
35
- # control frequency
36
- frame_dt = 1.0 / 60.0
37
- frame_steps = int(sim_duration / frame_dt)
38
37
 
39
- # sim frequency
40
- sim_substeps = 8
41
- sim_steps = frame_steps * sim_substeps
42
- sim_dt = frame_dt / sim_substeps
43
- sim_time = 0.0
38
+ @wp.kernel
39
+ def step_kernel(x: wp.array(dtype=wp.vec3), grad: wp.array(dtype=wp.vec3), alpha: float):
40
+ tid = wp.tid()
44
41
 
45
- render_time = 0.0
42
+ # gradient descent step
43
+ x[tid] = x[tid] - grad[tid] * alpha
46
44
 
47
- train_iters = 250
48
- train_rate = 0.02
49
45
 
50
- ke = 1.0e4
51
- kf = 0.0
52
- kd = 1.0e1
53
- mu = 0.25
46
+ class Example:
47
+ def __init__(self, stage=None, enable_rendering=True, profile=False, adapter=None, verbose=False):
48
+ self.device = wp.get_device()
49
+ self.verbose = verbose
54
50
 
55
- def __init__(self, render=True, profile=False, adapter=None):
56
- builder = wp.sim.ModelBuilder()
51
+ # seconds
52
+ sim_duration = 0.6
53
+
54
+ # control frequency
55
+ self.frame_dt = 1.0 / 60.0
56
+ frame_steps = int(sim_duration / self.frame_dt)
57
+
58
+ # sim frequency
59
+ self.sim_substeps = 8
60
+ self.sim_steps = frame_steps * self.sim_substeps
61
+ self.sim_dt = self.frame_dt / self.sim_substeps
57
62
 
58
- builder.add_particle(pos=(-0.5, 1.0, 0.0), vel=(5.0, -5.0, 0.0), mass=1.0)
59
- builder.add_shape_box(
60
- body=-1, pos=(2.0, 1.0, 0.0), hx=0.25, hy=1.0, hz=1.0, ke=self.ke, kf=self.kf, kd=self.kd, mu=self.mu
61
- )
63
+ self.iter = 0
64
+ self.render_time = 0.0
65
+
66
+ self.train_iters = 250
67
+ self.train_rate = 0.02
68
+
69
+ ke = 1.0e4
70
+ kf = 0.0
71
+ kd = 1.0e1
72
+ mu = 0.2
73
+
74
+ builder = wp.sim.ModelBuilder()
75
+ builder.add_particle(pos=wp.vec3(-0.5, 1.0, 0.0), vel=wp.vec3(5.0, -5.0, 0.0), mass=1.0)
76
+ builder.add_shape_box(body=-1, pos=wp.vec3(2.0, 1.0, 0.0), hx=0.25, hy=1.0, hz=1.0, ke=ke, kf=kf, kd=kd, mu=mu)
62
77
 
63
78
  self.device = wp.get_device(adapter)
64
79
  self.profile = profile
@@ -66,10 +81,10 @@ class Bounce:
66
81
  self.model = builder.finalize(self.device)
67
82
  self.model.ground = True
68
83
 
69
- self.model.soft_contact_ke = self.ke
70
- self.model.soft_contact_kf = self.kf
71
- self.model.soft_contact_kd = self.kd
72
- self.model.soft_contact_mu = self.mu
84
+ self.model.soft_contact_ke = ke
85
+ self.model.soft_contact_kf = kf
86
+ self.model.soft_contact_kd = kd
87
+ self.model.soft_contact_mu = mu
73
88
  self.model.soft_contact_margin = 10.0
74
89
  self.model.soft_contact_restitution = 1.0
75
90
 
@@ -86,24 +101,20 @@ class Bounce:
86
101
  # one-shot contact creation (valid if we're doing simple collision against a constant normal plane)
87
102
  wp.sim.collide(self.model, self.states[0])
88
103
 
89
- self.stage = None
90
- if render:
91
- self.stage = wp.sim.render.SimRendererOpenGL(
92
- self.model, os.path.join(os.path.dirname(__file__), "outputs/example_sim_grad_bounce.usd"), scaling=1.0
93
- )
94
-
95
- @wp.kernel
96
- def loss_kernel(pos: wp.array(dtype=wp.vec3), target: wp.vec3, loss: wp.array(dtype=float)):
97
- # distance to target
98
- delta = pos[0] - target
99
- loss[0] = wp.dot(delta, delta)
104
+ self.enable_rendering = enable_rendering
105
+ self.renderer = None
106
+ if self.enable_rendering:
107
+ self.renderer = wp.sim.render.SimRenderer(self.model, stage, scaling=1.0)
100
108
 
101
- @wp.kernel
102
- def step_kernel(x: wp.array(dtype=wp.vec3), grad: wp.array(dtype=wp.vec3), alpha: float):
103
- tid = wp.tid()
104
-
105
- # gradient descent step
106
- x[tid] = x[tid] - grad[tid] * alpha
109
+ # capture forward/backward passes
110
+ wp.capture_begin(self.device)
111
+ try:
112
+ self.tape = wp.Tape()
113
+ with self.tape:
114
+ self.compute_loss()
115
+ self.tape.backward(self.loss)
116
+ finally:
117
+ self.graph = wp.capture_end(self.device)
107
118
 
108
119
  def compute_loss(self):
109
120
  # run control loop
@@ -113,38 +124,53 @@ class Bounce:
113
124
  self.integrator.simulate(self.model, self.states[i], self.states[i + 1], self.sim_dt)
114
125
 
115
126
  # compute loss on final state
116
- wp.launch(
117
- self.loss_kernel, dim=1, inputs=[self.states[-1].particle_q, self.target, self.loss], device=self.device
118
- )
127
+ wp.launch(loss_kernel, dim=1, inputs=[self.states[-1].particle_q, self.target, self.loss], device=self.device)
119
128
 
120
129
  return self.loss
121
130
 
122
- def render(self, iter):
123
- if self.stage is None:
124
- return
131
+ def update(self):
132
+ with wp.ScopedTimer("Step", active=self.profile):
133
+ # forward + backward
134
+ wp.capture_launch(self.graph)
125
135
 
126
- # render every 16 iters
127
- if iter % 16 > 0:
128
- return
136
+ # gradient descent step
137
+ x = self.states[0].particle_qd
138
+ wp.launch(step_kernel, dim=len(x), inputs=[x, x.grad, self.train_rate], device=self.device)
129
139
 
130
- # draw trajectory
131
- traj_verts = [self.states[0].particle_q.numpy()[0].tolist()]
140
+ x_grad = self.tape.gradients[self.states[0].particle_qd]
132
141
 
133
- for i in range(0, self.sim_steps, self.sim_substeps):
134
- traj_verts.append(self.states[i].particle_q.numpy()[0].tolist())
142
+ if self.verbose:
143
+ print(f"Iter: {self.iter} Loss: {self.loss}")
144
+ print(f" x: {x} g: {x_grad}")
135
145
 
136
- self.stage.begin_frame(self.render_time)
137
- self.stage.render(self.states[i])
138
- self.stage.render_box(pos=self.target, rot=wp.quat_identity(), extents=(0.1, 0.1, 0.1), name="target")
139
- self.stage.render_line_strip(
140
- vertices=traj_verts,
141
- color=wp.render.bourke_color_map(0.0, 7.0, self.loss.numpy()[0]),
142
- radius=0.02,
143
- name=f"traj_{iter}",
144
- )
145
- self.stage.end_frame()
146
+ # clear grads for next iteration
147
+ self.tape.zero()
146
148
 
147
- self.render_time += self.frame_dt
149
+ self.iter = self.iter + 1
150
+
151
+ def render(self):
152
+ if self.enable_rendering:
153
+ with wp.ScopedTimer("Render", active=self.profile):
154
+ # draw trajectory
155
+ traj_verts = [self.states[0].particle_q.numpy()[0].tolist()]
156
+
157
+ for i in range(0, self.sim_steps, self.sim_substeps):
158
+ traj_verts.append(self.states[i].particle_q.numpy()[0].tolist())
159
+
160
+ self.renderer.begin_frame(self.render_time)
161
+ self.renderer.render(self.states[i])
162
+ self.renderer.render_box(
163
+ pos=self.target, rot=wp.quat_identity(), extents=(0.1, 0.1, 0.1), name="target"
164
+ )
165
+ self.renderer.render_line_strip(
166
+ vertices=traj_verts,
167
+ color=wp.render.bourke_color_map(0.0, 7.0, self.loss.numpy()[0]),
168
+ radius=0.02,
169
+ name=f"traj_{self.iter-1}",
170
+ )
171
+ self.renderer.end_frame()
172
+
173
+ self.render_time += self.frame_dt
148
174
 
149
175
  def check_grad(self):
150
176
  param = self.states[0].particle_qd
@@ -191,71 +217,20 @@ class Bounce:
191
217
 
192
218
  tape.zero()
193
219
 
194
- def train(self):
195
- for i in range(self.train_iters):
196
- tape = wp.Tape()
197
-
198
- with wp.ScopedTimer("Forward", active=self.profile):
199
- with tape:
200
- self.compute_loss()
201
-
202
- with wp.ScopedTimer("Backward", active=self.profile):
203
- tape.backward(self.loss)
204
-
205
- with wp.ScopedTimer("Render", active=self.profile):
206
- self.render(i)
207
-
208
- with wp.ScopedTimer("Step", active=self.profile):
209
- x = self.states[0].particle_qd
210
- x_grad = tape.gradients[self.states[0].particle_qd]
211
-
212
- print(f"Iter: {i} Loss: {self.loss}")
213
- print(f" x: {x} g: {x_grad}")
214
-
215
- wp.launch(self.step_kernel, dim=len(x), inputs=[x, x_grad, self.train_rate], device=self.device)
216
-
217
- tape.zero()
218
-
219
- if self.stage is not None:
220
- self.stage.save()
221
-
222
- def train_graph(self):
223
- # capture forward/backward passes
224
- wp.capture_begin()
225
-
226
- tape = wp.Tape()
227
- with tape:
228
- self.compute_loss()
229
-
230
- tape.backward(self.loss)
231
-
232
- self.graph = wp.capture_end()
233
-
220
+ def run(self):
234
221
  # replay and optimize
235
222
  for i in range(self.train_iters):
236
- with wp.ScopedTimer("Step", active=self.profile):
237
- # forward + backward
238
- wp.capture_launch(self.graph)
239
-
240
- # gradient descent step
241
- x = self.states[0].particle_qd
242
- wp.launch(self.step_kernel, dim=len(x), inputs=[x, x.grad, self.train_rate], device=self.device)
243
-
244
- x_grad = tape.gradients[self.states[0].particle_qd]
245
-
246
- print(f"Iter: {i} Loss: {self.loss}")
247
- print(f" x: {x} g: {x_grad}")
248
-
249
- # clear grads for next iteration
250
- tape.zero()
251
-
252
- with wp.ScopedTimer("Render", active=self.profile):
253
- self.render(i)
223
+ self.update()
224
+ # render every 16 iters
225
+ if i % 16 == 0:
226
+ self.render()
254
227
 
255
- if self.stage is not None:
256
- self.stage.save()
228
+ if self.enable_rendering:
229
+ self.renderer.save()
257
230
 
258
231
 
259
- bounce = Bounce(profile=False, render=True)
260
- bounce.check_grad()
261
- bounce.train_graph()
232
+ if __name__ == "__main__":
233
+ stage_path = os.path.join(os.path.dirname(__file__), "outputs/example_sim_grad_bounce.usd")
234
+ example = Example(stage_path, profile=False, enable_rendering=True, verbose=True)
235
+ example.check_grad()
236
+ example.run()
@@ -9,7 +9,7 @@
9
9
  # Example Sim Grad Cloth
10
10
  #
11
11
  # Shows how to use Warp to optimize the initial velocities of a piece of
12
- # cloth such that it's center of mass hits a target after a specified time.
12
+ # cloth such that its center of mass hits a target after a specified time.
13
13
  #
14
14
  # This example uses the built-in wp.Tape() object to compute gradients of
15
15
  # the distance to target (loss) w.r.t the initial velocity, followed by
@@ -17,8 +17,8 @@
17
17
  #
18
18
  ###########################################################################
19
19
 
20
- import os
21
20
  import math
21
+ import os
22
22
 
23
23
  import warp as wp
24
24
  import warp.sim
@@ -27,26 +27,53 @@ import warp.sim.render
27
27
  wp.init()
28
28
 
29
29
 
30
- class Cloth:
31
- # seconds
32
- sim_duration = 2.0
30
+ @wp.kernel
31
+ def com_kernel(positions: wp.array(dtype=wp.vec3), n: int, com: wp.array(dtype=wp.vec3)):
32
+ tid = wp.tid()
33
+
34
+ # compute center of mass
35
+ wp.atomic_add(com, 0, positions[tid] / float(n))
36
+
37
+
38
+ @wp.kernel
39
+ def loss_kernel(com: wp.array(dtype=wp.vec3), target: wp.vec3, loss: wp.array(dtype=float)):
40
+ # sq. distance to target
41
+ delta = com[0] - target
42
+
43
+ loss[0] = wp.dot(delta, delta)
44
+
45
+
46
+ @wp.kernel
47
+ def step_kernel(x: wp.array(dtype=wp.vec3), grad: wp.array(dtype=wp.vec3), alpha: float):
48
+ tid = wp.tid()
33
49
 
34
- # control frequency
35
- frame_dt = 1.0 / 60.0
36
- frame_steps = int(sim_duration / frame_dt)
50
+ # gradient descent step
51
+ x[tid] = x[tid] - grad[tid] * alpha
37
52
 
38
- # sim frequency
39
- sim_substeps = 16
40
- sim_steps = frame_steps * sim_substeps
41
- sim_dt = frame_dt / sim_substeps
42
- sim_time = 0.0
43
53
 
44
- render_time = 0.0
54
+ class Example:
55
+ def __init__(self, stage, profile=False, adapter=None, verbose=False):
56
+ self.device = wp.get_device()
57
+ self.verbose = verbose
45
58
 
46
- train_iters = 64
47
- train_rate = 5.0
59
+ # seconds
60
+ sim_duration = 2.0
61
+
62
+ # control frequency
63
+ self.frame_dt = 1.0 / 60.0
64
+ frame_steps = int(sim_duration / self.frame_dt)
65
+
66
+ # sim frequency
67
+ self.sim_substeps = 16
68
+ self.sim_steps = frame_steps * self.sim_substeps
69
+ self.sim_dt = self.frame_dt / self.sim_substeps
70
+
71
+ self.iter = 0
72
+ self.render_time = 0.0
73
+
74
+ self.train_iters = 64
75
+ self.train_rate = 5.0
48
76
 
49
- def __init__(self, render=True, profile=False, adapter=None):
50
77
  builder = wp.sim.ModelBuilder()
51
78
  builder.default_particle_radius = 0.01
52
79
 
@@ -54,9 +81,9 @@ class Cloth:
54
81
  dim_y = 16
55
82
 
56
83
  builder.add_cloth_grid(
57
- pos=(0.0, 0.0, 0.0),
58
- vel=(0.1, 0.1, 0.0),
59
- rot=wp.quat_from_axis_angle((1.0, 0.0, 0.0), -math.pi * 0.25),
84
+ pos=wp.vec3(0.0, 0.0, 0.0),
85
+ vel=wp.vec3(0.1, 0.1, 0.0),
86
+ rot=wp.quat_from_axis_angle(wp.vec3(1.0, 0.0, 0.0), -math.pi * 0.25),
60
87
  dim_x=dim_x,
61
88
  dim_y=dim_y,
62
89
  cell_x=1.0 / dim_x,
@@ -86,31 +113,17 @@ class Cloth:
86
113
  for i in range(self.sim_steps + 1):
87
114
  self.states.append(self.model.state(requires_grad=True))
88
115
 
89
- if self.render:
90
- self.stage = wp.sim.render.SimRendererOpenGL(
91
- self.model, os.path.join(os.path.dirname(__file__), "outputs/example_sim_grad_cloth.usd"), scaling=4.0
92
- )
93
-
94
- @wp.kernel
95
- def com_kernel(positions: wp.array(dtype=wp.vec3), n: int, com: wp.array(dtype=wp.vec3)):
96
- tid = wp.tid()
97
-
98
- # compute center of mass
99
- wp.atomic_add(com, 0, positions[tid] / float(n))
100
-
101
- @wp.kernel
102
- def loss_kernel(com: wp.array(dtype=wp.vec3), target: wp.vec3, loss: wp.array(dtype=float)):
103
- # sq. distance to target
104
- delta = com[0] - target
105
-
106
- loss[0] = wp.dot(delta, delta)
116
+ self.renderer = wp.sim.render.SimRenderer(self.model, stage, scaling=4.0)
107
117
 
108
- @wp.kernel
109
- def step_kernel(x: wp.array(dtype=wp.vec3), grad: wp.array(dtype=wp.vec3), alpha: float):
110
- tid = wp.tid()
111
-
112
- # gradient descent step
113
- x[tid] = x[tid] - grad[tid] * alpha
118
+ # capture forward/backward passes
119
+ wp.capture_begin(self.device)
120
+ try:
121
+ self.tape = wp.Tape()
122
+ with self.tape:
123
+ self.compute_loss()
124
+ self.tape.backward(self.loss)
125
+ finally:
126
+ self.graph = wp.capture_end(self.device)
114
127
 
115
128
  def compute_loss(self):
116
129
  # run control loop
@@ -122,92 +135,65 @@ class Cloth:
122
135
  # compute loss on final state
123
136
  self.com.zero_()
124
137
  wp.launch(
125
- self.com_kernel,
138
+ com_kernel,
126
139
  dim=self.model.particle_count,
127
140
  inputs=[self.states[-1].particle_q, self.model.particle_count, self.com],
128
141
  device=self.device,
129
142
  )
130
- wp.launch(self.loss_kernel, dim=1, inputs=[self.com, self.target, self.loss], device=self.device)
143
+ wp.launch(loss_kernel, dim=1, inputs=[self.com, self.target, self.loss], device=self.device)
131
144
 
132
145
  return self.loss
133
146
 
134
- def render(self, iter):
135
- # render every 4 iters
136
- if iter % 4 > 0:
137
- return
138
-
139
- # draw trajectory
140
- traj_verts = [self.states[0].particle_q.numpy().mean(axis=0)]
141
-
142
- for i in range(0, self.sim_steps, self.sim_substeps):
143
- traj_verts.append(self.states[i].particle_q.numpy().mean(axis=0))
144
-
145
- self.stage.begin_frame(self.render_time)
146
- self.stage.render(self.states[i])
147
- self.stage.render_box(pos=self.target, rot=wp.quat_identity(), extents=(0.1, 0.1, 0.1), name="target")
148
- self.stage.render_line_strip(
149
- vertices=traj_verts,
150
- color=wp.render.bourke_color_map(0.0, 269.0, self.loss.numpy()[0]),
151
- radius=0.02,
152
- name=f"traj_{iter}",
153
- )
154
- self.stage.end_frame()
155
-
156
- self.render_time += self.frame_dt
157
-
158
- def train(self, mode="gd"):
159
- tape = wp.Tape()
160
-
161
- for i in range(self.train_iters):
162
- with wp.ScopedTimer("Forward", active=self.profile):
163
- with tape:
164
- self.compute_loss()
147
+ def update(self):
148
+ with wp.ScopedTimer("Step", active=self.profile):
149
+ wp.capture_launch(self.graph)
165
150
 
166
- with wp.ScopedTimer("Backward", active=self.profile):
167
- tape.backward(self.loss)
151
+ # gradient descent step
152
+ x = self.states[0].particle_qd
168
153
 
169
- with wp.ScopedTimer("Render", active=self.profile):
170
- self.render(i)
154
+ if self.verbose:
155
+ print(f"Iter: {self.iter} Loss: {self.loss}")
171
156
 
172
- with wp.ScopedTimer("Step", active=self.profile):
173
- x = self.states[0].particle_qd
174
- x_grad = tape.gradients[self.states[0].particle_qd]
157
+ wp.launch(step_kernel, dim=len(x), inputs=[x, x.grad, self.train_rate], device=self.device)
175
158
 
176
- print(f"Iter: {i} Loss: {self.loss}")
159
+ # clear grads for next iteration
160
+ self.tape.zero()
177
161
 
178
- wp.launch(self.step_kernel, dim=len(x), inputs=[x, x_grad, self.train_rate], device=self.device)
162
+ self.iter = self.iter + 1
179
163
 
180
- tape.reset()
164
+ def render(self):
165
+ with wp.ScopedTimer("Render", active=self.profile):
166
+ # draw trajectory
167
+ traj_verts = [self.states[0].particle_q.numpy().mean(axis=0)]
181
168
 
182
- def train_graph(self, mode="gd"):
183
- wp.capture_begin()
169
+ for i in range(0, self.sim_steps, self.sim_substeps):
170
+ traj_verts.append(self.states[i].particle_q.numpy().mean(axis=0))
184
171
 
185
- tape = wp.Tape()
186
- with tape:
187
- self.compute_loss()
172
+ self.renderer.begin_frame(self.render_time)
173
+ self.renderer.render(self.states[i])
174
+ self.renderer.render_box(
175
+ pos=self.target, rot=wp.quat_identity(), extents=(0.1, 0.1, 0.1), name="target"
176
+ )
177
+ self.renderer.render_line_strip(
178
+ vertices=traj_verts,
179
+ color=wp.render.bourke_color_map(0.0, 269.0, self.loss.numpy()[0]),
180
+ radius=0.02,
181
+ name=f"traj_{self.iter-1}",
182
+ )
183
+ self.renderer.end_frame()
188
184
 
189
- tape.backward(self.loss)
185
+ self.render_time += self.frame_dt
190
186
 
191
- self.graph = wp.capture_end()
192
187
 
193
- for i in range(self.train_iters):
194
- with wp.ScopedTimer("Replay", active=self.profile):
195
- wp.capture_launch(self.graph)
196
-
197
- with wp.ScopedTimer("Render", active=self.profile):
198
- self.render(i)
199
-
200
- with wp.ScopedTimer("Step", active=self.profile):
201
- x = self.states[0].particle_qd
202
-
203
- print(f"Iter: {i} Loss: {self.loss}")
204
-
205
- wp.launch(self.step_kernel, dim=len(x), inputs=[x, x.grad, self.train_rate], device=self.device)
206
-
207
- tape.zero()
208
-
209
- self.stage.save()
188
+ if __name__ == "__main__":
189
+ stage_path = os.path.join(os.path.dirname(__file__), "outputs/example_sim_grad_cloth.usd")
190
+ example = Example(stage_path, profile=False, verbose=True)
210
191
 
192
+ # replay and optimize
193
+ for i in range(example.train_iters):
194
+ example.update()
195
+ # render every 4 iters
196
+ if i % 4 == 0:
197
+ example.render()
211
198
 
212
- bounce = Cloth(profile=False, render=True)
213
- bounce.train_graph("gd")
199
+ example.renderer.save()
@@ -44,9 +44,9 @@ class Example:
44
44
  cell_x=self.radius * 2.0,
45
45
  cell_y=self.radius * 2.0,
46
46
  cell_z=self.radius * 2.0,
47
- pos=(0.0, 1.0, 0.0),
47
+ pos=wp.vec3(0.0, 1.0, 0.0),
48
48
  rot=wp.quat_identity(),
49
- vel=(5.0, 0.0, 0.0),
49
+ vel=wp.vec3(5.0, 0.0, 0.0),
50
50
  mass=0.1,
51
51
  jitter=self.radius * 0.1,
52
52
  )
@@ -68,10 +68,11 @@ class Example:
68
68
  with wp.ScopedTimer("simulate", active=True):
69
69
  self.model.particle_grid.build(self.state_0.particle_q, self.radius * 2.0)
70
70
 
71
- for s in range(self.sim_substeps):
71
+ for _ in range(self.sim_substeps):
72
72
  self.state_0.clear_forces()
73
73
 
74
74
  self.integrator.simulate(self.model, self.state_0, self.state_1, self.sim_dt)
75
+ self.sim_time += self.frame_dt
75
76
 
76
77
  # swap states
77
78
  (self.state_0, self.state_1) = (self.state_1, self.state_0)
@@ -84,15 +85,13 @@ class Example:
84
85
  self.renderer.render(self.state_0)
85
86
  self.renderer.end_frame()
86
87
 
87
- self.sim_time += self.frame_dt
88
-
89
88
 
90
89
  if __name__ == "__main__":
91
90
  stage_path = os.path.join(os.path.dirname(__file__), "outputs/example_sim_granular.usd")
92
91
 
93
92
  example = Example(stage_path)
94
93
 
95
- for i in range(example.frame_count):
94
+ for _ in range(example.frame_count):
96
95
  example.update()
97
96
  example.render()
98
97