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,262 @@
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 Stokes Transfer
18
+ #
19
+ # This example computes a 2D weakly-compressible Stokes flow around
20
+ # a moving object, including:
21
+ # - defining active cells from a mask, and restricting the computation domain to those
22
+ # - utilizing the PicQuadrature to integrate over unstructured particles
23
+ ###########################################################################
24
+
25
+ import math
26
+
27
+ import numpy as np
28
+
29
+ import warp as wp
30
+ import warp.examples.fem.utils as fem_example_utils
31
+ import warp.fem as fem
32
+ from warp.fem.utils import array_axpy
33
+ from warp.utils import array_cast
34
+
35
+
36
+ @fem.integrand
37
+ def vel_from_particles_form(s: fem.Sample, particle_vel: wp.array(dtype=wp.vec2), v: fem.Field):
38
+ vel = particle_vel[s.qp_index]
39
+ return wp.dot(vel, v(s))
40
+
41
+
42
+ @fem.integrand
43
+ def viscosity_form(s: fem.Sample, u: fem.Field, v: fem.Field, nu: float):
44
+ return nu * wp.ddot(fem.D(u, s), fem.D(v, s))
45
+
46
+
47
+ @fem.integrand
48
+ def mass_form(
49
+ s: fem.Sample,
50
+ u: fem.Field,
51
+ v: fem.Field,
52
+ ):
53
+ return wp.dot(u(s), v(s))
54
+
55
+
56
+ @fem.integrand
57
+ def scalar_mass_form(
58
+ s: fem.Sample,
59
+ p: fem.Field,
60
+ q: fem.Field,
61
+ ):
62
+ return p(s) * q(s)
63
+
64
+
65
+ @fem.integrand
66
+ def div_form(
67
+ s: fem.Sample,
68
+ u: fem.Field,
69
+ q: fem.Field,
70
+ ):
71
+ return q(s) * fem.div(u, s)
72
+
73
+
74
+ @fem.integrand
75
+ def cell_activity(s: fem.Sample, domain: fem.Domain, c1: wp.vec2, c2: wp.vec2, radius: float):
76
+ pos = domain(s)
77
+ if wp.length(pos - c1) < radius:
78
+ return 0.0
79
+ if wp.length(pos - c2) < radius:
80
+ return 0.0
81
+ return 1.0
82
+
83
+
84
+ @wp.kernel
85
+ def inverse_array_kernel(m: wp.array(dtype=wp.float64)):
86
+ m[wp.tid()] = wp.float64(1.0) / m[wp.tid()]
87
+
88
+
89
+ class Example:
90
+ def __init__(self, quiet=False, resolution=50):
91
+ self._quiet = quiet
92
+
93
+ self.res = resolution
94
+ self.cell_size = 1.0 / self.res
95
+
96
+ self.vel = 1.0
97
+ self.viscosity = 100.0
98
+ self.compliance = 0.01
99
+ self.bd_strength = 100000.0
100
+
101
+ geo = fem.Grid2D(res=wp.vec2i(self.res))
102
+
103
+ # Displacement boundary conditions are defined by two circles going in opposite directions
104
+ # Sample particles along those
105
+ circle_radius = 0.15
106
+ c1_center = wp.vec2(0.25, 0.5)
107
+ c2_center = wp.vec2(0.75, 0.5)
108
+ particles, particle_areas, particle_velocities = self._gen_particles(circle_radius, c1_center, c2_center)
109
+
110
+ # Disable cells that are interior to the circles
111
+ cell_space = fem.make_polynomial_space(geo, degree=0)
112
+ activity = cell_space.make_field()
113
+ fem.interpolate(
114
+ cell_activity,
115
+ dest=activity,
116
+ values={"c1": c1_center, "c2": c2_center, "radius": circle_radius - self.cell_size},
117
+ )
118
+
119
+ # Explicitly define the active geometry partition from those cells
120
+ self._active_partition = fem.ExplicitGeometryPartition(geo, wp.array(activity.dof_values.numpy(), dtype=int))
121
+ if not self._quiet:
122
+ print("Active cells:", self._active_partition.cell_count())
123
+
124
+ # Function spaces -- Q1 for vel, Q0 for pressure
125
+ u_space = fem.make_polynomial_space(geo, degree=1, dtype=wp.vec2)
126
+ p_space = fem.make_polynomial_space(geo, degree=0)
127
+
128
+ self._active_space_partition = fem.make_space_partition(
129
+ space=u_space, geometry_partition=self._active_partition
130
+ )
131
+ self._active_p_space_partition = fem.make_space_partition(
132
+ space=p_space, geometry_partition=self._active_partition
133
+ )
134
+
135
+ self._u_field = u_space.make_field()
136
+ self._p_field = p_space.make_field()
137
+
138
+ # Particle-based quadrature rule over active cells
139
+ domain = fem.Cells(geometry=self._active_partition)
140
+ self._pic_quadrature = fem.PicQuadrature(domain, particles, particle_areas)
141
+ self._particle_velocities = particle_velocities
142
+
143
+ self.renderer = fem_example_utils.Plot()
144
+
145
+ def step(self):
146
+ u_space = self._u_field.space
147
+ p_space = self._p_field.space
148
+
149
+ # Weakly-enforced boundary condition on particles
150
+ u_test = fem.make_test(space=u_space, space_partition=self._active_space_partition)
151
+ u_trial = fem.make_trial(space=u_space, space_partition=self._active_space_partition)
152
+
153
+ u_rhs = fem.integrate(
154
+ vel_from_particles_form,
155
+ quadrature=self._pic_quadrature,
156
+ fields={"v": u_test},
157
+ values={"particle_vel": self._particle_velocities},
158
+ output_dtype=wp.vec2d,
159
+ )
160
+ u_bd_matrix = fem.integrate(mass_form, quadrature=self._pic_quadrature, fields={"u": u_trial, "v": u_test})
161
+
162
+ # Viscosity
163
+ u_visc_matrix = fem.integrate(
164
+ viscosity_form,
165
+ fields={"u": u_trial, "v": u_test},
166
+ values={"nu": self.viscosity},
167
+ )
168
+
169
+ # Pressure-velocity coupling
170
+ p_test = fem.make_test(space=p_space, space_partition=self._active_p_space_partition)
171
+ p_trial = fem.make_trial(space=p_space, space_partition=self._active_p_space_partition)
172
+
173
+ div_matrix = fem.integrate(div_form, fields={"u": u_trial, "q": p_test})
174
+ inv_p_mass_matrix = fem.integrate(scalar_mass_form, fields={"p": p_trial, "q": p_test})
175
+ wp.launch(
176
+ kernel=inverse_array_kernel,
177
+ dim=inv_p_mass_matrix.values.shape,
178
+ device=inv_p_mass_matrix.values.device,
179
+ inputs=[inv_p_mass_matrix.values],
180
+ )
181
+
182
+ # Assemble linear system
183
+ u_matrix = u_visc_matrix
184
+ u_matrix += u_bd_matrix * self.bd_strength
185
+
186
+ gradient_matrix = div_matrix.transpose() @ inv_p_mass_matrix
187
+ u_matrix += gradient_matrix @ div_matrix / self.compliance
188
+
189
+ # scale u_rhs
190
+ array_axpy(u_rhs, u_rhs, alpha=0.0, beta=self.bd_strength)
191
+
192
+ # Solve for displacement
193
+ u_res = wp.zeros_like(u_rhs)
194
+ fem_example_utils.bsr_cg(u_matrix, x=u_res, b=u_rhs, quiet=self._quiet)
195
+
196
+ # Compute pressure from displacement
197
+ div_u = div_matrix @ u_res
198
+ p_res = -inv_p_mass_matrix @ div_u
199
+
200
+ # Copy to fields
201
+ u_nodes = wp.indexedarray(self._u_field.dof_values, indices=self._active_space_partition.space_node_indices())
202
+ p_nodes = wp.indexedarray(self._p_field.dof_values, indices=self._active_p_space_partition.space_node_indices())
203
+
204
+ array_cast(in_array=u_res, out_array=u_nodes)
205
+ array_cast(in_array=p_res, out_array=p_nodes)
206
+
207
+ def render(self):
208
+ self.renderer.add_field("pressure", self._p_field)
209
+ self.renderer.add_field("velocity", self._u_field)
210
+
211
+ def _gen_particles(self, circle_radius, c1_center, c2_center):
212
+ """Generate some particles along two circles defining velocity boundary conditions"""
213
+
214
+ # Generate particles defining the transfer displacement
215
+ particles_per_circle = int(2.0 * math.pi * circle_radius * self.res)
216
+
217
+ angles = np.linspace(0, 2.0 * math.pi, particles_per_circle, endpoint=False)
218
+
219
+ n_particles = 2 * particles_per_circle
220
+ particles = np.empty((n_particles, 2), dtype=float)
221
+
222
+ particles[:particles_per_circle, 0] = c1_center[0] + circle_radius * np.cos(angles)
223
+ particles[:particles_per_circle, 1] = c1_center[1] + circle_radius * np.sin(angles)
224
+ particles[particles_per_circle:, 0] = c2_center[0] + circle_radius * np.cos(angles)
225
+ particles[particles_per_circle:, 1] = c2_center[1] + circle_radius * np.sin(angles)
226
+
227
+ particle_areas = np.ones(n_particles) * self.cell_size**2
228
+ particle_velocities = np.zeros_like(particles)
229
+ particle_velocities[:particles_per_circle, 0] = self.vel
230
+ particle_velocities[particles_per_circle:, 0] = -self.vel
231
+
232
+ particles = wp.array(particles, dtype=wp.vec2)
233
+ particle_areas = wp.array(particle_areas, dtype=float)
234
+ particle_velocities = wp.array(particle_velocities, dtype=wp.vec2)
235
+
236
+ return particles, particle_areas, particle_velocities
237
+
238
+
239
+ if __name__ == "__main__":
240
+ import argparse
241
+
242
+ wp.set_module_options({"enable_backward": False})
243
+
244
+ parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
245
+ parser.add_argument("--device", type=str, default=None, help="Override the default Warp device.")
246
+ parser.add_argument("--resolution", type=int, default=50, help="Grid resolution.")
247
+ parser.add_argument(
248
+ "--headless",
249
+ action="store_true",
250
+ help="Run in headless mode, suppressing the opening of any graphical windows.",
251
+ )
252
+ parser.add_argument("--quiet", action="store_true", help="Suppresses the printing out of iteration residuals.")
253
+
254
+ args = parser.parse_known_args()[0]
255
+
256
+ with wp.ScopedDevice(args.device):
257
+ example = Example(quiet=args.quiet, resolution=args.resolution)
258
+ example.step()
259
+ example.render()
260
+
261
+ if not args.headless:
262
+ example.renderer.plot(options={"velocity": {"streamlines": {}}})
@@ -0,0 +1,352 @@
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 Streamlines
18
+ #
19
+ # Shows how to generate 3D streamlines by tracing through a velocity field
20
+ # using the `warp.fem.lookup` operator.
21
+ # Also illustrates using `warp.fem.Subdomain` to define subsets of elements.
22
+ #
23
+ ###########################################################################
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
+ from warp.examples.fem.example_apic_fluid import divergence_form, solve_incompressibility
31
+
32
+
33
+ @fem.integrand
34
+ def classify_boundary_sides(
35
+ s: fem.Sample,
36
+ domain: fem.Domain,
37
+ outflow: wp.array(dtype=int),
38
+ freeslip: wp.array(dtype=int),
39
+ inflow: wp.array(dtype=int),
40
+ ):
41
+ x = fem.position(domain, s)
42
+ n = fem.normal(domain, s)
43
+
44
+ if n[0] < -0.5:
45
+ # left side
46
+ inflow[s.qp_index] = 1
47
+ elif n[0] > 0.5:
48
+ if x[1] > 0.33 or x[2] < 0.33:
49
+ # right side, top
50
+ freeslip[s.qp_index] = 1
51
+ else:
52
+ # right side, bottom
53
+ outflow[s.qp_index] = 1
54
+ else:
55
+ freeslip[s.qp_index] = 1
56
+
57
+
58
+ @fem.integrand
59
+ def inflow_velocity(
60
+ s: fem.Sample,
61
+ domain: fem.Domain,
62
+ ):
63
+ n = fem.normal(domain, s)
64
+ return -n
65
+
66
+
67
+ @fem.integrand
68
+ def noslip_projector_form(
69
+ s: fem.Sample,
70
+ u: fem.Field,
71
+ v: fem.Field,
72
+ ):
73
+ return wp.dot(u(s), v(s))
74
+
75
+
76
+ @fem.integrand
77
+ def freeslip_projector_form(
78
+ s: fem.Sample,
79
+ domain: fem.Domain,
80
+ u: fem.Field,
81
+ v: fem.Field,
82
+ ):
83
+ n = fem.normal(domain, s)
84
+ return wp.dot(u(s), n) * wp.dot(n, v(s))
85
+
86
+
87
+ @fem.integrand
88
+ def mass_form(
89
+ s: fem.Sample,
90
+ u: fem.Field,
91
+ v: fem.Field,
92
+ ):
93
+ return wp.dot(u(s), v(s))
94
+
95
+
96
+ @fem.integrand
97
+ def spawn_streamlines(s: fem.Sample, domain: fem.Domain, jitter: float):
98
+ rng = wp.rand_init(s.qp_index)
99
+ random_offset = wp.vec3(wp.randf(rng), wp.randf(rng), wp.randf(rng)) - wp.vec3(0.5)
100
+
101
+ # remove jistter along normal
102
+ n = fem.normal(domain, s)
103
+ random_offset -= wp.dot(random_offset, n) * n
104
+
105
+ return domain(s) + jitter * random_offset
106
+
107
+
108
+ @fem.integrand
109
+ def gen_streamlines(
110
+ s: fem.Sample,
111
+ domain: fem.Domain,
112
+ u: fem.Field,
113
+ spawn_points: wp.array(dtype=wp.vec3),
114
+ point_count: int,
115
+ dx: float,
116
+ pos: wp.array2d(dtype=wp.vec3),
117
+ speed: wp.array2d(dtype=float),
118
+ ):
119
+ idx = s.qp_index
120
+
121
+ p = spawn_points[idx]
122
+ s = fem.lookup(domain, p)
123
+ for k in range(point_count):
124
+ v = u(s)
125
+ pos[idx, k] = p
126
+ speed[idx, k] = wp.length(v)
127
+
128
+ flow_dir = wp.normalize(v)
129
+ adv_p = p + flow_dir * dx
130
+ adv_s = fem.lookup(domain, adv_p, s)
131
+
132
+ if adv_s.element_index != fem.NULL_ELEMENT_INDEX:
133
+ # if the lookup result position is different from adv_p,
134
+ # it means we have been projected back onto the domain;
135
+ # align back with flow and terminate streamline
136
+ new_p = domain(adv_s)
137
+ if wp.length_sq(new_p - adv_p) > 0.000001:
138
+ p = p + wp.dot(new_p - p, flow_dir) * flow_dir
139
+ s = fem.lookup(domain, p, s)
140
+ dx = 0.0
141
+ else:
142
+ s = adv_s
143
+ p = new_p
144
+
145
+
146
+ class Example:
147
+ def __init__(self, quiet=False, degree=2, resolution=16, mesh="grid", headless: bool = False):
148
+ self._quiet = quiet
149
+ self._degree = degree
150
+
151
+ self._streamline_dx = 0.5 / resolution
152
+ self._streamline_point_count = 4 * resolution
153
+
154
+ res = wp.vec3i(resolution)
155
+
156
+ if mesh == "tet":
157
+ pos, tet_vtx_indices = fem_example_utils.gen_tetmesh(
158
+ res=res,
159
+ )
160
+ self._geo = fem.Tetmesh(tet_vtx_indices, pos, build_bvh=True)
161
+ elif mesh == "nano":
162
+ volume = fem_example_utils.gen_volume(
163
+ res=res,
164
+ )
165
+ self._geo = fem.Nanogrid(volume)
166
+ else:
167
+ self._geo = fem.Grid3D(
168
+ res=res,
169
+ )
170
+
171
+ # Mark sides with boundary conditions that should apply
172
+ boundary = fem.BoundarySides(self._geo)
173
+ inflow_mask = wp.zeros(shape=boundary.element_count(), dtype=int)
174
+ freeslip_mask = wp.zeros(shape=boundary.element_count(), dtype=int)
175
+ outflow_mask = wp.zeros(shape=boundary.element_count(), dtype=int)
176
+
177
+ fem.interpolate(
178
+ classify_boundary_sides,
179
+ quadrature=fem.RegularQuadrature(boundary, order=0),
180
+ values={"outflow": outflow_mask, "freeslip": freeslip_mask, "inflow": inflow_mask},
181
+ )
182
+
183
+ self._inflow = fem.Subdomain(boundary, element_mask=inflow_mask)
184
+ self._freeslip = fem.Subdomain(boundary, element_mask=freeslip_mask)
185
+ self._outflow = fem.Subdomain(boundary, element_mask=outflow_mask)
186
+
187
+ self.plot = fem_example_utils.Plot()
188
+
189
+ self.renderer = None
190
+ if not headless:
191
+ try:
192
+ self.renderer = wp.render.OpenGLRenderer(
193
+ camera_pos=(2.0, 0.5, 3.0),
194
+ camera_front=(-0.66, 0.0, -1.0),
195
+ draw_axis=False,
196
+ )
197
+ except Exception as err:
198
+ wp.utils.warn(f"Could not initialize OpenGL renderer: {err}")
199
+ pass
200
+
201
+ def step(self):
202
+ self._generate_incompressible_flow()
203
+
204
+ # first generate spawn points for the streamlines
205
+ # we do this by regularly sampling the inflow boundary with a small amount of jitter
206
+ streamline_spawn = fem.RegularQuadrature(
207
+ domain=self._inflow, order=self._degree, family=fem.Polynomial.GAUSS_LEGENDRE
208
+ )
209
+ n_streamlines = streamline_spawn.total_point_count()
210
+ spawn_points = wp.empty(dtype=wp.vec3, shape=n_streamlines)
211
+
212
+ jitter_amount = self._streamline_dx / self._degree
213
+ fem.interpolate(
214
+ spawn_streamlines, dest=spawn_points, quadrature=streamline_spawn, values={"jitter": jitter_amount}
215
+ )
216
+
217
+ # now forward-trace the velocity field to generate the streamlines
218
+ # here we use a fixed number of points per streamline, otherwise we would need to
219
+ # do a first pass to count points, then array_scan the offsets, then a second pass
220
+ # to populate the per-point data
221
+
222
+ point_count = self._streamline_point_count
223
+ points = wp.empty(dtype=wp.vec3, shape=(n_streamlines, point_count))
224
+ speed = wp.empty(dtype=float, shape=(n_streamlines, point_count))
225
+
226
+ fem.interpolate(
227
+ gen_streamlines,
228
+ domain=fem.Cells(self._geo),
229
+ dim=n_streamlines,
230
+ fields={"u": self.velocity_field},
231
+ values={
232
+ "spawn_points": spawn_points,
233
+ "point_count": self._streamline_point_count,
234
+ "dx": self._streamline_dx,
235
+ "pos": points,
236
+ "speed": speed,
237
+ },
238
+ )
239
+
240
+ self._points = points
241
+ self._speed = speed
242
+
243
+ def render(self):
244
+ # self.renderer.add_field("solution", self.pressure_field)
245
+ self.plot.add_field("pressure", self.pressure_field)
246
+ # self.plot.add_field("velocity", self.velocity_field)
247
+
248
+ if self.renderer is not None:
249
+ streamline_count = self._points.shape[0]
250
+ point_count = self._streamline_point_count
251
+
252
+ vertices = self._points.flatten().numpy()
253
+
254
+ line_offsets = np.arange(streamline_count) * point_count
255
+ indices_beg = np.arange(point_count - 1)[np.newaxis, :] + line_offsets[:, np.newaxis]
256
+ indices_end = indices_beg + 1
257
+ indices = np.vstack((indices_beg.flatten(), indices_end.flatten())).T.flatten()
258
+
259
+ colors = self._speed.numpy()[:, :-1].flatten()
260
+ colors = [wp.render.bourke_color_map(0.0, 3.0, c) for c in colors]
261
+
262
+ self.renderer.begin_frame(0)
263
+ self.renderer.render_line_list("streamlines", vertices, indices)
264
+ self.renderer.render_line_list("streamlines", vertices, indices, colors)
265
+
266
+ self.renderer.paused = True
267
+ self.renderer.end_frame()
268
+
269
+ def _generate_incompressible_flow(self):
270
+ # Function spaces for velocity and pressure (RT1 / P0)
271
+ u_space = fem.make_polynomial_space(
272
+ geo=self._geo, element_basis=fem.ElementBasis.RAVIART_THOMAS, degree=1, dtype=wp.vec3
273
+ )
274
+ p_space = fem.make_polynomial_space(geo=self._geo, degree=0, dtype=float)
275
+
276
+ self.pressure_field = p_space.make_field()
277
+ self.velocity_field = u_space.make_field()
278
+
279
+ # Boundary condition projector and matrices
280
+ inflow_test = fem.make_test(u_space, domain=self._inflow)
281
+ inflow_trial = fem.make_trial(u_space, domain=self._inflow)
282
+ dirichlet_projector = fem.integrate(
283
+ noslip_projector_form, fields={"u": inflow_test, "v": inflow_trial}, nodal=True, output_dtype=float
284
+ )
285
+
286
+ freeslip_test = fem.make_test(u_space, domain=self._freeslip)
287
+ freeslip_trial = fem.make_trial(u_space, domain=self._freeslip)
288
+ dirichlet_projector += fem.integrate(
289
+ freeslip_projector_form,
290
+ fields={"u": freeslip_test, "v": freeslip_trial},
291
+ nodal=True,
292
+ output_dtype=float,
293
+ )
294
+ fem.normalize_dirichlet_projector(dirichlet_projector)
295
+
296
+ # Initialize velocity field with BC
297
+ fem.interpolate(inflow_velocity, dest=fem.make_restriction(self.velocity_field, domain=self._inflow))
298
+
299
+ # (Diagonal) mass matrix
300
+ rho_test = fem.make_test(u_space)
301
+ rho_trial = fem.make_trial(u_space)
302
+ inv_mass_matrix = fem.integrate(
303
+ mass_form, fields={"u": rho_trial, "v": rho_test}, nodal=True, output_dtype=float
304
+ )
305
+ fem_example_utils.invert_diagonal_bsr_matrix(inv_mass_matrix)
306
+
307
+ # Assemble divergence operator matrix
308
+ p_test = fem.make_test(p_space)
309
+ u_trial = fem.make_trial(u_space)
310
+ divergence_matrix = fem.integrate(
311
+ divergence_form,
312
+ fields={"u": u_trial, "psi": p_test},
313
+ output_dtype=float,
314
+ )
315
+
316
+ # Solve incompressibility
317
+ solve_incompressibility(
318
+ divergence_matrix,
319
+ dirichlet_projector,
320
+ inv_mass_matrix.values,
321
+ self.pressure_field.dof_values,
322
+ self.velocity_field.dof_values,
323
+ quiet=self._quiet,
324
+ )
325
+
326
+
327
+ if __name__ == "__main__":
328
+ import argparse
329
+
330
+ wp.set_module_options({"enable_backward": False})
331
+
332
+ parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
333
+ parser.add_argument("--device", type=str, default=None, help="Override the default Warp device.")
334
+ parser.add_argument("--resolution", type=int, default=8, help="Grid resolution.")
335
+ parser.add_argument("--degree", type=int, default=2, help="Polynomial degree of shape functions.")
336
+ parser.add_argument("--mesh", choices=("grid", "tet", "hex", "nano"), default="grid", help="Mesh type.")
337
+ parser.add_argument(
338
+ "--headless",
339
+ action="store_true",
340
+ help="Run in headless mode, suppressing the opening of any graphical windows.",
341
+ )
342
+ parser.add_argument("--quiet", action="store_true", help="Suppresses the printing out of iteration residuals.")
343
+
344
+ args = parser.parse_known_args()[0]
345
+
346
+ with wp.ScopedDevice(args.device):
347
+ example = Example(
348
+ quiet=args.quiet, degree=args.degree, resolution=args.resolution, mesh=args.mesh, headless=args.headless
349
+ )
350
+
351
+ example.step()
352
+ example.render()