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,857 @@
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
+ from typing import Optional
17
+
18
+ import numpy as np
19
+
20
+ import warp as wp
21
+ from warp.fem import cache, utils
22
+ from warp.fem.types import NULL_ELEMENT_INDEX, OUTSIDE, Coords, ElementIndex, Sample, make_free_sample
23
+
24
+ from .element import Cube, Square
25
+ from .geometry import Geometry
26
+ from .nanogrid import (
27
+ Nanogrid,
28
+ _add_axis_flag,
29
+ _build_node_grid,
30
+ _extract_axis_flag,
31
+ _get_boundary_mask,
32
+ _make_face_flags,
33
+ )
34
+
35
+ _FACE_LEVEL_BIT = wp.constant(wp.uint8(4)) # follows nanogrid.FACE_OUTER_OFFSET_BIT
36
+ _GRID_LEVEL_BIT = wp.constant(wp.int32(19)) # follows nanogrid.GRID_AXIS_FLAG
37
+
38
+
39
+ @wp.struct
40
+ class AdaptiveNanogridCellArg:
41
+ # Utility device functions
42
+ cell_grid: wp.uint64
43
+ cell_ijk: wp.array(dtype=wp.vec3i)
44
+ cell_level: wp.array(dtype=wp.uint8)
45
+ inverse_transform: wp.mat33
46
+ cell_volume: float
47
+ level_count: int
48
+
49
+
50
+ @wp.struct
51
+ class AdaptiveNanogridSideArg:
52
+ # Utility device functions
53
+ cell_arg: AdaptiveNanogridCellArg
54
+ face_ijk: wp.array(dtype=wp.vec3i)
55
+ face_cell_indices: wp.array(dtype=wp.vec2i)
56
+ face_flags: wp.array(dtype=wp.uint8)
57
+ face_areas: wp.vec3
58
+
59
+
60
+ class AdaptiveNanogrid(Geometry):
61
+ """Adaptive sparse grid"""
62
+
63
+ dimension = 3
64
+
65
+ def __init__(
66
+ self,
67
+ cell_grid: wp.Volume,
68
+ cell_level: wp.array,
69
+ level_count: int,
70
+ temporary_store: cache.TemporaryStore,
71
+ ):
72
+ """
73
+ Constructs an adaptive sparse grid geometry from an in-memory NanoVDB volume and a list of levels.
74
+
75
+ It is not recommended to use this constructor directly; see the helper functions :func:`warp.fem.adaptive_nanogrid_from_field` and :func:`warp.fem.adaptive_nanogrid_from_hierarchy`
76
+
77
+ Args:
78
+ cell_grid: A warp volume (ideally backed by an index grid) whose voxels coordinates correspond to the lowest fine-resolution voxel of each cell.
79
+ The cell's extent is then given by the `cell_level` array. For instance, a voxel at coordinates ``ijk`` and level ``0`` corresponds to a fine cell at the same coordinates,
80
+ a voxel at coordinates ``2*ijk`` and level ``1`` corresponds to a cell spanning ``2^3`` voxels from ``2*ijk`` to ``2*ijk + (1,1,1)``, etc.
81
+ cell_level: Refinement level for each voxel of the volume. Level 0 is the finest, level ``level_count-1`` is the coarsest.
82
+ level_count: Number of levels in the grid
83
+ """
84
+
85
+ if level_count > 8:
86
+ raise ValueError("Too many refinement levels, max 8 supported")
87
+
88
+ self.level_count = level_count
89
+ self._cell_grid = cell_grid
90
+ self._cell_level = cell_level
91
+
92
+ device = self._cell_grid.device
93
+ self._cell_ijk = wp.array(dtype=wp.vec3i, shape=(cell_grid.get_voxel_count(),), device=device)
94
+ self._cell_grid.get_voxels(out=self._cell_ijk)
95
+ self._cell_grid_info = self._cell_grid.get_grid_info()
96
+
97
+ self._node_grid = _build_node_grid(self._cell_ijk, self._cell_level, self._cell_grid, temporary_store)
98
+ node_count = self._node_grid.get_voxel_count()
99
+ self._node_ijk = wp.array(shape=(node_count,), dtype=wp.vec3i, device=device)
100
+ self._node_grid.get_voxels(out=self._node_ijk)
101
+
102
+ self._face_grid = None
103
+ self._face_ijk = None
104
+
105
+ self._stacked_edge_grid = None
106
+ self._stacked_edge_count = 0
107
+ self._stacked_face_grid = None
108
+ self._stacked_face_count = 0
109
+
110
+ @property
111
+ def cell_grid(self) -> wp.Volume:
112
+ return self._cell_grid
113
+
114
+ @property
115
+ def vertex_grid(self) -> wp.Volume:
116
+ return self._node_grid
117
+
118
+ @property
119
+ def face_grid(self) -> wp.Volume:
120
+ self._ensure_face_grid()
121
+ return self._face_grid
122
+
123
+ def cell_count(self):
124
+ return self._cell_ijk.shape[0]
125
+
126
+ def vertex_count(self):
127
+ return self._node_ijk.shape[0]
128
+
129
+ def side_count(self):
130
+ self._ensure_face_grid()
131
+ return self._face_ijk.shape[0]
132
+
133
+ def boundary_side_count(self):
134
+ self._ensure_face_grid()
135
+ return self._boundary_face_indices.shape[0]
136
+
137
+ @property
138
+ def stacked_face_grid(self) -> wp.Volume:
139
+ self._ensure_stacked_face_grid()
140
+ return self._stacked_face_grid
141
+
142
+ def stacked_face_count(self):
143
+ self._ensure_stacked_face_grid()
144
+ return self._stacked_face_count
145
+
146
+ @property
147
+ def stacked_edge_grid(self) -> wp.Volume:
148
+ self._ensure_stacked_edge_grid()
149
+ return self._stacked_edge_grid
150
+
151
+ def stacked_edge_count(self):
152
+ self._ensure_stacked_edge_grid()
153
+ return self._stacked_edge_count
154
+
155
+ def reference_cell(self) -> Cube:
156
+ return Cube()
157
+
158
+ def reference_side(self) -> Square:
159
+ return Square()
160
+
161
+ @property
162
+ def transform(self):
163
+ return np.array(self._cell_grid_info.transform_matrix).reshape(3, 3)
164
+
165
+ CellArg = AdaptiveNanogridCellArg
166
+
167
+ @cache.cached_arg_value
168
+ def cell_arg_value(self, device) -> CellArg:
169
+ args = self.CellArg()
170
+ args.cell_grid = self._cell_grid.id
171
+ args.cell_ijk = self._cell_ijk
172
+ args.cell_level = self._cell_level
173
+
174
+ transform = self.transform
175
+ args.inverse_transform = wp.mat33f(np.linalg.inv(transform))
176
+ args.cell_volume = abs(np.linalg.det(transform))
177
+ args.level_count = self.level_count
178
+
179
+ return args
180
+
181
+ @wp.func
182
+ def _cell_scale(args: CellArg, cell_index: int):
183
+ return float(1 << int(args.cell_level[cell_index]))
184
+
185
+ @wp.func
186
+ def cell_position(args: CellArg, s: Sample):
187
+ scale = AdaptiveNanogrid._cell_scale(args, s.element_index)
188
+ uvw = wp.vec3(args.cell_ijk[s.element_index]) + s.element_coords * scale
189
+ return wp.volume_index_to_world(args.cell_grid, uvw - wp.vec3(0.5))
190
+
191
+ @wp.func
192
+ def cell_deformation_gradient(args: CellArg, s: Sample):
193
+ scale = AdaptiveNanogrid._cell_scale(args, s.element_index)
194
+ return wp.inverse(args.inverse_transform) * scale
195
+
196
+ @wp.func
197
+ def cell_inverse_deformation_gradient(args: CellArg, s: Sample):
198
+ scale = AdaptiveNanogrid._cell_scale(args, s.element_index)
199
+ return args.inverse_transform / scale
200
+
201
+ @wp.func
202
+ def _make_sample(args: CellArg, cell_index: int, uvw: wp.vec3):
203
+ ijk = args.cell_ijk[cell_index]
204
+ return make_free_sample(cell_index, (uvw - wp.vec3(ijk)) / AdaptiveNanogrid._cell_scale(args, cell_index))
205
+
206
+ @wp.func
207
+ def cell_lookup(args: CellArg, pos: wp.vec3):
208
+ uvw = wp.volume_world_to_index(args.cell_grid, pos) + wp.vec3(0.5)
209
+ ijk = wp.vec3i(int(wp.floor(uvw[0])), int(wp.floor(uvw[1])), int(wp.floor(uvw[2])))
210
+ cell_index = AdaptiveNanogrid.find_cell(args.cell_grid, ijk, args.level_count, args.cell_level)
211
+
212
+ if cell_index == -1:
213
+ coords = uvw - wp.vec3(ijk)
214
+
215
+ if wp.min(coords) == 0.0 or wp.max(coords) == 1.0:
216
+ il = wp.where(coords[0] > 0.5, 0, -1)
217
+ jl = wp.where(coords[1] > 0.5, 0, -1)
218
+ kl = wp.where(coords[2] > 0.5, 0, -1)
219
+
220
+ for n in range(8):
221
+ ni = n >> 2
222
+ nj = (n & 2) >> 1
223
+ nk = n & 1
224
+ nijk = ijk + wp.vec3i(ni + il, nj + jl, nk + kl)
225
+
226
+ coords = uvw - wp.vec3(nijk)
227
+ if wp.min(coords) >= 0.0 and wp.max(coords) <= 1.0:
228
+ cell_index = AdaptiveNanogrid.find_cell(args.cell_grid, nijk, args.level_count, args.cell_level)
229
+ if cell_index != -1:
230
+ return AdaptiveNanogrid._make_sample(args, cell_index, uvw)
231
+
232
+ return make_free_sample(NULL_ELEMENT_INDEX, Coords(OUTSIDE))
233
+
234
+ return AdaptiveNanogrid._make_sample(args, cell_index, uvw)
235
+
236
+ @wp.func
237
+ def cell_lookup(args: CellArg, pos: wp.vec3, guess: Sample):
238
+ s_global = AdaptiveNanogrid.cell_lookup(args, pos)
239
+
240
+ if s_global.element_index != NULL_ELEMENT_INDEX:
241
+ return s_global
242
+
243
+ closest_voxel = int(NULL_ELEMENT_INDEX)
244
+ closest_coords = Coords(OUTSIDE)
245
+ closest_dist = float(1.0e8)
246
+
247
+ # project to closest in stencil
248
+ uvw = wp.volume_world_to_index(args.cell_grid, pos) + wp.vec3(0.5)
249
+ cell_ijk = args.cell_ijk[guess.element_index]
250
+ for ni in range(-1, 2):
251
+ for nj in range(-1, 2):
252
+ for nk in range(-1, 2):
253
+ nijk = cell_ijk + wp.vec3i(ni, nj, nk)
254
+ cell_idx = AdaptiveNanogrid.find_cell(args.cell_grid, nijk, args.level_count, args.cell_level)
255
+ if cell_idx != -1:
256
+ nijk = args.cell_ijk[cell_idx]
257
+ scale = AdaptiveNanogrid._cell_scale(args, cell_idx)
258
+ coords = (uvw - wp.vec3(nijk)) / scale
259
+ dist, proj_coords = Nanogrid._project_on_voxel_at_origin(coords)
260
+ dist *= scale
261
+ if dist <= closest_dist:
262
+ closest_dist = dist
263
+ closest_voxel = cell_idx
264
+ closest_coords = proj_coords
265
+
266
+ return make_free_sample(closest_voxel, closest_coords)
267
+
268
+ @wp.func
269
+ def cell_measure(args: CellArg, s: Sample):
270
+ scale = AdaptiveNanogrid._cell_scale(args, s.element_index)
271
+ return args.cell_volume * scale * scale * scale
272
+
273
+ @wp.func
274
+ def cell_normal(args: CellArg, s: Sample):
275
+ return wp.vec3(0.0)
276
+
277
+ SideIndexArg = Nanogrid.SideIndexArg
278
+ side_index_arg_value = Nanogrid.side_index_arg_value
279
+
280
+ SideArg = AdaptiveNanogridSideArg
281
+
282
+ @wp.func
283
+ def side_to_cell_arg(side_arg: SideArg):
284
+ return side_arg.cell_arg
285
+
286
+ @cache.cached_arg_value
287
+ def side_arg_value(self, device) -> SideArg:
288
+ self._ensure_face_grid()
289
+
290
+ args = self.SideArg()
291
+ args.cell_arg = self.cell_arg_value(device)
292
+ args.face_ijk = self._face_ijk.to(device)
293
+ args.face_flags = self._face_flags.to(device)
294
+ args.face_cell_indices = self._face_cell_indices.to(device)
295
+ transform = self.transform
296
+ args.face_areas = wp.vec3(
297
+ tuple(np.linalg.norm(np.cross(transform[:, k - 2], transform[:, k - 1])) for k in range(3))
298
+ )
299
+
300
+ return args
301
+
302
+ @wp.func
303
+ def boundary_side_index(args: SideIndexArg, boundary_side_index: int):
304
+ return args.boundary_face_indices[boundary_side_index]
305
+
306
+ @wp.func
307
+ def _get_face_level(flags: wp.uint8):
308
+ return wp.int32(flags >> _FACE_LEVEL_BIT)
309
+
310
+ @wp.func
311
+ def _get_face_scale(flags: wp.uint8):
312
+ return float(1 << AdaptiveNanogrid._get_face_level(flags))
313
+
314
+ @wp.func
315
+ def side_position(args: SideArg, s: Sample):
316
+ ijk = args.face_ijk[s.element_index]
317
+ flags = args.face_flags[s.element_index]
318
+ axis = Nanogrid._get_face_axis(flags)
319
+ scale = AdaptiveNanogrid._get_face_scale(flags)
320
+
321
+ uvw = wp.vec3(ijk) + scale * Nanogrid._side_to_cell_coords(axis, 0.0, s.element_coords)
322
+
323
+ cell_grid = args.cell_arg.cell_grid
324
+ return wp.volume_index_to_world(cell_grid, uvw - wp.vec3(0.5))
325
+
326
+ @wp.func
327
+ def side_deformation_gradient(args: SideArg, s: Sample):
328
+ flags = args.face_flags[s.element_index]
329
+ axis = Nanogrid._get_face_axis(flags)
330
+ flip = Nanogrid._get_face_inner_offset(flags)
331
+ scale = AdaptiveNanogrid._get_face_scale(flags)
332
+ v1, v2 = Nanogrid._face_tangent_vecs(args.cell_arg.cell_grid, axis, flip)
333
+ return wp.matrix_from_cols(v1, v2) * scale
334
+
335
+ @wp.func
336
+ def side_inner_inverse_deformation_gradient(args: SideArg, s: Sample):
337
+ s_cell = make_free_sample(AdaptiveNanogrid.side_inner_cell_index(args, s.element_index), Coords())
338
+ return AdaptiveNanogrid.cell_inverse_deformation_gradient(args.cell_arg, s_cell)
339
+
340
+ @wp.func
341
+ def side_outer_inverse_deformation_gradient(args: SideArg, s: Sample):
342
+ s_cell = make_free_sample(AdaptiveNanogrid.side_outer_cell_index(args, s.element_index), Coords())
343
+ return AdaptiveNanogrid.cell_inverse_deformation_gradient(args.cell_arg, s_cell)
344
+
345
+ @wp.func
346
+ def side_measure(args: SideArg, s: Sample):
347
+ flags = args.face_flags[s.element_index]
348
+ axis = Nanogrid._get_face_axis(flags)
349
+ scale = AdaptiveNanogrid._get_face_scale(flags)
350
+ return args.face_areas[axis] * scale * scale
351
+
352
+ @wp.func
353
+ def side_measure_ratio(args: SideArg, s: Sample):
354
+ flags = args.face_flags[s.element_index]
355
+ axis = Nanogrid._get_face_axis(flags)
356
+ scale = AdaptiveNanogrid._get_face_scale(flags)
357
+ return args.face_areas[axis] / (args.cell_arg.cell_volume * scale)
358
+
359
+ @wp.func
360
+ def side_normal(args: SideArg, s: Sample):
361
+ flags = args.face_flags[s.element_index]
362
+ axis = Nanogrid._get_face_axis(flags)
363
+ flip = Nanogrid._get_face_inner_offset(flags)
364
+
365
+ v1, v2 = Nanogrid._face_tangent_vecs(args.cell_arg.cell_grid, axis, flip)
366
+ return wp.cross(v1, v2) / args.face_areas[axis]
367
+
368
+ @wp.func
369
+ def side_inner_cell_index(args: SideArg, side_index: ElementIndex):
370
+ return args.face_cell_indices[side_index][0]
371
+
372
+ @wp.func
373
+ def side_outer_cell_index(args: SideArg, side_index: ElementIndex):
374
+ return args.face_cell_indices[side_index][1]
375
+
376
+ @wp.func
377
+ def _coarse_cell_coords(
378
+ fine_ijk: wp.vec3i,
379
+ fine_level: int,
380
+ fine_coords: Coords,
381
+ coarse_ijk: wp.vec3i,
382
+ coarse_level: int,
383
+ ):
384
+ return (wp.vec3f(fine_ijk - coarse_ijk) + fine_coords * float(1 << fine_level)) / float(1 << coarse_level)
385
+
386
+ @wp.func
387
+ def side_inner_cell_coords(args: SideArg, side_index: ElementIndex, side_coords: Coords):
388
+ flags = args.face_flags[side_index]
389
+ axis = Nanogrid._get_face_axis(flags)
390
+ offset = Nanogrid._get_face_inner_offset(flags)
391
+
392
+ same_level_cell_coords = Nanogrid._side_to_cell_coords(axis, 1.0 - float(offset), side_coords)
393
+ same_level_cell_ijk = args.face_ijk[side_index]
394
+ side_level = AdaptiveNanogrid._get_face_level(flags)
395
+ same_level_cell_ijk[axis] += (offset - 1) << side_level
396
+
397
+ cell_index = AdaptiveNanogrid.side_inner_cell_index(args, side_index)
398
+ cell_level = int(args.cell_arg.cell_level[cell_index])
399
+ cell_ijk = args.cell_arg.cell_ijk[cell_index]
400
+
401
+ return AdaptiveNanogrid._coarse_cell_coords(
402
+ same_level_cell_ijk, side_level, same_level_cell_coords, cell_ijk, cell_level
403
+ )
404
+
405
+ @wp.func
406
+ def side_outer_cell_coords(args: SideArg, side_index: ElementIndex, side_coords: Coords):
407
+ flags = args.face_flags[side_index]
408
+ axis = Nanogrid._get_face_axis(flags)
409
+ offset = Nanogrid._get_face_outer_offset(flags)
410
+
411
+ same_level_cell_coords = Nanogrid._side_to_cell_coords(axis, float(offset), side_coords)
412
+ same_level_cell_ijk = args.face_ijk[side_index]
413
+ side_level = AdaptiveNanogrid._get_face_level(flags)
414
+ same_level_cell_ijk[axis] -= offset << side_level
415
+
416
+ cell_index = AdaptiveNanogrid.side_outer_cell_index(args, side_index)
417
+ cell_level = int(args.cell_arg.cell_level[cell_index])
418
+ cell_ijk = args.cell_arg.cell_ijk[cell_index]
419
+
420
+ return AdaptiveNanogrid._coarse_cell_coords(
421
+ same_level_cell_ijk, side_level, same_level_cell_coords, cell_ijk, cell_level
422
+ )
423
+
424
+ @wp.func
425
+ def side_from_cell_coords(
426
+ args: SideArg,
427
+ side_index: ElementIndex,
428
+ element_index: ElementIndex,
429
+ element_coords: Coords,
430
+ ):
431
+ flags = args.face_flags[side_index]
432
+ axis = Nanogrid._get_face_axis(flags)
433
+ side_level = AdaptiveNanogrid._get_face_level(flags)
434
+ cell_level = int(args.cell_arg.cell_level[element_index])
435
+
436
+ cell_ijk = args.cell_arg.cell_ijk[element_index]
437
+ side_ijk = args.face_ijk[side_index]
438
+
439
+ same_level_cell_coords = AdaptiveNanogrid._coarse_cell_coords(
440
+ cell_ijk, cell_level, element_coords, side_ijk, side_level
441
+ )
442
+
443
+ on_side = (
444
+ same_level_cell_coords[axis] == 0.0
445
+ and wp.min(same_level_cell_coords) >= 0.0
446
+ and wp.max(same_level_cell_coords) <= 1.0
447
+ )
448
+
449
+ return wp.where(
450
+ on_side,
451
+ Coords(same_level_cell_coords[(axis + 1) % 3], same_level_cell_coords[(axis + 2) % 3], 0.0),
452
+ Coords(OUTSIDE),
453
+ )
454
+
455
+ def _build_face_grid(self, temporary_store: Optional[cache.TemporaryStore] = None):
456
+ device = self._cell_grid.device
457
+
458
+ # Create a first grid with faces from cells
459
+ cell_face_grid = _build_cell_face_grid(self._cell_ijk, self._cell_level, self._cell_grid, temporary_store)
460
+
461
+ # Complete faces at resolution boundaries
462
+ self._face_grid = _build_completed_face_grid(
463
+ cell_face_grid, self._cell_grid, self.level_count, self._cell_level, temporary_store
464
+ )
465
+
466
+ face_count = self._face_grid.get_voxel_count()
467
+ self._face_ijk = wp.array(shape=(face_count,), dtype=wp.vec3i, device=device)
468
+ self._face_grid.get_voxels(out=self._face_ijk)
469
+
470
+ # Finalize our faces, cache flags and neighbour indices
471
+ self._face_cell_indices = wp.array(shape=(face_count,), dtype=wp.vec2i, device=device)
472
+ self._face_flags = wp.array(shape=(face_count,), dtype=wp.uint8, device=device)
473
+ boundary_face_mask = cache.borrow_temporary(temporary_store, shape=(face_count,), dtype=wp.int32, device=device)
474
+
475
+ wp.launch(
476
+ _build_face_indices_and_flags,
477
+ dim=face_count,
478
+ device=device,
479
+ inputs=[
480
+ self._cell_grid.id,
481
+ self.level_count,
482
+ self._cell_level,
483
+ self._face_ijk,
484
+ self._face_cell_indices,
485
+ self._face_flags,
486
+ boundary_face_mask.array,
487
+ ],
488
+ )
489
+ boundary_face_indices, _ = utils.masked_indices(boundary_face_mask.array)
490
+ self._boundary_face_indices = boundary_face_indices.detach()
491
+
492
+ def _ensure_face_grid(self):
493
+ if self._face_ijk is None:
494
+ self._build_face_grid()
495
+
496
+ def _ensure_stacked_edge_grid(self):
497
+ if self._stacked_edge_grid is None:
498
+ self._stacked_edge_grid = _build_stacked_edge_grid(
499
+ self._cell_ijk, self._cell_level, self._cell_grid, temporary_store=None
500
+ )
501
+ self._stacked_edge_count = self._stacked_edge_grid.get_voxel_count()
502
+
503
+ def _ensure_stacked_face_grid(self):
504
+ if self._stacked_face_grid is None:
505
+ self._stacked_face_grid = _build_stacked_face_grid(
506
+ self._cell_ijk, self._cell_level, self._cell_grid, temporary_store=None
507
+ )
508
+ self._stacked_face_count = self._stacked_face_grid.get_voxel_count()
509
+
510
+ @wp.func
511
+ def coarse_ijk(ijk: wp.vec3i, level: int):
512
+ # technically implementation-defined, but
513
+ # right-shifting negative numbers 1-fills on all our platforms
514
+ return wp.vec3i(ijk[0] >> level, ijk[1] >> level, ijk[2] >> level)
515
+
516
+ @wp.func
517
+ def fine_ijk(ijk: wp.vec3i, level: int):
518
+ # Our coords cannot exceed 1<<21,so no worries about overwriting the sign bit
519
+ return wp.vec3i(ijk[0] << level, ijk[1] << level, ijk[2] << level)
520
+
521
+ @wp.func
522
+ def encode_axis_and_level(ijk: wp.vec3i, axis: int, level: int):
523
+ # Embed a 3-bit level in the voxel coordinates
524
+ # by switching the _GRID_LEVEL_BIT for each axis
525
+
526
+ for ax in range(3):
527
+ coord = ijk[ax]
528
+ level_flag = ((level >> ax) & 1) << _GRID_LEVEL_BIT
529
+ ijk[ax] = wp.where(coord < 0, coord & ~level_flag, coord | level_flag)
530
+
531
+ return _add_axis_flag(ijk, axis)
532
+
533
+ @wp.func
534
+ def find_cell(
535
+ cell_grid: wp.uint64,
536
+ ijk: wp.vec3i,
537
+ level_count: int,
538
+ cell_level: wp.array(dtype=wp.uint8),
539
+ ):
540
+ for l in range(level_count):
541
+ mask = ~((1 << l) - 1)
542
+ cell_index = wp.volume_lookup_index(cell_grid, ijk[0] & mask, ijk[1] & mask, ijk[2] & mask)
543
+ if cell_index != -1:
544
+ if int(cell_level[cell_index]) >= l:
545
+ return cell_index
546
+
547
+ return -1
548
+
549
+
550
+ @wp.kernel
551
+ def _cell_node_indices(
552
+ cell_ijk: wp.array(dtype=wp.vec3i),
553
+ cell_level: wp.array(dtype=wp.uint8),
554
+ node_ijk: wp.array2d(dtype=wp.vec3i),
555
+ ):
556
+ cell, n = wp.tid()
557
+ level = int(cell_level[cell])
558
+ offset = AdaptiveNanogrid.fine_ijk(wp.vec3i((n & 4) >> 2, (n & 2) >> 1, n & 1), level)
559
+ node_ijk[cell, n] = cell_ijk[cell] + offset
560
+
561
+
562
+ @wp.kernel
563
+ def _cell_face_indices(
564
+ cell_ijk: wp.array(dtype=wp.vec3i),
565
+ cell_level: wp.array(dtype=wp.uint8),
566
+ node_ijk: wp.array2d(dtype=wp.vec3i),
567
+ ):
568
+ cell = wp.tid()
569
+ ijk = cell_ijk[cell]
570
+ node_ijk[cell, 0] = _add_axis_flag(ijk, 0)
571
+ node_ijk[cell, 1] = _add_axis_flag(ijk, 1)
572
+ node_ijk[cell, 2] = _add_axis_flag(ijk, 2)
573
+
574
+ offset = 1 << int(cell_level[cell])
575
+
576
+ node_ijk[cell, 3] = _add_axis_flag(ijk + wp.vec3i(offset, 0, 0), 0)
577
+ node_ijk[cell, 4] = _add_axis_flag(ijk + wp.vec3i(0, offset, 0), 1)
578
+ node_ijk[cell, 5] = _add_axis_flag(ijk + wp.vec3i(0, 0, offset), 2)
579
+
580
+
581
+ @wp.kernel
582
+ def _cell_stacked_face_indices(
583
+ cell_ijk: wp.array(dtype=wp.vec3i),
584
+ cell_level: wp.array(dtype=wp.uint8),
585
+ node_ijk: wp.array2d(dtype=wp.vec3i),
586
+ ):
587
+ cell = wp.tid()
588
+
589
+ level = int(cell_level[cell])
590
+ ijk = AdaptiveNanogrid.coarse_ijk(cell_ijk[cell], level)
591
+
592
+ node_ijk[cell, 0] = AdaptiveNanogrid.encode_axis_and_level(ijk, 0, level)
593
+ node_ijk[cell, 1] = AdaptiveNanogrid.encode_axis_and_level(ijk, 1, level)
594
+ node_ijk[cell, 2] = AdaptiveNanogrid.encode_axis_and_level(ijk, 2, level)
595
+
596
+ node_ijk[cell, 3] = AdaptiveNanogrid.encode_axis_and_level(ijk + wp.vec3i(1, 0, 0), 0, level)
597
+ node_ijk[cell, 4] = AdaptiveNanogrid.encode_axis_and_level(ijk + wp.vec3i(0, 1, 0), 1, level)
598
+ node_ijk[cell, 5] = AdaptiveNanogrid.encode_axis_and_level(ijk + wp.vec3i(0, 0, 1), 2, level)
599
+
600
+
601
+ @wp.kernel
602
+ def _cell_stacked_edge_indices(
603
+ cell_ijk: wp.array(dtype=wp.vec3i),
604
+ cell_level: wp.array(dtype=wp.uint8),
605
+ edge_ijk: wp.array2d(dtype=wp.vec3i),
606
+ ):
607
+ cell = wp.tid()
608
+ level = int(cell_level[cell])
609
+ ijk = AdaptiveNanogrid.coarse_ijk(cell_ijk[cell], level)
610
+
611
+ edge_ijk[cell, 0] = AdaptiveNanogrid.encode_axis_and_level(ijk, 0, level)
612
+ edge_ijk[cell, 1] = AdaptiveNanogrid.encode_axis_and_level(ijk, 1, level)
613
+ edge_ijk[cell, 2] = AdaptiveNanogrid.encode_axis_and_level(ijk, 2, level)
614
+
615
+ edge_ijk[cell, 3] = AdaptiveNanogrid.encode_axis_and_level(ijk + wp.vec3i(0, 1, 0), 0, level)
616
+ edge_ijk[cell, 4] = AdaptiveNanogrid.encode_axis_and_level(ijk + wp.vec3i(0, 0, 1), 1, level)
617
+ edge_ijk[cell, 5] = AdaptiveNanogrid.encode_axis_and_level(ijk + wp.vec3i(1, 0, 0), 2, level)
618
+
619
+ edge_ijk[cell, 6] = AdaptiveNanogrid.encode_axis_and_level(ijk + wp.vec3i(0, 1, 1), 0, level)
620
+ edge_ijk[cell, 7] = AdaptiveNanogrid.encode_axis_and_level(ijk + wp.vec3i(1, 0, 1), 1, level)
621
+ edge_ijk[cell, 8] = AdaptiveNanogrid.encode_axis_and_level(ijk + wp.vec3i(1, 1, 0), 2, level)
622
+
623
+ edge_ijk[cell, 9] = AdaptiveNanogrid.encode_axis_and_level(ijk + wp.vec3i(0, 0, 1), 0, level)
624
+ edge_ijk[cell, 10] = AdaptiveNanogrid.encode_axis_and_level(ijk + wp.vec3i(1, 0, 0), 1, level)
625
+ edge_ijk[cell, 11] = AdaptiveNanogrid.encode_axis_and_level(ijk + wp.vec3i(0, 1, 0), 2, level)
626
+
627
+
628
+ def _build_node_grid(cell_ijk, cell_level, cell_grid: wp.Volume, temporary_store: cache.TemporaryStore):
629
+ cell_count = cell_ijk.shape[0]
630
+
631
+ cell_nodes = cache.borrow_temporary(temporary_store, shape=(cell_count, 8), dtype=wp.vec3i, device=cell_ijk.device)
632
+ wp.launch(
633
+ _cell_node_indices,
634
+ dim=cell_nodes.array.shape,
635
+ inputs=[cell_ijk, cell_level, cell_nodes.array],
636
+ device=cell_ijk.device,
637
+ )
638
+ node_grid = wp.Volume.allocate_by_voxels(
639
+ cell_nodes.array.flatten(), voxel_size=cell_grid.get_voxel_size()[0], device=cell_ijk.device
640
+ )
641
+
642
+ return node_grid
643
+
644
+
645
+ def _build_cell_face_grid(cell_ijk, cell_level, grid: wp.Volume, temporary_store: cache.TemporaryStore):
646
+ cell_count = cell_ijk.shape[0]
647
+
648
+ cell_faces = cache.borrow_temporary(temporary_store, shape=(cell_count, 6), dtype=wp.vec3i, device=cell_ijk.device)
649
+ wp.launch(
650
+ _cell_face_indices, dim=cell_count, inputs=[cell_ijk, cell_level, cell_faces.array], device=cell_ijk.device
651
+ )
652
+ face_grid = wp.Volume.allocate_by_voxels(
653
+ cell_faces.array.flatten(), voxel_size=grid.get_voxel_size()[0], device=cell_ijk.device
654
+ )
655
+
656
+ return face_grid
657
+
658
+
659
+ def _build_completed_face_grid(
660
+ cell_face_grid: wp.Volume,
661
+ cell_grid: wp.Volume,
662
+ level_count: int,
663
+ cell_level: wp.array,
664
+ temporary_store: cache.TemporaryStore,
665
+ ):
666
+ device = cell_grid.device
667
+
668
+ cell_face_count = cell_face_grid.get_voxel_count()
669
+ cell_face_ijk = cache.borrow_temporary(temporary_store, shape=(cell_face_count,), dtype=wp.vec3i, device=device)
670
+
671
+ additional_face_count = cache.borrow_temporary(temporary_store, shape=1, dtype=int, device=device)
672
+
673
+ # Count the number of supplemental faces we need to add at resolution boundaries
674
+ cell_face_grid.get_voxels(out=cell_face_ijk.array)
675
+ additional_face_count.array.zero_()
676
+ wp.launch(
677
+ _count_multires_faces,
678
+ dim=cell_face_count,
679
+ device=device,
680
+ inputs=[
681
+ cell_grid.id,
682
+ level_count,
683
+ cell_level,
684
+ cell_face_ijk.array,
685
+ additional_face_count.array,
686
+ ],
687
+ )
688
+
689
+ # Cat these new faces with the original ones
690
+ cat_face_count = cell_face_count + int(additional_face_count.array.numpy()[0])
691
+ cat_face_ijk = cache.borrow_temporary(temporary_store, shape=(cat_face_count,), dtype=wp.vec3i, device=device)
692
+ wp.copy(src=cell_face_ijk.array, dest=cat_face_ijk.array, dest_offset=cat_face_count - cell_face_count)
693
+
694
+ wp.launch(
695
+ _fill_multires_faces,
696
+ dim=cell_face_count,
697
+ device=device,
698
+ inputs=[
699
+ cell_grid.id,
700
+ level_count,
701
+ cell_level,
702
+ cell_face_ijk.array,
703
+ additional_face_count.array,
704
+ cat_face_ijk.array,
705
+ ],
706
+ )
707
+
708
+ # Now recreate a new grid with all those faces
709
+ face_grid = wp.Volume.allocate_by_voxels(
710
+ cat_face_ijk.array.flatten(), voxel_size=cell_face_grid.get_voxel_size(), device=device
711
+ )
712
+
713
+ return face_grid
714
+
715
+
716
+ def _build_stacked_face_grid(cell_ijk, cell_level, grid: wp.Volume, temporary_store: cache.TemporaryStore):
717
+ cell_count = cell_ijk.shape[0]
718
+
719
+ cell_faces = cache.borrow_temporary(temporary_store, shape=(cell_count, 6), dtype=wp.vec3i, device=cell_ijk.device)
720
+ wp.launch(
721
+ _cell_stacked_face_indices,
722
+ dim=cell_count,
723
+ inputs=[cell_ijk, cell_level, cell_faces.array],
724
+ device=cell_ijk.device,
725
+ )
726
+ face_grid = wp.Volume.allocate_by_voxels(
727
+ cell_faces.array.flatten(), voxel_size=grid.get_voxel_size()[0], device=cell_ijk.device
728
+ )
729
+
730
+ return face_grid
731
+
732
+
733
+ def _build_stacked_edge_grid(cell_ijk, cell_level, grid: wp.Volume, temporary_store: cache.TemporaryStore):
734
+ cell_count = cell_ijk.shape[0]
735
+
736
+ cell_edges = cache.borrow_temporary(temporary_store, shape=(cell_count, 12), dtype=wp.vec3i, device=cell_ijk.device)
737
+ wp.launch(
738
+ _cell_stacked_edge_indices,
739
+ dim=cell_count,
740
+ inputs=[cell_ijk, cell_level, cell_edges.array],
741
+ device=cell_ijk.device,
742
+ )
743
+ edge_grid = wp.Volume.allocate_by_voxels(
744
+ cell_edges.array.flatten(), voxel_size=grid.get_voxel_size()[0], device=cell_ijk.device
745
+ )
746
+
747
+ return edge_grid
748
+
749
+
750
+ @wp.func
751
+ def _find_face_neighbours(
752
+ cell_grid: wp.uint64,
753
+ ijk: wp.vec3i,
754
+ axis: int,
755
+ level_count: int,
756
+ cell_level: wp.array(dtype=wp.uint8),
757
+ ):
758
+ ijk_minus = ijk
759
+ ijk_minus[axis] -= 1
760
+
761
+ plus_cell_index = AdaptiveNanogrid.find_cell(cell_grid, ijk, level_count, cell_level)
762
+ minus_cell_index = AdaptiveNanogrid.find_cell(cell_grid, ijk_minus, level_count, cell_level)
763
+ return plus_cell_index, minus_cell_index
764
+
765
+
766
+ @wp.kernel
767
+ def _count_multires_faces(
768
+ cell_grid: wp.uint64,
769
+ level_count: int,
770
+ cell_level: wp.array(dtype=wp.uint8),
771
+ face_ijk: wp.array(dtype=wp.vec3i),
772
+ count: wp.array(dtype=int),
773
+ ):
774
+ face = wp.tid()
775
+
776
+ axis, ijk = _extract_axis_flag(face_ijk[face])
777
+
778
+ plus_cell_index, minus_cell_index = _find_face_neighbours(cell_grid, ijk, axis, level_count, cell_level)
779
+
780
+ if plus_cell_index == -1 or minus_cell_index == -1:
781
+ return
782
+
783
+ plus_level = int(cell_level[plus_cell_index])
784
+ minus_level = int(cell_level[minus_cell_index])
785
+ level_diff = wp.abs(plus_level - minus_level)
786
+
787
+ if level_diff != 0:
788
+ fine_face_count = 1 << (2 * level_diff)
789
+ wp.atomic_add(count, 0, fine_face_count)
790
+
791
+
792
+ @wp.kernel
793
+ def _fill_multires_faces(
794
+ cell_grid: wp.uint64,
795
+ level_count: int,
796
+ cell_level: wp.array(dtype=wp.uint8),
797
+ face_ijk: wp.array(dtype=wp.vec3i),
798
+ count: wp.array(dtype=int),
799
+ added_ijk: wp.array(dtype=wp.vec3i),
800
+ ):
801
+ face = wp.tid()
802
+
803
+ axis, ijk = _extract_axis_flag(face_ijk[face])
804
+ plus_cell_index, minus_cell_index = _find_face_neighbours(cell_grid, ijk, axis, level_count, cell_level)
805
+
806
+ if plus_cell_index == -1 or minus_cell_index == -1:
807
+ return
808
+
809
+ plus_level = int(cell_level[plus_cell_index])
810
+ minus_level = int(cell_level[minus_cell_index])
811
+ level_diff = wp.abs(plus_level - minus_level)
812
+
813
+ if level_diff != 0:
814
+ fine_face_count = 1 << (2 * level_diff)
815
+ side_mask = (1 << level_diff) - 1
816
+
817
+ fine_level = min(plus_level, minus_level)
818
+ base_level = max(plus_level, minus_level)
819
+
820
+ base_mask = ~((1 << base_level) - 1)
821
+ base_ijk = wp.vec3i(ijk[0] & base_mask, ijk[1] & base_mask, ijk[2] & base_mask)
822
+
823
+ offset = wp.atomic_sub(count, 0, fine_face_count) - fine_face_count
824
+ for f in range(fine_face_count):
825
+ f_ijk = base_ijk
826
+ f_ijk[(axis + 1) % 3] |= (f & side_mask) << fine_level
827
+ f_ijk[(axis + 2) % 3] |= (f >> level_diff) << fine_level
828
+ added_ijk[offset + f] = _add_axis_flag(f_ijk, axis)
829
+
830
+
831
+ @wp.kernel
832
+ def _build_face_indices_and_flags(
833
+ cell_grid: wp.uint64,
834
+ level_count: int,
835
+ cell_level: wp.array(dtype=wp.uint8),
836
+ face_ijk: wp.array(dtype=wp.vec3i),
837
+ face_cell_indices: wp.array(dtype=wp.vec2i),
838
+ face_flags: wp.array(dtype=wp.uint8),
839
+ boundary_face_mask: wp.array(dtype=int),
840
+ ):
841
+ face = wp.tid()
842
+
843
+ axis, ijk = _extract_axis_flag(face_ijk[face])
844
+
845
+ plus_cell_index, minus_cell_index = _find_face_neighbours(cell_grid, ijk, axis, level_count, cell_level)
846
+
847
+ inner_cell = wp.where(minus_cell_index == -1, plus_cell_index, minus_cell_index)
848
+ outer_cell = wp.where(plus_cell_index == -1, minus_cell_index, plus_cell_index)
849
+
850
+ face_level = wp.min(cell_level[inner_cell], cell_level[outer_cell])
851
+
852
+ face_ijk[face] = ijk
853
+ flags = _make_face_flags(axis, plus_cell_index, minus_cell_index) | (face_level << _FACE_LEVEL_BIT)
854
+ face_flags[face] = flags
855
+ boundary_face_mask[face] = _get_boundary_mask(flags)
856
+
857
+ face_cell_indices[face] = wp.vec2i(inner_cell, outer_cell)