warp-lang 1.7.0__py3-none-manylinux_2_34_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 (429) hide show
  1. warp/__init__.py +139 -0
  2. warp/__init__.pyi +1 -0
  3. warp/autograd.py +1142 -0
  4. warp/bin/warp-clang.so +0 -0
  5. warp/bin/warp.so +0 -0
  6. warp/build.py +557 -0
  7. warp/build_dll.py +405 -0
  8. warp/builtins.py +6855 -0
  9. warp/codegen.py +3969 -0
  10. warp/config.py +158 -0
  11. warp/constants.py +57 -0
  12. warp/context.py +6812 -0
  13. warp/dlpack.py +462 -0
  14. warp/examples/__init__.py +24 -0
  15. warp/examples/assets/bear.usd +0 -0
  16. warp/examples/assets/bunny.usd +0 -0
  17. warp/examples/assets/cartpole.urdf +110 -0
  18. warp/examples/assets/crazyflie.usd +0 -0
  19. warp/examples/assets/cube.usd +0 -0
  20. warp/examples/assets/nonuniform.usd +0 -0
  21. warp/examples/assets/nv_ant.xml +92 -0
  22. warp/examples/assets/nv_humanoid.xml +183 -0
  23. warp/examples/assets/nvidia_logo.png +0 -0
  24. warp/examples/assets/pixel.jpg +0 -0
  25. warp/examples/assets/quadruped.urdf +268 -0
  26. warp/examples/assets/rocks.nvdb +0 -0
  27. warp/examples/assets/rocks.usd +0 -0
  28. warp/examples/assets/sphere.usd +0 -0
  29. warp/examples/assets/square_cloth.usd +0 -0
  30. warp/examples/benchmarks/benchmark_api.py +389 -0
  31. warp/examples/benchmarks/benchmark_cloth.py +296 -0
  32. warp/examples/benchmarks/benchmark_cloth_cupy.py +96 -0
  33. warp/examples/benchmarks/benchmark_cloth_jax.py +105 -0
  34. warp/examples/benchmarks/benchmark_cloth_numba.py +161 -0
  35. warp/examples/benchmarks/benchmark_cloth_numpy.py +85 -0
  36. warp/examples/benchmarks/benchmark_cloth_paddle.py +94 -0
  37. warp/examples/benchmarks/benchmark_cloth_pytorch.py +94 -0
  38. warp/examples/benchmarks/benchmark_cloth_taichi.py +120 -0
  39. warp/examples/benchmarks/benchmark_cloth_warp.py +153 -0
  40. warp/examples/benchmarks/benchmark_gemm.py +164 -0
  41. warp/examples/benchmarks/benchmark_interop_paddle.py +166 -0
  42. warp/examples/benchmarks/benchmark_interop_torch.py +166 -0
  43. warp/examples/benchmarks/benchmark_launches.py +301 -0
  44. warp/examples/benchmarks/benchmark_tile_load_store.py +103 -0
  45. warp/examples/browse.py +37 -0
  46. warp/examples/core/example_cupy.py +86 -0
  47. warp/examples/core/example_dem.py +241 -0
  48. warp/examples/core/example_fluid.py +299 -0
  49. warp/examples/core/example_graph_capture.py +150 -0
  50. warp/examples/core/example_marching_cubes.py +194 -0
  51. warp/examples/core/example_mesh.py +180 -0
  52. warp/examples/core/example_mesh_intersect.py +211 -0
  53. warp/examples/core/example_nvdb.py +182 -0
  54. warp/examples/core/example_raycast.py +111 -0
  55. warp/examples/core/example_raymarch.py +205 -0
  56. warp/examples/core/example_render_opengl.py +193 -0
  57. warp/examples/core/example_sample_mesh.py +300 -0
  58. warp/examples/core/example_sph.py +411 -0
  59. warp/examples/core/example_torch.py +211 -0
  60. warp/examples/core/example_wave.py +269 -0
  61. warp/examples/fem/example_adaptive_grid.py +286 -0
  62. warp/examples/fem/example_apic_fluid.py +423 -0
  63. warp/examples/fem/example_burgers.py +261 -0
  64. warp/examples/fem/example_convection_diffusion.py +178 -0
  65. warp/examples/fem/example_convection_diffusion_dg.py +204 -0
  66. warp/examples/fem/example_deformed_geometry.py +172 -0
  67. warp/examples/fem/example_diffusion.py +196 -0
  68. warp/examples/fem/example_diffusion_3d.py +225 -0
  69. warp/examples/fem/example_diffusion_mgpu.py +220 -0
  70. warp/examples/fem/example_distortion_energy.py +228 -0
  71. warp/examples/fem/example_magnetostatics.py +240 -0
  72. warp/examples/fem/example_mixed_elasticity.py +291 -0
  73. warp/examples/fem/example_navier_stokes.py +261 -0
  74. warp/examples/fem/example_nonconforming_contact.py +298 -0
  75. warp/examples/fem/example_stokes.py +213 -0
  76. warp/examples/fem/example_stokes_transfer.py +262 -0
  77. warp/examples/fem/example_streamlines.py +352 -0
  78. warp/examples/fem/utils.py +1000 -0
  79. warp/examples/interop/example_jax_callable.py +116 -0
  80. warp/examples/interop/example_jax_ffi_callback.py +132 -0
  81. warp/examples/interop/example_jax_kernel.py +205 -0
  82. warp/examples/optim/example_bounce.py +266 -0
  83. warp/examples/optim/example_cloth_throw.py +228 -0
  84. warp/examples/optim/example_diffray.py +561 -0
  85. warp/examples/optim/example_drone.py +870 -0
  86. warp/examples/optim/example_fluid_checkpoint.py +497 -0
  87. warp/examples/optim/example_inverse_kinematics.py +182 -0
  88. warp/examples/optim/example_inverse_kinematics_torch.py +191 -0
  89. warp/examples/optim/example_softbody_properties.py +400 -0
  90. warp/examples/optim/example_spring_cage.py +245 -0
  91. warp/examples/optim/example_trajectory.py +227 -0
  92. warp/examples/sim/example_cartpole.py +143 -0
  93. warp/examples/sim/example_cloth.py +225 -0
  94. warp/examples/sim/example_cloth_self_contact.py +322 -0
  95. warp/examples/sim/example_granular.py +130 -0
  96. warp/examples/sim/example_granular_collision_sdf.py +202 -0
  97. warp/examples/sim/example_jacobian_ik.py +244 -0
  98. warp/examples/sim/example_particle_chain.py +124 -0
  99. warp/examples/sim/example_quadruped.py +203 -0
  100. warp/examples/sim/example_rigid_chain.py +203 -0
  101. warp/examples/sim/example_rigid_contact.py +195 -0
  102. warp/examples/sim/example_rigid_force.py +133 -0
  103. warp/examples/sim/example_rigid_gyroscopic.py +115 -0
  104. warp/examples/sim/example_rigid_soft_contact.py +140 -0
  105. warp/examples/sim/example_soft_body.py +196 -0
  106. warp/examples/tile/example_tile_cholesky.py +87 -0
  107. warp/examples/tile/example_tile_convolution.py +66 -0
  108. warp/examples/tile/example_tile_fft.py +55 -0
  109. warp/examples/tile/example_tile_filtering.py +113 -0
  110. warp/examples/tile/example_tile_matmul.py +85 -0
  111. warp/examples/tile/example_tile_mlp.py +383 -0
  112. warp/examples/tile/example_tile_nbody.py +199 -0
  113. warp/examples/tile/example_tile_walker.py +327 -0
  114. warp/fabric.py +355 -0
  115. warp/fem/__init__.py +106 -0
  116. warp/fem/adaptivity.py +508 -0
  117. warp/fem/cache.py +572 -0
  118. warp/fem/dirichlet.py +202 -0
  119. warp/fem/domain.py +411 -0
  120. warp/fem/field/__init__.py +125 -0
  121. warp/fem/field/field.py +619 -0
  122. warp/fem/field/nodal_field.py +326 -0
  123. warp/fem/field/restriction.py +37 -0
  124. warp/fem/field/virtual.py +848 -0
  125. warp/fem/geometry/__init__.py +32 -0
  126. warp/fem/geometry/adaptive_nanogrid.py +857 -0
  127. warp/fem/geometry/closest_point.py +84 -0
  128. warp/fem/geometry/deformed_geometry.py +221 -0
  129. warp/fem/geometry/element.py +776 -0
  130. warp/fem/geometry/geometry.py +362 -0
  131. warp/fem/geometry/grid_2d.py +392 -0
  132. warp/fem/geometry/grid_3d.py +452 -0
  133. warp/fem/geometry/hexmesh.py +911 -0
  134. warp/fem/geometry/nanogrid.py +571 -0
  135. warp/fem/geometry/partition.py +389 -0
  136. warp/fem/geometry/quadmesh.py +663 -0
  137. warp/fem/geometry/tetmesh.py +855 -0
  138. warp/fem/geometry/trimesh.py +806 -0
  139. warp/fem/integrate.py +2335 -0
  140. warp/fem/linalg.py +419 -0
  141. warp/fem/operator.py +293 -0
  142. warp/fem/polynomial.py +229 -0
  143. warp/fem/quadrature/__init__.py +17 -0
  144. warp/fem/quadrature/pic_quadrature.py +299 -0
  145. warp/fem/quadrature/quadrature.py +591 -0
  146. warp/fem/space/__init__.py +228 -0
  147. warp/fem/space/basis_function_space.py +468 -0
  148. warp/fem/space/basis_space.py +667 -0
  149. warp/fem/space/dof_mapper.py +251 -0
  150. warp/fem/space/function_space.py +309 -0
  151. warp/fem/space/grid_2d_function_space.py +177 -0
  152. warp/fem/space/grid_3d_function_space.py +227 -0
  153. warp/fem/space/hexmesh_function_space.py +257 -0
  154. warp/fem/space/nanogrid_function_space.py +201 -0
  155. warp/fem/space/partition.py +367 -0
  156. warp/fem/space/quadmesh_function_space.py +223 -0
  157. warp/fem/space/restriction.py +179 -0
  158. warp/fem/space/shape/__init__.py +143 -0
  159. warp/fem/space/shape/cube_shape_function.py +1105 -0
  160. warp/fem/space/shape/shape_function.py +133 -0
  161. warp/fem/space/shape/square_shape_function.py +926 -0
  162. warp/fem/space/shape/tet_shape_function.py +834 -0
  163. warp/fem/space/shape/triangle_shape_function.py +672 -0
  164. warp/fem/space/tetmesh_function_space.py +271 -0
  165. warp/fem/space/topology.py +424 -0
  166. warp/fem/space/trimesh_function_space.py +194 -0
  167. warp/fem/types.py +99 -0
  168. warp/fem/utils.py +420 -0
  169. warp/jax.py +187 -0
  170. warp/jax_experimental/__init__.py +16 -0
  171. warp/jax_experimental/custom_call.py +351 -0
  172. warp/jax_experimental/ffi.py +698 -0
  173. warp/jax_experimental/xla_ffi.py +602 -0
  174. warp/math.py +244 -0
  175. warp/native/array.h +1145 -0
  176. warp/native/builtin.h +1800 -0
  177. warp/native/bvh.cpp +492 -0
  178. warp/native/bvh.cu +791 -0
  179. warp/native/bvh.h +554 -0
  180. warp/native/clang/clang.cpp +536 -0
  181. warp/native/coloring.cpp +613 -0
  182. warp/native/crt.cpp +51 -0
  183. warp/native/crt.h +362 -0
  184. warp/native/cuda_crt.h +1058 -0
  185. warp/native/cuda_util.cpp +646 -0
  186. warp/native/cuda_util.h +307 -0
  187. warp/native/error.cpp +77 -0
  188. warp/native/error.h +36 -0
  189. warp/native/exports.h +1878 -0
  190. warp/native/fabric.h +245 -0
  191. warp/native/hashgrid.cpp +311 -0
  192. warp/native/hashgrid.cu +87 -0
  193. warp/native/hashgrid.h +240 -0
  194. warp/native/initializer_array.h +41 -0
  195. warp/native/intersect.h +1230 -0
  196. warp/native/intersect_adj.h +375 -0
  197. warp/native/intersect_tri.h +339 -0
  198. warp/native/marching.cpp +19 -0
  199. warp/native/marching.cu +514 -0
  200. warp/native/marching.h +19 -0
  201. warp/native/mat.h +2220 -0
  202. warp/native/mathdx.cpp +87 -0
  203. warp/native/matnn.h +343 -0
  204. warp/native/mesh.cpp +266 -0
  205. warp/native/mesh.cu +404 -0
  206. warp/native/mesh.h +1980 -0
  207. warp/native/nanovdb/GridHandle.h +366 -0
  208. warp/native/nanovdb/HostBuffer.h +590 -0
  209. warp/native/nanovdb/NanoVDB.h +6624 -0
  210. warp/native/nanovdb/PNanoVDB.h +3390 -0
  211. warp/native/noise.h +859 -0
  212. warp/native/quat.h +1371 -0
  213. warp/native/rand.h +342 -0
  214. warp/native/range.h +139 -0
  215. warp/native/reduce.cpp +174 -0
  216. warp/native/reduce.cu +364 -0
  217. warp/native/runlength_encode.cpp +79 -0
  218. warp/native/runlength_encode.cu +61 -0
  219. warp/native/scan.cpp +47 -0
  220. warp/native/scan.cu +53 -0
  221. warp/native/scan.h +23 -0
  222. warp/native/solid_angle.h +466 -0
  223. warp/native/sort.cpp +251 -0
  224. warp/native/sort.cu +277 -0
  225. warp/native/sort.h +33 -0
  226. warp/native/sparse.cpp +378 -0
  227. warp/native/sparse.cu +524 -0
  228. warp/native/spatial.h +657 -0
  229. warp/native/svd.h +702 -0
  230. warp/native/temp_buffer.h +46 -0
  231. warp/native/tile.h +2584 -0
  232. warp/native/tile_reduce.h +264 -0
  233. warp/native/vec.h +1426 -0
  234. warp/native/volume.cpp +501 -0
  235. warp/native/volume.cu +67 -0
  236. warp/native/volume.h +969 -0
  237. warp/native/volume_builder.cu +477 -0
  238. warp/native/volume_builder.h +52 -0
  239. warp/native/volume_impl.h +70 -0
  240. warp/native/warp.cpp +1082 -0
  241. warp/native/warp.cu +3636 -0
  242. warp/native/warp.h +381 -0
  243. warp/optim/__init__.py +17 -0
  244. warp/optim/adam.py +163 -0
  245. warp/optim/linear.py +1137 -0
  246. warp/optim/sgd.py +112 -0
  247. warp/paddle.py +407 -0
  248. warp/render/__init__.py +18 -0
  249. warp/render/render_opengl.py +3518 -0
  250. warp/render/render_usd.py +784 -0
  251. warp/render/utils.py +160 -0
  252. warp/sim/__init__.py +65 -0
  253. warp/sim/articulation.py +793 -0
  254. warp/sim/collide.py +2395 -0
  255. warp/sim/graph_coloring.py +300 -0
  256. warp/sim/import_mjcf.py +790 -0
  257. warp/sim/import_snu.py +227 -0
  258. warp/sim/import_urdf.py +579 -0
  259. warp/sim/import_usd.py +894 -0
  260. warp/sim/inertia.py +324 -0
  261. warp/sim/integrator.py +242 -0
  262. warp/sim/integrator_euler.py +1997 -0
  263. warp/sim/integrator_featherstone.py +2101 -0
  264. warp/sim/integrator_vbd.py +2048 -0
  265. warp/sim/integrator_xpbd.py +3292 -0
  266. warp/sim/model.py +4791 -0
  267. warp/sim/particles.py +121 -0
  268. warp/sim/render.py +427 -0
  269. warp/sim/utils.py +428 -0
  270. warp/sparse.py +2057 -0
  271. warp/stubs.py +3333 -0
  272. warp/tape.py +1203 -0
  273. warp/tests/__init__.py +1 -0
  274. warp/tests/__main__.py +4 -0
  275. warp/tests/assets/curlnoise_golden.npy +0 -0
  276. warp/tests/assets/mlp_golden.npy +0 -0
  277. warp/tests/assets/pixel.npy +0 -0
  278. warp/tests/assets/pnoise_golden.npy +0 -0
  279. warp/tests/assets/spiky.usd +0 -0
  280. warp/tests/assets/test_grid.nvdb +0 -0
  281. warp/tests/assets/test_index_grid.nvdb +0 -0
  282. warp/tests/assets/test_int32_grid.nvdb +0 -0
  283. warp/tests/assets/test_vec_grid.nvdb +0 -0
  284. warp/tests/assets/torus.nvdb +0 -0
  285. warp/tests/assets/torus.usda +105 -0
  286. warp/tests/aux_test_class_kernel.py +34 -0
  287. warp/tests/aux_test_compile_consts_dummy.py +18 -0
  288. warp/tests/aux_test_conditional_unequal_types_kernels.py +29 -0
  289. warp/tests/aux_test_dependent.py +29 -0
  290. warp/tests/aux_test_grad_customs.py +29 -0
  291. warp/tests/aux_test_instancing_gc.py +26 -0
  292. warp/tests/aux_test_module_unload.py +23 -0
  293. warp/tests/aux_test_name_clash1.py +40 -0
  294. warp/tests/aux_test_name_clash2.py +40 -0
  295. warp/tests/aux_test_reference.py +9 -0
  296. warp/tests/aux_test_reference_reference.py +8 -0
  297. warp/tests/aux_test_square.py +16 -0
  298. warp/tests/aux_test_unresolved_func.py +22 -0
  299. warp/tests/aux_test_unresolved_symbol.py +22 -0
  300. warp/tests/cuda/__init__.py +0 -0
  301. warp/tests/cuda/test_async.py +676 -0
  302. warp/tests/cuda/test_ipc.py +124 -0
  303. warp/tests/cuda/test_mempool.py +233 -0
  304. warp/tests/cuda/test_multigpu.py +169 -0
  305. warp/tests/cuda/test_peer.py +139 -0
  306. warp/tests/cuda/test_pinned.py +84 -0
  307. warp/tests/cuda/test_streams.py +634 -0
  308. warp/tests/geometry/__init__.py +0 -0
  309. warp/tests/geometry/test_bvh.py +200 -0
  310. warp/tests/geometry/test_hash_grid.py +221 -0
  311. warp/tests/geometry/test_marching_cubes.py +74 -0
  312. warp/tests/geometry/test_mesh.py +316 -0
  313. warp/tests/geometry/test_mesh_query_aabb.py +399 -0
  314. warp/tests/geometry/test_mesh_query_point.py +932 -0
  315. warp/tests/geometry/test_mesh_query_ray.py +311 -0
  316. warp/tests/geometry/test_volume.py +1103 -0
  317. warp/tests/geometry/test_volume_write.py +346 -0
  318. warp/tests/interop/__init__.py +0 -0
  319. warp/tests/interop/test_dlpack.py +729 -0
  320. warp/tests/interop/test_jax.py +371 -0
  321. warp/tests/interop/test_paddle.py +800 -0
  322. warp/tests/interop/test_torch.py +1001 -0
  323. warp/tests/run_coverage_serial.py +39 -0
  324. warp/tests/sim/__init__.py +0 -0
  325. warp/tests/sim/disabled_kinematics.py +244 -0
  326. warp/tests/sim/flaky_test_sim_grad.py +290 -0
  327. warp/tests/sim/test_collision.py +604 -0
  328. warp/tests/sim/test_coloring.py +258 -0
  329. warp/tests/sim/test_model.py +224 -0
  330. warp/tests/sim/test_sim_grad_bounce_linear.py +212 -0
  331. warp/tests/sim/test_sim_kinematics.py +98 -0
  332. warp/tests/sim/test_vbd.py +597 -0
  333. warp/tests/test_adam.py +163 -0
  334. warp/tests/test_arithmetic.py +1096 -0
  335. warp/tests/test_array.py +2972 -0
  336. warp/tests/test_array_reduce.py +156 -0
  337. warp/tests/test_assert.py +250 -0
  338. warp/tests/test_atomic.py +153 -0
  339. warp/tests/test_bool.py +220 -0
  340. warp/tests/test_builtins_resolution.py +1298 -0
  341. warp/tests/test_closest_point_edge_edge.py +327 -0
  342. warp/tests/test_codegen.py +810 -0
  343. warp/tests/test_codegen_instancing.py +1495 -0
  344. warp/tests/test_compile_consts.py +215 -0
  345. warp/tests/test_conditional.py +252 -0
  346. warp/tests/test_context.py +42 -0
  347. warp/tests/test_copy.py +238 -0
  348. warp/tests/test_ctypes.py +638 -0
  349. warp/tests/test_dense.py +73 -0
  350. warp/tests/test_devices.py +97 -0
  351. warp/tests/test_examples.py +482 -0
  352. warp/tests/test_fabricarray.py +996 -0
  353. warp/tests/test_fast_math.py +74 -0
  354. warp/tests/test_fem.py +2003 -0
  355. warp/tests/test_fp16.py +136 -0
  356. warp/tests/test_func.py +454 -0
  357. warp/tests/test_future_annotations.py +98 -0
  358. warp/tests/test_generics.py +656 -0
  359. warp/tests/test_grad.py +893 -0
  360. warp/tests/test_grad_customs.py +339 -0
  361. warp/tests/test_grad_debug.py +341 -0
  362. warp/tests/test_implicit_init.py +411 -0
  363. warp/tests/test_import.py +45 -0
  364. warp/tests/test_indexedarray.py +1140 -0
  365. warp/tests/test_intersect.py +73 -0
  366. warp/tests/test_iter.py +76 -0
  367. warp/tests/test_large.py +177 -0
  368. warp/tests/test_launch.py +411 -0
  369. warp/tests/test_lerp.py +151 -0
  370. warp/tests/test_linear_solvers.py +193 -0
  371. warp/tests/test_lvalue.py +427 -0
  372. warp/tests/test_mat.py +2089 -0
  373. warp/tests/test_mat_lite.py +122 -0
  374. warp/tests/test_mat_scalar_ops.py +2913 -0
  375. warp/tests/test_math.py +178 -0
  376. warp/tests/test_mlp.py +282 -0
  377. warp/tests/test_module_hashing.py +258 -0
  378. warp/tests/test_modules_lite.py +44 -0
  379. warp/tests/test_noise.py +252 -0
  380. warp/tests/test_operators.py +299 -0
  381. warp/tests/test_options.py +129 -0
  382. warp/tests/test_overwrite.py +551 -0
  383. warp/tests/test_print.py +339 -0
  384. warp/tests/test_quat.py +2315 -0
  385. warp/tests/test_rand.py +339 -0
  386. warp/tests/test_reload.py +302 -0
  387. warp/tests/test_rounding.py +185 -0
  388. warp/tests/test_runlength_encode.py +196 -0
  389. warp/tests/test_scalar_ops.py +105 -0
  390. warp/tests/test_smoothstep.py +108 -0
  391. warp/tests/test_snippet.py +318 -0
  392. warp/tests/test_sparse.py +582 -0
  393. warp/tests/test_spatial.py +2229 -0
  394. warp/tests/test_special_values.py +361 -0
  395. warp/tests/test_static.py +592 -0
  396. warp/tests/test_struct.py +734 -0
  397. warp/tests/test_tape.py +204 -0
  398. warp/tests/test_transient_module.py +93 -0
  399. warp/tests/test_triangle_closest_point.py +145 -0
  400. warp/tests/test_types.py +562 -0
  401. warp/tests/test_utils.py +588 -0
  402. warp/tests/test_vec.py +1487 -0
  403. warp/tests/test_vec_lite.py +80 -0
  404. warp/tests/test_vec_scalar_ops.py +2327 -0
  405. warp/tests/test_verify_fp.py +100 -0
  406. warp/tests/tile/__init__.py +0 -0
  407. warp/tests/tile/test_tile.py +780 -0
  408. warp/tests/tile/test_tile_load.py +407 -0
  409. warp/tests/tile/test_tile_mathdx.py +208 -0
  410. warp/tests/tile/test_tile_mlp.py +402 -0
  411. warp/tests/tile/test_tile_reduce.py +447 -0
  412. warp/tests/tile/test_tile_shared_memory.py +247 -0
  413. warp/tests/tile/test_tile_view.py +173 -0
  414. warp/tests/unittest_serial.py +47 -0
  415. warp/tests/unittest_suites.py +427 -0
  416. warp/tests/unittest_utils.py +468 -0
  417. warp/tests/walkthrough_debug.py +93 -0
  418. warp/thirdparty/__init__.py +0 -0
  419. warp/thirdparty/appdirs.py +598 -0
  420. warp/thirdparty/dlpack.py +145 -0
  421. warp/thirdparty/unittest_parallel.py +570 -0
  422. warp/torch.py +391 -0
  423. warp/types.py +5230 -0
  424. warp/utils.py +1137 -0
  425. warp_lang-1.7.0.dist-info/METADATA +516 -0
  426. warp_lang-1.7.0.dist-info/RECORD +429 -0
  427. warp_lang-1.7.0.dist-info/WHEEL +5 -0
  428. warp_lang-1.7.0.dist-info/licenses/LICENSE.md +202 -0
  429. warp_lang-1.7.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,286 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2024 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ ###########################################################################
17
+ # Example Adaptive Grid
18
+ #
19
+ # Demonstrates using an adaptive grid to increase the simulation resolition
20
+ # near a collider boundary.
21
+ #
22
+ ###########################################################################
23
+ import os.path
24
+
25
+ import numpy as np
26
+
27
+ import warp as wp
28
+ import warp.examples
29
+ import warp.examples.fem.utils as fem_example_utils
30
+ import warp.fem as fem
31
+ from warp.examples.fem.example_apic_fluid import divergence_form, solve_incompressibility
32
+
33
+
34
+ @fem.integrand
35
+ def inflow_velocity(
36
+ s: fem.Sample,
37
+ domain: fem.Domain,
38
+ bounds_lo: wp.vec3,
39
+ bounds_hi: wp.vec3,
40
+ ):
41
+ x = fem.position(domain, s)
42
+
43
+ if x[1] <= bounds_lo[1] or x[2] <= bounds_lo[2] or x[1] >= bounds_hi[1] or x[2] >= bounds_hi[2]:
44
+ return wp.vec3(0.0)
45
+
46
+ if x[0] <= bounds_lo[0] or x[0] >= bounds_hi[0]:
47
+ return wp.vec3(1.0, 0.0, 0.0)
48
+
49
+ return wp.vec3(0.0)
50
+
51
+
52
+ @fem.integrand
53
+ def noslip_projector_form(
54
+ s: fem.Sample,
55
+ u: fem.Field,
56
+ v: fem.Field,
57
+ ):
58
+ return wp.dot(u(s), v(s))
59
+
60
+
61
+ @fem.integrand
62
+ def mass_form(
63
+ s: fem.Sample,
64
+ u: fem.Field,
65
+ v: fem.Field,
66
+ ):
67
+ return fem.linalg.generalized_inner(u(s), v(s))
68
+
69
+
70
+ @fem.integrand
71
+ def side_divergence_form(s: fem.Sample, domain: fem.Domain, u: fem.Field, psi: fem.Field):
72
+ # normal velocity jump (non-zero at resolution boundaries)
73
+ return -wp.dot(fem.jump(u, s), fem.normal(domain, s)) * psi(s)
74
+
75
+
76
+ @wp.func
77
+ def refinement_field(xyz: wp.vec3, volume: wp.uint64):
78
+ # use distance to collider as refinement function
79
+ uvw = wp.volume_world_to_index(volume, xyz)
80
+ sdf = wp.volume_sample_f(volume, uvw, wp.Volume.LINEAR)
81
+
82
+ if sdf < 0.0:
83
+ return sdf
84
+
85
+ # combine with heuristical distance to keep coarsening past nvdb narrowband
86
+ return 0.5 * wp.max(wp.length(xyz) - 20.0, sdf)
87
+
88
+
89
+ @fem.integrand
90
+ def pressure_anomaly_field(s: fem.Sample, domain: fem.Domain, pressure: fem.Field):
91
+ # for visualization, deduce affine part such that grad P = u_x
92
+ x = domain(s)
93
+ return pressure(s) + x[0]
94
+
95
+
96
+ class Example:
97
+ def __init__(
98
+ self, quiet=False, degree=2, div_conforming=False, base_resolution=8, level_count=4, headless: bool = False
99
+ ):
100
+ self._quiet = quiet
101
+ self._degree = degree
102
+ self._div_conforming = div_conforming
103
+
104
+ # Start from a coarse, dense grid
105
+ res = wp.vec3i(2 * base_resolution, base_resolution // 2, base_resolution)
106
+ bounds_lo = wp.vec3(-50.0, 0.0, -17.5)
107
+ bounds_hi = wp.vec3(50.0, 12.5, 17.5)
108
+ sim_vol = fem_example_utils.gen_volume(res=res, bounds_lo=bounds_lo, bounds_hi=bounds_hi)
109
+
110
+ # load collision volume
111
+ collider_path = os.path.join(warp.examples.get_asset_directory(), "rocks.nvdb")
112
+ with open(collider_path, "rb") as file:
113
+ # create Volume object
114
+ collider = wp.Volume.load_from_nvdb(file)
115
+
116
+ # Make adaptive grid from coarse base and refinement field
117
+ refinement = fem.ImplicitField(
118
+ domain=fem.Cells(fem.Nanogrid(sim_vol)), func=refinement_field, values={"volume": collider.id}
119
+ )
120
+ self._geo = fem.adaptivity.adaptive_nanogrid_from_field(
121
+ sim_vol, level_count, refinement_field=refinement, grading="face"
122
+ )
123
+
124
+ # Function spaces for velocity, pressure (RTk / Pk-1 or Pk / Pk-1)
125
+ u_space = fem.make_polynomial_space(
126
+ geo=self._geo,
127
+ element_basis=fem.ElementBasis.RAVIART_THOMAS if div_conforming else None,
128
+ degree=self._degree,
129
+ dtype=wp.vec3,
130
+ )
131
+ p_space = fem.make_polynomial_space(geo=self._geo, degree=self._degree - 1, dtype=float)
132
+
133
+ self.pressure_field = p_space.make_field()
134
+ self.pressure_anomaly_field = p_space.make_field()
135
+ self.velocity_field = u_space.make_field()
136
+
137
+ # Initialize velocity field with BC
138
+ bounds_scale = 0.9999 # account for difference between bounds and actual grid extents
139
+ bounds_center = 0.5 * (bounds_hi + bounds_lo)
140
+ bounds_extent = 0.5 * (bounds_hi - bounds_lo)
141
+ fem.interpolate(
142
+ inflow_velocity,
143
+ dest=fem.make_restriction(self.velocity_field, domain=fem.BoundarySides(self._geo)),
144
+ values={
145
+ "bounds_lo": bounds_center - bounds_scale * bounds_extent,
146
+ "bounds_hi": bounds_center + bounds_scale * bounds_extent,
147
+ },
148
+ )
149
+
150
+ self.plot = fem_example_utils.Plot()
151
+
152
+ def render(self):
153
+ # self.renderer.add_field("solution", self.pressure_field)
154
+ self.plot.add_field("pressure_anomaly", self.pressure_anomaly_field)
155
+
156
+ if self._div_conforming:
157
+ # If using H(div)-conforming elements, interpolate to continuous space
158
+ velocity_field_lagrange = fem.make_polynomial_space(
159
+ self.velocity_field.geometry, dtype=wp.vec3, degree=self._degree
160
+ ).make_field()
161
+ fem.interpolate(self.velocity_field, dest=velocity_field_lagrange)
162
+ else:
163
+ velocity_field_lagrange = self.velocity_field
164
+
165
+ self.plot.add_field("velocity", velocity_field_lagrange)
166
+
167
+ def step(self):
168
+ u_space = self.velocity_field.space
169
+ p_space = self.pressure_field.space
170
+
171
+ # Boundary condition projector and matrices
172
+ boundary = fem.BoundarySides(self._geo)
173
+ bd_test = fem.make_test(u_space, domain=boundary)
174
+ bd_trial = fem.make_trial(u_space, domain=boundary)
175
+ dirichlet_projector = fem.integrate(
176
+ noslip_projector_form, fields={"u": bd_test, "v": bd_trial}, nodal=True, output_dtype=float
177
+ )
178
+ fem.normalize_dirichlet_projector(dirichlet_projector)
179
+
180
+ # (Diagonal) mass matrix
181
+ if self._div_conforming:
182
+ rho_test = fem.make_test(u_space)
183
+ rho_trial = fem.make_trial(u_space)
184
+ else:
185
+ rho_space = fem.make_polynomial_space(geo=u_space.geometry, degree=self._degree)
186
+ rho_test = fem.make_test(rho_space)
187
+ rho_trial = fem.make_trial(rho_space)
188
+
189
+ inv_mass_matrix = fem.integrate(
190
+ mass_form, fields={"u": rho_trial, "v": rho_test}, nodal=True, output_dtype=float
191
+ )
192
+ fem_example_utils.invert_diagonal_bsr_matrix(inv_mass_matrix)
193
+
194
+ # Assemble divergence operator matrix
195
+ p_test = fem.make_test(p_space)
196
+ u_trial = fem.make_trial(u_space)
197
+ divergence_matrix = fem.integrate(
198
+ divergence_form,
199
+ fields={"u": u_trial, "psi": p_test},
200
+ output_dtype=float,
201
+ )
202
+
203
+ # need to account for discontinuities at resolution boundaries (t-junctions)
204
+ p_side_test = fem.make_test(p_space, domain=fem.Sides(self._geo))
205
+ u_side_trial = fem.make_trial(u_space, domain=fem.Sides(self._geo))
206
+ divergence_matrix += fem.integrate(
207
+ side_divergence_form,
208
+ fields={"u": u_side_trial, "psi": p_side_test},
209
+ output_dtype=float,
210
+ assembly="generic", # not required, for test coverage purposes
211
+ )
212
+
213
+ # Solve incompressibility
214
+ solve_incompressibility(
215
+ divergence_matrix,
216
+ dirichlet_projector,
217
+ inv_mass_matrix.values,
218
+ self.pressure_field.dof_values,
219
+ self.velocity_field.dof_values,
220
+ quiet=self._quiet,
221
+ )
222
+
223
+ fem.interpolate(
224
+ pressure_anomaly_field,
225
+ dest=self.pressure_anomaly_field,
226
+ fields={"pressure": self.pressure_field},
227
+ )
228
+
229
+
230
+ if __name__ == "__main__":
231
+ import argparse
232
+
233
+ wp.set_module_options({"enable_backward": False})
234
+
235
+ parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
236
+ parser.add_argument("--device", type=str, default=None, help="Override the default Warp device.")
237
+ parser.add_argument("--resolution", type=int, default=8, help="Grid resolution.")
238
+ parser.add_argument("--degree", type=int, default=1, help="Polynomial degree of shape functions.")
239
+ parser.add_argument(
240
+ "--div_conforming", action="store_true", default=False, help="Use H(div)-conforming function space"
241
+ )
242
+ parser.add_argument("--level_count", type=int, default=4, help="Number of refinement levels.")
243
+ parser.add_argument(
244
+ "--headless",
245
+ action="store_true",
246
+ help="Run in headless mode, suppressing the opening of any graphical windows.",
247
+ )
248
+ parser.add_argument("--quiet", action="store_true", help="Suppresses the printing out of iteration residuals.")
249
+
250
+ args = parser.parse_known_args()[0]
251
+
252
+ with wp.ScopedDevice(args.device):
253
+ example = Example(
254
+ quiet=args.quiet,
255
+ degree=args.degree,
256
+ div_conforming=args.div_conforming,
257
+ base_resolution=args.resolution,
258
+ level_count=args.level_count,
259
+ headless=args.headless,
260
+ )
261
+
262
+ example.step()
263
+ example.render()
264
+
265
+ if not args.headless:
266
+ ref_geom = None
267
+ try:
268
+ from pxr import Usd, UsdGeom
269
+
270
+ stage = Usd.Stage.Open(os.path.join(warp.examples.get_asset_directory(), "rocks.usd"))
271
+ mesh = UsdGeom.Mesh(stage.GetPrimAtPath("/root/rocks"))
272
+ points = np.array((mesh.GetPointsAttr().Get()))
273
+ counts = np.array((mesh.GetFaceVertexCountsAttr().Get()))
274
+ indices = np.array(mesh.GetFaceVertexIndicesAttr().Get())
275
+ ref_geom = (points, counts, indices)
276
+ except Exception:
277
+ pass
278
+
279
+ example.plot.plot(
280
+ {
281
+ "rows": 2,
282
+ "ref_geom": ref_geom,
283
+ "velocity": {"streamlines": {"density": 25, "glyph_scale": 0.01}},
284
+ "pressure_anomaly": {},
285
+ }
286
+ )
@@ -0,0 +1,423 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
2
+ # SPDX-License-Identifier: Apache-2.0
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ ###########################################################################
17
+ # Example APIC Fluid Simulation
18
+ #
19
+ # Shows how to implement a minimalist APIC fluid simulation using a NanoVDB
20
+ # grid and the PicQuadrature class.
21
+ ###########################################################################
22
+
23
+ from typing import Any
24
+
25
+ import numpy as np
26
+
27
+ import warp as wp
28
+ import warp.examples.fem.utils as fem_example_utils
29
+ import warp.fem as fem
30
+ import warp.sim.render
31
+ from warp.fem import Domain, Field, Sample, at_node, div, grad, integrand
32
+ from warp.sim import Model, State
33
+ from warp.sparse import BsrMatrix, bsr_mm, bsr_mv, bsr_transposed
34
+
35
+
36
+ @wp.func
37
+ def collision_sdf(x: wp.vec3):
38
+ # Arbitrary sdf representing collision geometry
39
+ # Here an inverted half-ball of radius 10
40
+ x[1] = wp.min(x[1], 0.0)
41
+ return 10.0 - wp.length(x), -wp.normalize(x)
42
+
43
+
44
+ @integrand
45
+ def integrate_fraction(s: Sample, phi: Field):
46
+ return phi(s)
47
+
48
+
49
+ @integrand
50
+ def integrate_velocity(
51
+ s: Sample,
52
+ domain: Domain,
53
+ u: Field,
54
+ velocities: wp.array(dtype=wp.vec3),
55
+ velocity_gradients: wp.array(dtype=wp.mat33),
56
+ dt: float,
57
+ gravity: wp.vec3,
58
+ ):
59
+ """Transfer particle velocities to grid"""
60
+ node_offset = domain(at_node(u, s)) - domain(s)
61
+ vel_apic = velocities[s.qp_index] + velocity_gradients[s.qp_index] * node_offset
62
+
63
+ vel_adv = vel_apic + dt * gravity
64
+
65
+ # if inside collider, remove normal velocity
66
+ sdf, sdf_gradient = collision_sdf(domain(s))
67
+ if sdf <= 0:
68
+ v_n = wp.dot(vel_adv, sdf_gradient)
69
+ vel_adv -= wp.max(v_n, 0.0) * sdf_gradient
70
+
71
+ return wp.dot(u(s), vel_adv)
72
+
73
+
74
+ @integrand
75
+ def update_particles(
76
+ s: Sample,
77
+ domain: Domain,
78
+ grid_vel: Field,
79
+ dt: float,
80
+ pos: wp.array(dtype=wp.vec3),
81
+ pos_prev: wp.array(dtype=wp.vec3),
82
+ vel: wp.array(dtype=wp.vec3),
83
+ vel_grad: wp.array(dtype=wp.mat33),
84
+ ):
85
+ """Read particle velocity from grid and advect positions"""
86
+ p_vel = grid_vel(s)
87
+ vel_grad[s.qp_index] = grad(grid_vel, s)
88
+
89
+ pos_adv = pos_prev[s.qp_index] + dt * p_vel
90
+
91
+ pos[s.qp_index] = pos_adv
92
+ vel[s.qp_index] = p_vel
93
+
94
+
95
+ @integrand
96
+ def velocity_boundary_projector_form(s: Sample, domain: Domain, u: Field, v: Field):
97
+ """Projector for velocity-Dirichlet boundary conditions"""
98
+
99
+ x = domain(s)
100
+ sdf, sdf_normal = collision_sdf(x)
101
+
102
+ if sdf > 0.0:
103
+ # Neuman
104
+ return 0.0
105
+
106
+ # Free-slip on boundary
107
+ return wp.dot(u(s), sdf_normal) * wp.dot(v(s), sdf_normal)
108
+
109
+
110
+ @integrand
111
+ def divergence_form(s: Sample, domain: Domain, u: Field, psi: Field):
112
+ # Divergence bilinear form
113
+ return div(u, s) * psi(s)
114
+
115
+
116
+ @wp.kernel
117
+ def invert_volume_kernel(values: wp.array(dtype=float)):
118
+ i = wp.tid()
119
+ m = values[i]
120
+ values[i] = wp.where(m == 0.0, 0.0, 1.0 / m)
121
+
122
+
123
+ @wp.kernel
124
+ def scalar_vector_multiply(
125
+ alpha: wp.array(dtype=float),
126
+ x: wp.array(dtype=wp.vec3),
127
+ y: wp.array(dtype=wp.vec3),
128
+ ):
129
+ i = wp.tid()
130
+ y[i] = alpha[i] * x[i]
131
+
132
+
133
+ @wp.kernel
134
+ def scale_transposed_divergence_mat(
135
+ tr_divergence_mat_offsets: wp.array(dtype=int),
136
+ tr_divergence_mat_values: wp.array(dtype=Any),
137
+ inv_fraction_int: wp.array(dtype=float),
138
+ ):
139
+ # In-place scaling of gradient operator rows with inverse mass
140
+
141
+ u_i = wp.tid()
142
+ block_beg = tr_divergence_mat_offsets[u_i]
143
+ block_end = tr_divergence_mat_offsets[u_i + 1]
144
+
145
+ for b in range(block_beg, block_end):
146
+ tr_divergence_mat_values[b] = tr_divergence_mat_values[b] * inv_fraction_int[u_i]
147
+
148
+
149
+ def solve_incompressibility(
150
+ divergence_mat: BsrMatrix, dirichlet_projector: BsrMatrix, inv_volume, pressure, velocity, quiet: bool = False
151
+ ):
152
+ """Solve for divergence-free velocity delta:
153
+
154
+ delta_velocity = inv_volume * transpose(divergence_mat) * pressure
155
+ divergence_mat * (velocity + delta_velocity) = 0
156
+ dirichlet_projector * delta_velocity = 0
157
+ """
158
+
159
+ # Constraint-free divergence -- computed *before* projection of divergence_mat
160
+ rhs = wp.empty_like(pressure)
161
+ bsr_mv(A=divergence_mat, x=velocity, y=rhs, alpha=-1.0)
162
+
163
+ # Project matrix to enforce boundary conditions
164
+ # divergence_matrix -= divergence_matrix * vel_projector
165
+ bsr_mm(alpha=-1.0, x=divergence_mat, y=dirichlet_projector, z=divergence_mat, beta=1.0)
166
+
167
+ # Build transposed gradient matrix, scale with inverse fraction
168
+ transposed_divergence_mat = bsr_transposed(divergence_mat)
169
+ wp.launch(
170
+ kernel=scale_transposed_divergence_mat,
171
+ dim=inv_volume.shape[0],
172
+ inputs=[
173
+ transposed_divergence_mat.offsets,
174
+ transposed_divergence_mat.values,
175
+ inv_volume,
176
+ ],
177
+ )
178
+
179
+ # For simplicity, assemble Schur complement and solve with CG
180
+ schur = bsr_mm(divergence_mat, transposed_divergence_mat)
181
+
182
+ fem_example_utils.bsr_cg(schur, b=rhs, x=pressure, quiet=quiet, tol=1.0e-6, method="cr", max_iters=1000)
183
+
184
+ # Apply pressure to velocity
185
+ bsr_mv(A=transposed_divergence_mat, x=pressure, y=velocity, alpha=1.0, beta=1.0)
186
+
187
+
188
+ class Example:
189
+ def __init__(self, quiet=False, stage_path="example_apic_fluid.usd", voxel_size=1.0):
190
+ fps = 60
191
+ self.frame_dt = 1.0 / fps
192
+ self.current_frame = 0
193
+
194
+ self.sim_substeps = 1
195
+ self.sim_dt = self.frame_dt / self.sim_substeps
196
+ self.voxel_size = voxel_size
197
+
198
+ self._quiet = quiet
199
+
200
+ # particle emission
201
+ particle_grid_lo = wp.vec3(-5)
202
+ particle_grid_hi = wp.vec3(5)
203
+
204
+ grid_cell_size = voxel_size
205
+ grid_cell_volume = np.prod(grid_cell_size)
206
+
207
+ PARTICLES_PER_CELL_DIM = 2
208
+ self.radius = float(np.max(grid_cell_size) / (2 * PARTICLES_PER_CELL_DIM))
209
+
210
+ particle_grid_res = (
211
+ np.array((particle_grid_hi - particle_grid_lo) / voxel_size, dtype=int) * PARTICLES_PER_CELL_DIM
212
+ )
213
+ particle_grid_offset = wp.vec3(self.radius, self.radius, self.radius)
214
+
215
+ # Initialize warp.sim model, spawn particles
216
+ builder = wp.sim.ModelBuilder()
217
+ builder.add_particle_grid(
218
+ dim_x=particle_grid_res[0],
219
+ dim_y=particle_grid_res[1],
220
+ dim_z=particle_grid_res[2],
221
+ cell_x=self.radius * 2.0,
222
+ cell_y=self.radius * 2.0,
223
+ cell_z=self.radius * 2.0,
224
+ pos=particle_grid_lo + particle_grid_offset,
225
+ rot=wp.quat_identity(),
226
+ vel=wp.vec3(0.0, 0.0, 0.0),
227
+ mass=grid_cell_volume / PARTICLES_PER_CELL_DIM**3,
228
+ jitter=self.radius * 1.0,
229
+ )
230
+ self.model: Model = builder.finalize()
231
+ self.model.ground = False
232
+
233
+ # Storage for temporary variables
234
+ self.temporary_store = fem.TemporaryStore()
235
+
236
+ if not self._quiet:
237
+ print("Particle count:", self.model.particle_count)
238
+
239
+ self.state_0: State = self.model.state()
240
+ self.state_0.particle_qd_grad = wp.zeros(shape=(self.model.particle_count), dtype=wp.mat33)
241
+
242
+ self.state_1: State = self.model.state()
243
+ self.state_1.particle_qd_grad = wp.zeros(shape=(self.model.particle_count), dtype=wp.mat33)
244
+
245
+ try:
246
+ if stage_path:
247
+ self.renderer = warp.sim.render.SimRenderer(self.model, stage_path, scaling=20.0)
248
+ else:
249
+ self.renderer = None
250
+ except Exception as err:
251
+ print(f"Could not initialize SimRenderer for stage '{stage_path}': {err}.")
252
+
253
+ def step(self):
254
+ fem.set_default_temporary_store(self.temporary_store)
255
+
256
+ self.current_frame = self.current_frame + 1
257
+
258
+ with wp.ScopedTimer(f"simulate frame {self.current_frame}", active=True):
259
+ for _s in range(self.sim_substeps):
260
+ # Allocate the voxels and create the warp.fem geometry
261
+ volume = wp.Volume.allocate_by_voxels(
262
+ voxel_points=self.state_0.particle_q,
263
+ voxel_size=self.voxel_size,
264
+ )
265
+ grid = fem.Nanogrid(volume)
266
+
267
+ # Define function spaces: linear (Q1) for velocity and volume fraction,
268
+ # piecewise-constant for pressure
269
+ linear_basis_space = fem.make_polynomial_basis_space(grid, degree=1)
270
+ velocity_space = fem.make_collocated_function_space(linear_basis_space, dtype=wp.vec3)
271
+ fraction_space = fem.make_collocated_function_space(linear_basis_space, dtype=float)
272
+ strain_space = fem.make_polynomial_space(
273
+ grid,
274
+ dtype=float,
275
+ degree=0,
276
+ discontinuous=True,
277
+ )
278
+
279
+ pressure_field = strain_space.make_field()
280
+ velocity_field = velocity_space.make_field()
281
+
282
+ # Define test and trial functions and integrating linear and bilinear forms
283
+ domain = fem.Cells(grid)
284
+ velocity_test = fem.make_test(velocity_space, domain=domain)
285
+ velocity_trial = fem.make_trial(velocity_space, domain=domain)
286
+ fraction_test = fem.make_test(fraction_space, domain=domain)
287
+ strain_test = fem.make_test(strain_space, domain=domain)
288
+
289
+ # Build projector for Dirichlet boundary conditions
290
+ vel_projector = fem.integrate(
291
+ velocity_boundary_projector_form,
292
+ fields={"u": velocity_trial, "v": velocity_test},
293
+ nodal=True,
294
+ output_dtype=float,
295
+ )
296
+ fem.normalize_dirichlet_projector(vel_projector)
297
+
298
+ # Bin particles to grid cells
299
+ pic = fem.PicQuadrature(
300
+ domain=domain, positions=self.state_0.particle_q, measures=self.model.particle_mass
301
+ )
302
+
303
+ # Compute inverse particle volume for each grid node
304
+ inv_volume = fem.integrate(
305
+ integrate_fraction,
306
+ quadrature=pic,
307
+ fields={"phi": fraction_test},
308
+ output_dtype=float,
309
+ )
310
+ wp.launch(kernel=invert_volume_kernel, dim=inv_volume.shape, inputs=[inv_volume])
311
+
312
+ # Velocity right-hand side
313
+ velocity_int = fem.integrate(
314
+ integrate_velocity,
315
+ quadrature=pic,
316
+ fields={"u": velocity_test},
317
+ values={
318
+ "velocities": self.state_0.particle_qd,
319
+ "velocity_gradients": self.state_0.particle_qd_grad,
320
+ "dt": self.sim_dt,
321
+ "gravity": self.model.gravity,
322
+ },
323
+ output_dtype=wp.vec3,
324
+ )
325
+
326
+ # Compute constraint-free velocity
327
+ wp.launch(
328
+ kernel=scalar_vector_multiply,
329
+ dim=inv_volume.shape[0],
330
+ inputs=[inv_volume, velocity_int, velocity_field.dof_values],
331
+ )
332
+
333
+ # Apply velocity boundary conditions:
334
+ # velocity -= vel_projector * velocity
335
+ bsr_mv(
336
+ A=vel_projector,
337
+ x=velocity_field.dof_values,
338
+ y=velocity_field.dof_values,
339
+ alpha=-1.0,
340
+ beta=1.0,
341
+ )
342
+
343
+ # Assemble divergence operator matrix
344
+ divergence_matrix = fem.integrate(
345
+ divergence_form,
346
+ quadrature=pic,
347
+ fields={"u": velocity_trial, "psi": strain_test},
348
+ output_dtype=float,
349
+ )
350
+
351
+ # Solve unilateral incompressibility
352
+ solve_incompressibility(
353
+ divergence_matrix,
354
+ vel_projector,
355
+ inv_volume,
356
+ pressure_field.dof_values,
357
+ velocity_field.dof_values,
358
+ quiet=self._quiet,
359
+ )
360
+
361
+ # (A)PIC advection
362
+ fem.interpolate(
363
+ update_particles,
364
+ quadrature=pic,
365
+ values={
366
+ "pos": self.state_1.particle_q,
367
+ "pos_prev": self.state_0.particle_q,
368
+ "vel": self.state_1.particle_qd,
369
+ "vel_grad": self.state_1.particle_qd_grad,
370
+ "dt": self.sim_dt,
371
+ },
372
+ fields={"grid_vel": velocity_field},
373
+ )
374
+
375
+ # swap states
376
+ (self.state_0, self.state_1) = (self.state_1, self.state_0)
377
+
378
+ fem.set_default_temporary_store(None)
379
+
380
+ def render(self, is_live=False):
381
+ if self.renderer is None:
382
+ return
383
+
384
+ with wp.ScopedTimer("render", active=True):
385
+ time = self.current_frame * self.frame_dt
386
+
387
+ self.renderer.begin_frame(time)
388
+ self.renderer.render(self.state_0)
389
+ self.renderer.end_frame()
390
+
391
+
392
+ if __name__ == "__main__":
393
+ import argparse
394
+
395
+ wp.set_module_options({"enable_backward": False})
396
+
397
+ parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
398
+ parser.add_argument("--device", type=str, default=None, help="Override the default Warp device.")
399
+ parser.add_argument(
400
+ "--stage_path",
401
+ type=lambda x: None if x == "None" else str(x),
402
+ default="example_apic_fluid.usd",
403
+ help="Path to the output USD file.",
404
+ )
405
+ parser.add_argument("--num_frames", type=int, default=250, help="Total number of frames.")
406
+ parser.add_argument("--quiet", action="store_true")
407
+ parser.add_argument(
408
+ "--voxel_size",
409
+ type=float,
410
+ default=0.25,
411
+ )
412
+
413
+ args = parser.parse_known_args()[0]
414
+
415
+ with wp.ScopedDevice(args.device):
416
+ example = Example(quiet=args.quiet, stage_path=args.stage_path, voxel_size=args.voxel_size)
417
+
418
+ for _ in range(args.num_frames):
419
+ example.step()
420
+ example.render()
421
+
422
+ if example.renderer:
423
+ example.renderer.save()