warp-lang 1.0.0b2__py3-none-manylinux2014_x86_64.whl → 1.0.0b6__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.
Files changed (269) 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.so +0 -0
  57. warp/bin/warp.so +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/fem/field/discrete_field.py +0 -80
  257. warp/fem/space/nodal_function_space.py +0 -233
  258. warp/tests/test_all.py +0 -223
  259. warp/tests/test_array_scan.py +0 -60
  260. warp/tests/test_base.py +0 -208
  261. warp/tests/test_unresolved_func.py +0 -7
  262. warp/tests/test_unresolved_symbol.py +0 -7
  263. warp_lang-1.0.0b2.dist-info/METADATA +0 -26
  264. warp_lang-1.0.0b2.dist-info/RECORD +0 -378
  265. /warp/tests/{test_compile_consts_dummy.py → aux_test_compile_consts_dummy.py} +0 -0
  266. /warp/tests/{test_reference_reference.py → aux_test_reference_reference.py} +0 -0
  267. /warp/tests/{test_square.py → aux_test_square.py} +0 -0
  268. {warp_lang-1.0.0b2.dist-info → warp_lang-1.0.0b6.dist-info}/LICENSE.md +0 -0
  269. {warp_lang-1.0.0b2.dist-info → warp_lang-1.0.0b6.dist-info}/top_level.txt +0 -0
@@ -23,15 +23,15 @@ import warp.sim
23
23
  import warp.sim.render
24
24
  from warp.optim import Adam
25
25
 
26
- import matplotlib.pyplot as plt
27
-
28
26
  wp.init()
29
27
 
30
28
 
31
29
  @wp.kernel
32
- def loss_l2(states: wp.array(dtype=wp.float32), targets: wp.array(dtype=wp.float32), loss: wp.array(dtype=wp.float32)):
33
- i = wp.tid()
34
- diff = states[i] - targets[i]
30
+ def loss_l2(
31
+ states: wp.array2d(dtype=wp.float32), targets: wp.array2d(dtype=wp.float32), loss: wp.array(dtype=wp.float32)
32
+ ):
33
+ i, j = wp.tid()
34
+ diff = states[i, j] - targets[i, j]
35
35
  l = diff * diff
36
36
  wp.atomic_add(loss, 0, l)
37
37
 
@@ -44,23 +44,25 @@ def apply_torque(torques: wp.array(dtype=wp.float32), start_index: int, body_f:
44
44
 
45
45
 
46
46
  @wp.kernel
47
- def save_state(body_q: wp.array(dtype=wp.transform), start_index: int, states: wp.array(dtype=wp.float32)):
47
+ def save_state(body_q: wp.array(dtype=wp.transform), write_index: int, states: wp.array2d(dtype=wp.float32)):
48
48
  pos = wp.transform_get_translation(body_q[0])
49
- states[start_index + 0] = pos[0]
50
- states[start_index + 1] = pos[2]
49
+ states[write_index, 0] = pos[0]
50
+ states[write_index, 1] = pos[2]
51
+
51
52
 
53
+ class Example:
54
+ def __init__(self, stage, device=None, verbose=False):
55
+ self.verbose = verbose
56
+ self.frame_dt = 1.0 / 60.0
57
+ self.episode_frames = 100
52
58
 
53
- class Environment:
54
- frame_dt = 1.0 / 60.0
55
- episode_frames = 100
59
+ self.sim_substeps = 1
60
+ self.sim_dt = self.frame_dt / self.sim_substeps
56
61
 
57
- sim_substeps = 1
58
- sim_dt = frame_dt / sim_substeps
62
+ self.render_time = 0.0
59
63
 
60
- sim_time = 0.0
61
- render_time = 0.0
64
+ self.iter = 0
62
65
 
63
- def __init__(self, device="cpu"):
64
66
  builder = wp.sim.ModelBuilder()
65
67
 
66
68
  self.device = device
@@ -69,7 +71,7 @@ class Environment:
69
71
  builder = wp.sim.ModelBuilder(gravity=0.0)
70
72
  builder.add_articulation()
71
73
  b = builder.add_body(origin=wp.transform())
72
- s = builder.add_shape_box(pos=(0.0, 0.0, 0.0), hx=0.5, hy=0.5, hz=0.5, density=100.0, body=b)
74
+ builder.add_shape_box(pos=wp.vec3(0.0, 0.0, 0.0), hx=0.5, hy=0.5, hz=0.5, density=100.0, body=b)
73
75
 
74
76
  # compute reference trajectory
75
77
  rad = np.linspace(0.0, np.pi * 2, self.episode_frames)
@@ -78,7 +80,8 @@ class Environment:
78
80
  # set initial joint configuration to first reference state
79
81
  builder.body_q[0] = wp.transform(p=[self.ref_traj[0][0], 0.0, self.ref_traj[0][1]])
80
82
 
81
- self.ref_traj = wp.array(self.ref_traj.flatten(), dtype=wp.float32, device=self.device, requires_grad=True)
83
+ self.ref_traj = wp.array(self.ref_traj, dtype=wp.float32, device=self.device, requires_grad=True)
84
+ self.last_traj = wp.empty_like(self.ref_traj)
82
85
 
83
86
  # finalize model
84
87
  self.model = builder.finalize(device, requires_grad=True)
@@ -93,127 +96,126 @@ class Environment:
93
96
  self.action_dim = 2
94
97
  self.state_dim = 2
95
98
 
96
- assert len(self.ref_traj) == self.episode_frames * self.state_dim
99
+ assert self.ref_traj.shape == (self.episode_frames, self.state_dim)
97
100
 
98
101
  self.integrator = wp.sim.SemiImplicitIntegrator()
99
102
 
100
- def simulate(self, state: wp.sim.State, action: wp.array, action_index: int, requires_grad=False) -> wp.sim.State:
103
+ # initial guess
104
+ self.actions = wp.array(
105
+ np.zeros(self.episode_frames * self.action_dim) * 100.0,
106
+ dtype=wp.float32,
107
+ device=self.device,
108
+ requires_grad=True,
109
+ )
110
+
111
+ self.optimizer = Adam([self.actions], lr=1e2)
112
+ self.loss = wp.zeros(1, dtype=wp.float32, device=self.device, requires_grad=True)
113
+
114
+ self.renderer = wp.sim.render.SimRenderer(self.model, stage, scaling=100.0)
115
+
116
+ # allocate sim states for trajectory
117
+ self.states = []
118
+ for _ in range(self.episode_frames + 1):
119
+ self.states.append(self.model.state(requires_grad=True))
120
+
121
+ def compute_loss(self):
101
122
  """
102
- Simulate the system for the given states.
123
+ Advances the system dynamics given the rigid-body state in maximal coordinates and generalized joint torques
124
+ [body_q, body_qd, tau].
103
125
  """
104
126
 
105
- for _ in range(self.sim_substeps):
106
- if requires_grad:
127
+ self.last_traj.zero_()
128
+
129
+ for i in range(self.episode_frames):
130
+ state = self.states[i]
131
+
132
+ for _ in range(self.sim_substeps):
107
133
  next_state = self.model.state(requires_grad=True)
108
- else:
109
- next_state = state
110
- next_state.clear_forces()
111
-
112
- wp.sim.collide(self.model, state)
113
- # apply generalized torques to rigid body here, instead of planar joints
114
- wp.launch(apply_torque, 1, inputs=[action, action_index], outputs=[state.body_f], device=action.device)
115
- state = self.integrator.simulate(self.model, state, next_state, self.sim_dt, requires_grad=requires_grad)
116
- return state
117
-
118
- def _render(self, state: wp.sim.State):
119
- self.renderer.begin_frame(self.render_time)
120
- self.renderer.render(state)
121
- self.renderer.end_frame()
122
- self.render_time += self.frame_dt
123
- self.renderer.save()
124
-
125
- def forward(self, actions: wp.array, requires_grad=False, loss=None, render=False):
126
- """
127
- Advances the system dynamics given the rigid-body state in maximal coordinates and generalized joint torques [body_q, body_qd, tau].
128
- Simulates for the set number of substeps and returns the next state in maximal and (optional) generalized coordinates [body_q_next, body_qd_next, joint_q_next, joint_qd_next].
129
- """
130
134
 
131
- actions.requires_grad = requires_grad
132
- state = self.model.state(requires_grad=requires_grad)
133
- if render:
134
- # set up Usd renderer
135
- self.renderer = wp.sim.render.SimRenderer(
136
- self.model, os.path.join(os.path.dirname(__file__), "outputs/example_sim_trajopt.usd"), scaling=100.0
137
- )
138
- self.render_time = 0.0
139
- self._render(state)
135
+ wp.sim.collide(self.model, state)
140
136
 
141
- states = wp.zeros(
142
- self.episode_frames * self.state_dim, dtype=wp.float32, device=self.device, requires_grad=requires_grad
143
- )
137
+ # apply generalized torques to rigid body here, instead of planar joints
138
+ wp.launch(
139
+ apply_torque,
140
+ 1,
141
+ inputs=[self.actions, i * self.action_dim],
142
+ outputs=[state.body_f],
143
+ device=self.device,
144
+ )
144
145
 
145
- for i in range(self.episode_frames):
146
- # simulate
147
- next_state = self.simulate(state, actions, action_index=i * self.action_dim, requires_grad=requires_grad)
146
+ state = self.integrator.simulate(self.model, state, next_state, self.sim_dt, requires_grad=True)
147
+
148
+ self.states[i + 1] = state
148
149
 
149
150
  # save state
150
151
  wp.launch(
151
- save_state, dim=1, inputs=[next_state.body_q, i * self.state_dim], outputs=[states], device=self.device
152
+ save_state,
153
+ dim=1,
154
+ inputs=[self.states[i + 1].body_q, i],
155
+ outputs=[self.last_traj],
156
+ device=self.device,
152
157
  )
153
158
 
154
- # update state
155
- state = next_state
156
-
157
- if render:
158
- self._render(state)
159
-
160
159
  # compute loss
161
- if loss is None:
162
- loss = wp.zeros(1, dtype=wp.float32, device=self.device, requires_grad=requires_grad)
163
160
  wp.launch(
164
161
  loss_l2,
165
- dim=self.state_dim * self.episode_frames,
166
- inputs=[states, self.ref_traj],
167
- outputs=[loss],
162
+ dim=self.last_traj.shape,
163
+ inputs=[self.last_traj, self.ref_traj],
164
+ outputs=[self.loss],
168
165
  device=self.device,
169
166
  )
170
167
 
171
- return states
168
+ def update(self):
169
+ """Runs a single optimizer iteration"""
170
+ self.loss.zero_()
171
+ tape = wp.Tape()
172
+ with tape:
173
+ self.compute_loss()
172
174
 
173
- def optimize(self, num_iter=100, lr=0.01):
174
- # initial guess
175
- actions = wp.array(
176
- np.zeros(self.episode_frames * self.action_dim) * 100.0,
177
- dtype=wp.float32,
178
- device=self.device,
179
- requires_grad=True,
180
- )
175
+ if self.verbose and (self.iter + 1) % 10 == 0:
176
+ print(f"Iter {self.iter+1} Loss: {self.loss.numpy()[0]:.3f}")
181
177
 
182
- optimizer = Adam([actions], lr=lr)
183
- loss = wp.zeros(1, dtype=wp.float32, device=self.device, requires_grad=True)
178
+ tape.backward(loss=self.loss)
184
179
 
185
- # optimize
186
- for i in range(1, num_iter + 1):
187
- loss.zero_()
188
- tape = wp.Tape()
189
- with tape:
190
- self.forward(actions, requires_grad=True, loss=loss)
180
+ # print("action grad", self.actions.grad.numpy())
181
+ assert not np.isnan(self.actions.grad.numpy()).any(), "NaN in gradient"
191
182
 
192
- if i % 10 == 0:
193
- print(f"iter {i}/{num_iter} loss: {loss.numpy()[0]:.3f}")
183
+ self.optimizer.step([self.actions.grad])
184
+ tape.zero()
185
+ self.iter = self.iter + 1
186
+
187
+ def render(self):
188
+ for i in range(self.episode_frames):
189
+ self.renderer.begin_frame(self.render_time)
190
+ self.renderer.render(self.states[i + 1])
191
+ self.renderer.end_frame()
192
+ self.render_time += self.frame_dt
194
193
 
195
- tape.backward(loss=loss)
196
- # print("action grad", actions.grad.numpy())
197
- assert not np.isnan(actions.grad.numpy()).any(), "NaN in gradient"
198
- optimizer.step([actions.grad])
199
- tape.zero()
200
194
 
201
- return actions
195
+ if __name__ == "__main__":
196
+ import matplotlib.pyplot as plt
202
197
 
198
+ stage_path = os.path.join(os.path.dirname(__file__), "outputs/example_sim_trajopt.usd")
199
+ example = Example(stage_path, device=wp.get_preferred_device(), verbose=True)
203
200
 
204
- np.set_printoptions(precision=4, linewidth=2000, suppress=True)
201
+ # Optimize
202
+ num_iter = 250
205
203
 
206
- sim = Environment(device=wp.get_preferred_device())
204
+ for i in range(num_iter):
205
+ example.update()
207
206
 
208
- best_actions = sim.optimize(num_iter=250, lr=1e2)
209
- # render
210
- opt_traj = sim.forward(best_actions, render=True)
207
+ # Render every 25 iters
208
+ if i % 25 == 0:
209
+ example.render()
211
210
 
212
- np_states = opt_traj.numpy().reshape((-1, 2))
213
- np_ref = sim.ref_traj.numpy().reshape((-1, 2))
214
- plt.plot(np_ref[:, 0], np_ref[:, 1], label="reference")
215
- plt.plot(np_states[:, 0], np_states[:, 1], label="optimized")
216
- plt.grid()
217
- plt.legend()
218
- plt.axis("equal")
219
- plt.show()
211
+ example.renderer.save()
212
+
213
+ np_states = example.last_traj.numpy()
214
+ np_ref = example.ref_traj.numpy()
215
+ plt.plot(np_ref[:, 0], np_ref[:, 1], label="Reference Trajectory")
216
+ plt.plot(np_states[:, 0], np_states[:, 1], label="Optimized Trajectory")
217
+ plt.grid()
218
+ plt.legend()
219
+ plt.axis("equal")
220
+ plt.show()
221
+ #
examples/example_sph.py CHANGED
@@ -6,26 +6,27 @@
6
6
  # license agreement from NVIDIA CORPORATION is strictly prohibited.
7
7
 
8
8
  ###########################################################################
9
- # Example Smooth Particle Hydrodynamics
9
+ # Example Smoothed Particle Hydrodynamics
10
+ #
11
+ # Shows how to implement a SPH fluid simulation.
10
12
  #
11
- # Shows how to implement a SPH
12
13
  # Neighbors are found using the wp.HashGrid class, and
13
14
  # wp.hash_grid_query(), wp.hash_grid_query_next() kernel methods.
14
15
  #
15
16
  # Reference Publication
16
- # Müller, Matthias, David Charypar, and Markus H. Gross.
17
+ # Matthias Müller, David Charypar, and Markus H. Gross.
17
18
  # "Particle-based fluid simulation for interactive applications."
18
19
  # Symposium on Computer animation. Vol. 2. 2003.
19
20
  #
20
21
  ###########################################################################
21
22
 
23
+ import os
24
+
22
25
  import numpy as np
23
26
 
24
27
  import warp as wp
25
28
  import warp.render
26
29
 
27
- import os
28
-
29
30
  wp.init()
30
31
 
31
32
 
@@ -314,7 +315,7 @@ class Example:
314
315
 
315
316
  def update(self):
316
317
  with wp.ScopedTimer("simulate", active=True):
317
- for s in range(self.sim_step_to_frame_ratio):
318
+ for _ in range(self.sim_step_to_frame_ratio):
318
319
  with wp.ScopedTimer("grid build", active=False):
319
320
  # build grid
320
321
  self.grid.build(self.x, self.smoothing_length)
@@ -359,6 +360,8 @@ class Example:
359
360
  # drift
360
361
  wp.launch(kernel=drift, dim=self.n, inputs=[self.x, self.v, self.dt])
361
362
 
363
+ self.sim_time += self.frame_dt
364
+
362
365
  def render(self, is_live=False):
363
366
  with wp.ScopedTimer("render", active=True):
364
367
  time = 0.0 if is_live else self.sim_time
@@ -367,8 +370,6 @@ class Example:
367
370
  self.renderer.render_points(points=self.x.numpy(), radius=self.smoothing_length, name="points")
368
371
  self.renderer.end_frame()
369
372
 
370
- self.sim_time += self.frame_dt
371
-
372
373
 
373
374
  if __name__ == "__main__":
374
375
  stage_path = os.path.join(os.path.dirname(__file__), "outputs/example_sph.usd")
examples/example_wave.py CHANGED
@@ -13,8 +13,8 @@
13
13
  #
14
14
  ###########################################################################
15
15
 
16
- import os
17
16
  import math
17
+ import os
18
18
 
19
19
  import warp as wp
20
20
  import warp.render
@@ -111,9 +111,9 @@ def grid_update(heights: wp.array(dtype=float), vertices: wp.array(dtype=wp.vec3
111
111
 
112
112
 
113
113
  class Example:
114
- def __init__(self, stage):
115
- self.sim_width = 128
116
- self.sim_height = 128
114
+ def __init__(self, stage, resx, resy):
115
+ self.sim_width = resx
116
+ self.sim_height = resy
117
117
 
118
118
  self.sim_fps = 60.0
119
119
  self.sim_substeps = 16
@@ -163,14 +163,14 @@ class Example:
163
163
  self.sim_grid1 = wp.zeros(self.sim_width * self.sim_height, dtype=float)
164
164
  self.sim_verts = wp.array(vertices, dtype=wp.vec3)
165
165
 
166
- # create surface displacment around a point
166
+ # create surface displacement around a point
167
167
  self.cx = self.sim_width / 2 + math.sin(self.sim_time) * self.sim_width / 3
168
168
  self.cy = self.sim_height / 2 + math.cos(self.sim_time) * self.sim_height / 3
169
169
 
170
170
  def update(self):
171
171
  with wp.ScopedTimer("simulate", active=True):
172
172
  for s in range(self.sim_substeps):
173
- # create surface displacment around a point
173
+ # create surface displacement around a point
174
174
  self.cx = self.sim_width / 2 + math.sin(self.sim_time) * self.sim_width / 3
175
175
  self.cy = self.sim_height / 2 + math.cos(self.sim_time) * self.sim_height / 3
176
176
 
@@ -235,7 +235,7 @@ class Example:
235
235
  if __name__ == "__main__":
236
236
  stage_path = os.path.join(os.path.dirname(__file__), "outputs/example_wave.usd")
237
237
 
238
- example = Example(stage_path)
238
+ example = Example(stage_path, resx=128, resy=128)
239
239
 
240
240
  for i in range(example.sim_frames):
241
241
  example.update()
examples/fem/bsr_utils.py CHANGED
@@ -6,17 +6,14 @@ import warp.types
6
6
  from warp.sparse import BsrMatrix, bsr_zeros, bsr_get_diag, bsr_mv
7
7
  from warp.utils import array_inner
8
8
 
9
- try:
10
- from scipy.sparse import csr_array, bsr_array
11
- except ImportError:
12
- # WAR for older scipy
9
+
10
+ def bsr_to_scipy(matrix: BsrMatrix) -> "scipy.sparse.bsr_array":
13
11
  try:
14
- from scipy.sparse import csr_matrix as csr_array, bsr_matrix as bsr_array
12
+ from scipy.sparse import csr_array, bsr_array
15
13
  except ImportError:
16
- pass
17
-
14
+ # WAR for older scipy
15
+ from scipy.sparse import csr_matrix as csr_array, bsr_matrix as bsr_array
18
16
 
19
- def bsr_to_scipy(matrix: BsrMatrix) -> "bsr_array":
20
17
  if matrix.block_shape == (1, 1):
21
18
  return csr_array(
22
19
  (
@@ -37,7 +34,13 @@ def bsr_to_scipy(matrix: BsrMatrix) -> "bsr_array":
37
34
  )
38
35
 
39
36
 
40
- def scipy_to_bsr(sp: Union["bsr_array", "csr_array"], device=None, dtype=None) -> BsrMatrix:
37
+ def scipy_to_bsr(sp: Union["scipy.sparse.bsr_array", "scipy.sparse.csr_array"], device=None, dtype=None) -> BsrMatrix:
38
+ try:
39
+ from scipy.sparse import csr_array
40
+ except ImportError:
41
+ # WAR for older scipy
42
+ from scipy.sparse import csr_matrix as csr_array
43
+
41
44
  if dtype is None:
42
45
  dtype = warp.types.np_dtype_to_warp_type[sp.dtype]
43
46
 
@@ -68,9 +71,11 @@ def _bsr_cg_kernel_1(
68
71
  Ap: wp.array(dtype=Any),
69
72
  ):
70
73
  i = wp.tid()
71
- alpha = rs_old[0] / p_Ap[0]
72
- x[i] = x[i] + alpha * p[i]
73
- r[i] = r[i] - alpha * Ap[i]
74
+
75
+ if p_Ap[0] != 0.0:
76
+ alpha = rs_old[0] / p_Ap[0]
77
+ x[i] = x[i] + alpha * p[i]
78
+ r[i] = r[i] - alpha * Ap[i]
74
79
 
75
80
 
76
81
  @wp.kernel
@@ -133,6 +138,7 @@ def bsr_cg(
133
138
  use_diag_precond=True,
134
139
  mv_routine=bsr_mv,
135
140
  device=None,
141
+ quiet=False,
136
142
  ) -> Tuple[float, int]:
137
143
  """Solves the linear system A x = b using the Conjugate Gradient method, optionally with diagonal preconditioning
138
144
 
@@ -217,7 +223,8 @@ def bsr_cg(
217
223
 
218
224
  if ((i + 1) % check_every) == 0:
219
225
  err = rz_new.numpy()[0]
220
- print(f"At iteration {i} error = \t {err} \t tol: {tol_sq}")
226
+ if not quiet:
227
+ print(f"At iteration {i} error = \t {err} \t tol: {tol_sq}")
221
228
  if err <= tol_sq:
222
229
  end_iter = i
223
230
  break
@@ -231,17 +238,23 @@ def bsr_cg(
231
238
 
232
239
  err = rz_old.numpy()[0]
233
240
 
234
- print(f"Terminated after {end_iter} iterations with error = \t {err}")
241
+ if not quiet:
242
+ print(f"Terminated after {end_iter} iterations with error = \t {err}")
235
243
  return err, end_iter
236
244
 
237
245
 
238
246
  def invert_diagonal_bsr_mass_matrix(A: BsrMatrix):
239
247
  """Inverts each block of a block-diagonal mass matrix"""
240
248
 
241
- wp.launch(kernel=_block_diagonal_mass_invert, dim=A.nrow, inputs=[A.values], device=A.values.device)
249
+ scale = A.scalar_type(A.block_shape[0])
250
+ values = A.values
251
+ if not wp.types.type_is_matrix(values.dtype):
252
+ values = values.view(dtype=wp.mat(shape=(1, 1), dtype=A.scalar_type))
253
+
254
+ wp.launch(kernel=_block_diagonal_mass_invert, dim=A.nrow, inputs=[values, scale], device=values.device)
242
255
 
243
256
 
244
257
  @wp.kernel
245
- def _block_diagonal_mass_invert(values: wp.array(dtype=Any)):
258
+ def _block_diagonal_mass_invert(values: wp.array(dtype=Any), scale: Any):
246
259
  i = wp.tid()
247
- values[i] = values[i] / wp.ddot(values[i], values[i])
260
+ values[i] = scale * values[i] / wp.ddot(values[i], values[i])