warp-lang 1.10.0__py3-none-macosx_11_0_arm64.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 (468) hide show
  1. warp/__init__.py +334 -0
  2. warp/__init__.pyi +5856 -0
  3. warp/_src/__init__.py +14 -0
  4. warp/_src/autograd.py +1077 -0
  5. warp/_src/build.py +620 -0
  6. warp/_src/build_dll.py +642 -0
  7. warp/_src/builtins.py +10555 -0
  8. warp/_src/codegen.py +4361 -0
  9. warp/_src/config.py +178 -0
  10. warp/_src/constants.py +59 -0
  11. warp/_src/context.py +8352 -0
  12. warp/_src/dlpack.py +464 -0
  13. warp/_src/fabric.py +362 -0
  14. warp/_src/fem/__init__.py +14 -0
  15. warp/_src/fem/adaptivity.py +510 -0
  16. warp/_src/fem/cache.py +689 -0
  17. warp/_src/fem/dirichlet.py +190 -0
  18. warp/_src/fem/domain.py +553 -0
  19. warp/_src/fem/field/__init__.py +131 -0
  20. warp/_src/fem/field/field.py +703 -0
  21. warp/_src/fem/field/nodal_field.py +403 -0
  22. warp/_src/fem/field/restriction.py +39 -0
  23. warp/_src/fem/field/virtual.py +1021 -0
  24. warp/_src/fem/geometry/__init__.py +32 -0
  25. warp/_src/fem/geometry/adaptive_nanogrid.py +782 -0
  26. warp/_src/fem/geometry/closest_point.py +99 -0
  27. warp/_src/fem/geometry/deformed_geometry.py +277 -0
  28. warp/_src/fem/geometry/element.py +854 -0
  29. warp/_src/fem/geometry/geometry.py +693 -0
  30. warp/_src/fem/geometry/grid_2d.py +478 -0
  31. warp/_src/fem/geometry/grid_3d.py +539 -0
  32. warp/_src/fem/geometry/hexmesh.py +956 -0
  33. warp/_src/fem/geometry/nanogrid.py +660 -0
  34. warp/_src/fem/geometry/partition.py +483 -0
  35. warp/_src/fem/geometry/quadmesh.py +597 -0
  36. warp/_src/fem/geometry/tetmesh.py +762 -0
  37. warp/_src/fem/geometry/trimesh.py +588 -0
  38. warp/_src/fem/integrate.py +2507 -0
  39. warp/_src/fem/linalg.py +385 -0
  40. warp/_src/fem/operator.py +398 -0
  41. warp/_src/fem/polynomial.py +231 -0
  42. warp/_src/fem/quadrature/__init__.py +17 -0
  43. warp/_src/fem/quadrature/pic_quadrature.py +318 -0
  44. warp/_src/fem/quadrature/quadrature.py +665 -0
  45. warp/_src/fem/space/__init__.py +248 -0
  46. warp/_src/fem/space/basis_function_space.py +499 -0
  47. warp/_src/fem/space/basis_space.py +681 -0
  48. warp/_src/fem/space/dof_mapper.py +253 -0
  49. warp/_src/fem/space/function_space.py +312 -0
  50. warp/_src/fem/space/grid_2d_function_space.py +179 -0
  51. warp/_src/fem/space/grid_3d_function_space.py +229 -0
  52. warp/_src/fem/space/hexmesh_function_space.py +255 -0
  53. warp/_src/fem/space/nanogrid_function_space.py +199 -0
  54. warp/_src/fem/space/partition.py +435 -0
  55. warp/_src/fem/space/quadmesh_function_space.py +222 -0
  56. warp/_src/fem/space/restriction.py +221 -0
  57. warp/_src/fem/space/shape/__init__.py +152 -0
  58. warp/_src/fem/space/shape/cube_shape_function.py +1107 -0
  59. warp/_src/fem/space/shape/shape_function.py +134 -0
  60. warp/_src/fem/space/shape/square_shape_function.py +928 -0
  61. warp/_src/fem/space/shape/tet_shape_function.py +829 -0
  62. warp/_src/fem/space/shape/triangle_shape_function.py +674 -0
  63. warp/_src/fem/space/tetmesh_function_space.py +270 -0
  64. warp/_src/fem/space/topology.py +461 -0
  65. warp/_src/fem/space/trimesh_function_space.py +193 -0
  66. warp/_src/fem/types.py +114 -0
  67. warp/_src/fem/utils.py +488 -0
  68. warp/_src/jax.py +188 -0
  69. warp/_src/jax_experimental/__init__.py +14 -0
  70. warp/_src/jax_experimental/custom_call.py +389 -0
  71. warp/_src/jax_experimental/ffi.py +1286 -0
  72. warp/_src/jax_experimental/xla_ffi.py +658 -0
  73. warp/_src/marching_cubes.py +710 -0
  74. warp/_src/math.py +416 -0
  75. warp/_src/optim/__init__.py +14 -0
  76. warp/_src/optim/adam.py +165 -0
  77. warp/_src/optim/linear.py +1608 -0
  78. warp/_src/optim/sgd.py +114 -0
  79. warp/_src/paddle.py +408 -0
  80. warp/_src/render/__init__.py +14 -0
  81. warp/_src/render/imgui_manager.py +291 -0
  82. warp/_src/render/render_opengl.py +3638 -0
  83. warp/_src/render/render_usd.py +939 -0
  84. warp/_src/render/utils.py +162 -0
  85. warp/_src/sparse.py +2718 -0
  86. warp/_src/tape.py +1208 -0
  87. warp/_src/thirdparty/__init__.py +0 -0
  88. warp/_src/thirdparty/appdirs.py +598 -0
  89. warp/_src/thirdparty/dlpack.py +145 -0
  90. warp/_src/thirdparty/unittest_parallel.py +676 -0
  91. warp/_src/torch.py +393 -0
  92. warp/_src/types.py +5888 -0
  93. warp/_src/utils.py +1695 -0
  94. warp/autograd.py +33 -0
  95. warp/bin/libwarp-clang.dylib +0 -0
  96. warp/bin/libwarp.dylib +0 -0
  97. warp/build.py +29 -0
  98. warp/build_dll.py +24 -0
  99. warp/codegen.py +24 -0
  100. warp/constants.py +24 -0
  101. warp/context.py +33 -0
  102. warp/dlpack.py +24 -0
  103. warp/examples/__init__.py +24 -0
  104. warp/examples/assets/bear.usd +0 -0
  105. warp/examples/assets/bunny.usd +0 -0
  106. warp/examples/assets/cube.usd +0 -0
  107. warp/examples/assets/nonuniform.usd +0 -0
  108. warp/examples/assets/nvidia_logo.png +0 -0
  109. warp/examples/assets/pixel.jpg +0 -0
  110. warp/examples/assets/rocks.nvdb +0 -0
  111. warp/examples/assets/rocks.usd +0 -0
  112. warp/examples/assets/sphere.usd +0 -0
  113. warp/examples/assets/square_cloth.usd +0 -0
  114. warp/examples/benchmarks/benchmark_api.py +389 -0
  115. warp/examples/benchmarks/benchmark_cloth.py +296 -0
  116. warp/examples/benchmarks/benchmark_cloth_cupy.py +96 -0
  117. warp/examples/benchmarks/benchmark_cloth_jax.py +105 -0
  118. warp/examples/benchmarks/benchmark_cloth_numba.py +161 -0
  119. warp/examples/benchmarks/benchmark_cloth_numpy.py +85 -0
  120. warp/examples/benchmarks/benchmark_cloth_paddle.py +94 -0
  121. warp/examples/benchmarks/benchmark_cloth_pytorch.py +94 -0
  122. warp/examples/benchmarks/benchmark_cloth_taichi.py +120 -0
  123. warp/examples/benchmarks/benchmark_cloth_warp.py +153 -0
  124. warp/examples/benchmarks/benchmark_gemm.py +164 -0
  125. warp/examples/benchmarks/benchmark_interop_paddle.py +166 -0
  126. warp/examples/benchmarks/benchmark_interop_torch.py +166 -0
  127. warp/examples/benchmarks/benchmark_launches.py +301 -0
  128. warp/examples/benchmarks/benchmark_tile_load_store.py +103 -0
  129. warp/examples/benchmarks/benchmark_tile_sort.py +155 -0
  130. warp/examples/browse.py +37 -0
  131. warp/examples/core/example_cupy.py +86 -0
  132. warp/examples/core/example_dem.py +241 -0
  133. warp/examples/core/example_fluid.py +299 -0
  134. warp/examples/core/example_graph_capture.py +150 -0
  135. warp/examples/core/example_marching_cubes.py +195 -0
  136. warp/examples/core/example_mesh.py +180 -0
  137. warp/examples/core/example_mesh_intersect.py +211 -0
  138. warp/examples/core/example_nvdb.py +182 -0
  139. warp/examples/core/example_raycast.py +111 -0
  140. warp/examples/core/example_raymarch.py +205 -0
  141. warp/examples/core/example_render_opengl.py +290 -0
  142. warp/examples/core/example_sample_mesh.py +300 -0
  143. warp/examples/core/example_sph.py +411 -0
  144. warp/examples/core/example_spin_lock.py +93 -0
  145. warp/examples/core/example_torch.py +211 -0
  146. warp/examples/core/example_wave.py +269 -0
  147. warp/examples/core/example_work_queue.py +118 -0
  148. warp/examples/distributed/example_jacobi_mpi.py +506 -0
  149. warp/examples/fem/example_adaptive_grid.py +286 -0
  150. warp/examples/fem/example_apic_fluid.py +469 -0
  151. warp/examples/fem/example_burgers.py +261 -0
  152. warp/examples/fem/example_convection_diffusion.py +181 -0
  153. warp/examples/fem/example_convection_diffusion_dg.py +225 -0
  154. warp/examples/fem/example_darcy_ls_optimization.py +489 -0
  155. warp/examples/fem/example_deformed_geometry.py +172 -0
  156. warp/examples/fem/example_diffusion.py +196 -0
  157. warp/examples/fem/example_diffusion_3d.py +225 -0
  158. warp/examples/fem/example_diffusion_mgpu.py +225 -0
  159. warp/examples/fem/example_distortion_energy.py +228 -0
  160. warp/examples/fem/example_elastic_shape_optimization.py +387 -0
  161. warp/examples/fem/example_magnetostatics.py +242 -0
  162. warp/examples/fem/example_mixed_elasticity.py +293 -0
  163. warp/examples/fem/example_navier_stokes.py +263 -0
  164. warp/examples/fem/example_nonconforming_contact.py +300 -0
  165. warp/examples/fem/example_stokes.py +213 -0
  166. warp/examples/fem/example_stokes_transfer.py +262 -0
  167. warp/examples/fem/example_streamlines.py +357 -0
  168. warp/examples/fem/utils.py +1047 -0
  169. warp/examples/interop/example_jax_callable.py +146 -0
  170. warp/examples/interop/example_jax_ffi_callback.py +132 -0
  171. warp/examples/interop/example_jax_kernel.py +232 -0
  172. warp/examples/optim/example_diffray.py +561 -0
  173. warp/examples/optim/example_fluid_checkpoint.py +497 -0
  174. warp/examples/tile/example_tile_block_cholesky.py +502 -0
  175. warp/examples/tile/example_tile_cholesky.py +88 -0
  176. warp/examples/tile/example_tile_convolution.py +66 -0
  177. warp/examples/tile/example_tile_fft.py +55 -0
  178. warp/examples/tile/example_tile_filtering.py +113 -0
  179. warp/examples/tile/example_tile_matmul.py +85 -0
  180. warp/examples/tile/example_tile_mcgp.py +191 -0
  181. warp/examples/tile/example_tile_mlp.py +385 -0
  182. warp/examples/tile/example_tile_nbody.py +199 -0
  183. warp/fabric.py +24 -0
  184. warp/fem/__init__.py +173 -0
  185. warp/fem/adaptivity.py +26 -0
  186. warp/fem/cache.py +30 -0
  187. warp/fem/dirichlet.py +24 -0
  188. warp/fem/field/__init__.py +24 -0
  189. warp/fem/field/field.py +26 -0
  190. warp/fem/geometry/__init__.py +21 -0
  191. warp/fem/geometry/closest_point.py +31 -0
  192. warp/fem/linalg.py +38 -0
  193. warp/fem/operator.py +32 -0
  194. warp/fem/polynomial.py +29 -0
  195. warp/fem/space/__init__.py +22 -0
  196. warp/fem/space/basis_space.py +24 -0
  197. warp/fem/space/shape/__init__.py +68 -0
  198. warp/fem/space/topology.py +24 -0
  199. warp/fem/types.py +24 -0
  200. warp/fem/utils.py +32 -0
  201. warp/jax.py +29 -0
  202. warp/jax_experimental/__init__.py +29 -0
  203. warp/jax_experimental/custom_call.py +29 -0
  204. warp/jax_experimental/ffi.py +39 -0
  205. warp/jax_experimental/xla_ffi.py +24 -0
  206. warp/marching_cubes.py +24 -0
  207. warp/math.py +37 -0
  208. warp/native/array.h +1687 -0
  209. warp/native/builtin.h +2327 -0
  210. warp/native/bvh.cpp +562 -0
  211. warp/native/bvh.cu +826 -0
  212. warp/native/bvh.h +555 -0
  213. warp/native/clang/clang.cpp +541 -0
  214. warp/native/coloring.cpp +622 -0
  215. warp/native/crt.cpp +51 -0
  216. warp/native/crt.h +568 -0
  217. warp/native/cuda_crt.h +1058 -0
  218. warp/native/cuda_util.cpp +677 -0
  219. warp/native/cuda_util.h +313 -0
  220. warp/native/error.cpp +77 -0
  221. warp/native/error.h +36 -0
  222. warp/native/exports.h +2023 -0
  223. warp/native/fabric.h +246 -0
  224. warp/native/hashgrid.cpp +311 -0
  225. warp/native/hashgrid.cu +89 -0
  226. warp/native/hashgrid.h +240 -0
  227. warp/native/initializer_array.h +41 -0
  228. warp/native/intersect.h +1253 -0
  229. warp/native/intersect_adj.h +375 -0
  230. warp/native/intersect_tri.h +348 -0
  231. warp/native/mat.h +5189 -0
  232. warp/native/mathdx.cpp +93 -0
  233. warp/native/matnn.h +221 -0
  234. warp/native/mesh.cpp +266 -0
  235. warp/native/mesh.cu +406 -0
  236. warp/native/mesh.h +2097 -0
  237. warp/native/nanovdb/GridHandle.h +533 -0
  238. warp/native/nanovdb/HostBuffer.h +591 -0
  239. warp/native/nanovdb/NanoVDB.h +6246 -0
  240. warp/native/nanovdb/NodeManager.h +323 -0
  241. warp/native/nanovdb/PNanoVDB.h +3390 -0
  242. warp/native/noise.h +859 -0
  243. warp/native/quat.h +1664 -0
  244. warp/native/rand.h +342 -0
  245. warp/native/range.h +145 -0
  246. warp/native/reduce.cpp +174 -0
  247. warp/native/reduce.cu +363 -0
  248. warp/native/runlength_encode.cpp +79 -0
  249. warp/native/runlength_encode.cu +61 -0
  250. warp/native/scan.cpp +47 -0
  251. warp/native/scan.cu +55 -0
  252. warp/native/scan.h +23 -0
  253. warp/native/solid_angle.h +466 -0
  254. warp/native/sort.cpp +251 -0
  255. warp/native/sort.cu +286 -0
  256. warp/native/sort.h +35 -0
  257. warp/native/sparse.cpp +241 -0
  258. warp/native/sparse.cu +435 -0
  259. warp/native/spatial.h +1306 -0
  260. warp/native/svd.h +727 -0
  261. warp/native/temp_buffer.h +46 -0
  262. warp/native/tile.h +4124 -0
  263. warp/native/tile_radix_sort.h +1112 -0
  264. warp/native/tile_reduce.h +838 -0
  265. warp/native/tile_scan.h +240 -0
  266. warp/native/tuple.h +189 -0
  267. warp/native/vec.h +2199 -0
  268. warp/native/version.h +23 -0
  269. warp/native/volume.cpp +501 -0
  270. warp/native/volume.cu +68 -0
  271. warp/native/volume.h +970 -0
  272. warp/native/volume_builder.cu +483 -0
  273. warp/native/volume_builder.h +52 -0
  274. warp/native/volume_impl.h +70 -0
  275. warp/native/warp.cpp +1143 -0
  276. warp/native/warp.cu +4604 -0
  277. warp/native/warp.h +358 -0
  278. warp/optim/__init__.py +20 -0
  279. warp/optim/adam.py +24 -0
  280. warp/optim/linear.py +35 -0
  281. warp/optim/sgd.py +24 -0
  282. warp/paddle.py +24 -0
  283. warp/py.typed +0 -0
  284. warp/render/__init__.py +22 -0
  285. warp/render/imgui_manager.py +29 -0
  286. warp/render/render_opengl.py +24 -0
  287. warp/render/render_usd.py +24 -0
  288. warp/render/utils.py +24 -0
  289. warp/sparse.py +51 -0
  290. warp/tape.py +24 -0
  291. warp/tests/__init__.py +1 -0
  292. warp/tests/__main__.py +4 -0
  293. warp/tests/assets/curlnoise_golden.npy +0 -0
  294. warp/tests/assets/mlp_golden.npy +0 -0
  295. warp/tests/assets/pixel.npy +0 -0
  296. warp/tests/assets/pnoise_golden.npy +0 -0
  297. warp/tests/assets/spiky.usd +0 -0
  298. warp/tests/assets/test_grid.nvdb +0 -0
  299. warp/tests/assets/test_index_grid.nvdb +0 -0
  300. warp/tests/assets/test_int32_grid.nvdb +0 -0
  301. warp/tests/assets/test_vec_grid.nvdb +0 -0
  302. warp/tests/assets/torus.nvdb +0 -0
  303. warp/tests/assets/torus.usda +105 -0
  304. warp/tests/aux_test_class_kernel.py +34 -0
  305. warp/tests/aux_test_compile_consts_dummy.py +18 -0
  306. warp/tests/aux_test_conditional_unequal_types_kernels.py +29 -0
  307. warp/tests/aux_test_dependent.py +29 -0
  308. warp/tests/aux_test_grad_customs.py +29 -0
  309. warp/tests/aux_test_instancing_gc.py +26 -0
  310. warp/tests/aux_test_module_aot.py +7 -0
  311. warp/tests/aux_test_module_unload.py +23 -0
  312. warp/tests/aux_test_name_clash1.py +40 -0
  313. warp/tests/aux_test_name_clash2.py +40 -0
  314. warp/tests/aux_test_reference.py +9 -0
  315. warp/tests/aux_test_reference_reference.py +8 -0
  316. warp/tests/aux_test_square.py +16 -0
  317. warp/tests/aux_test_unresolved_func.py +22 -0
  318. warp/tests/aux_test_unresolved_symbol.py +22 -0
  319. warp/tests/cuda/__init__.py +0 -0
  320. warp/tests/cuda/test_async.py +676 -0
  321. warp/tests/cuda/test_conditional_captures.py +1147 -0
  322. warp/tests/cuda/test_ipc.py +124 -0
  323. warp/tests/cuda/test_mempool.py +233 -0
  324. warp/tests/cuda/test_multigpu.py +169 -0
  325. warp/tests/cuda/test_peer.py +139 -0
  326. warp/tests/cuda/test_pinned.py +84 -0
  327. warp/tests/cuda/test_streams.py +691 -0
  328. warp/tests/geometry/__init__.py +0 -0
  329. warp/tests/geometry/test_bvh.py +335 -0
  330. warp/tests/geometry/test_hash_grid.py +259 -0
  331. warp/tests/geometry/test_marching_cubes.py +294 -0
  332. warp/tests/geometry/test_mesh.py +318 -0
  333. warp/tests/geometry/test_mesh_query_aabb.py +392 -0
  334. warp/tests/geometry/test_mesh_query_point.py +935 -0
  335. warp/tests/geometry/test_mesh_query_ray.py +323 -0
  336. warp/tests/geometry/test_volume.py +1103 -0
  337. warp/tests/geometry/test_volume_write.py +346 -0
  338. warp/tests/interop/__init__.py +0 -0
  339. warp/tests/interop/test_dlpack.py +730 -0
  340. warp/tests/interop/test_jax.py +1673 -0
  341. warp/tests/interop/test_paddle.py +800 -0
  342. warp/tests/interop/test_torch.py +1001 -0
  343. warp/tests/run_coverage_serial.py +39 -0
  344. warp/tests/test_adam.py +162 -0
  345. warp/tests/test_arithmetic.py +1096 -0
  346. warp/tests/test_array.py +3756 -0
  347. warp/tests/test_array_reduce.py +156 -0
  348. warp/tests/test_assert.py +303 -0
  349. warp/tests/test_atomic.py +336 -0
  350. warp/tests/test_atomic_bitwise.py +209 -0
  351. warp/tests/test_atomic_cas.py +312 -0
  352. warp/tests/test_bool.py +220 -0
  353. warp/tests/test_builtins_resolution.py +732 -0
  354. warp/tests/test_closest_point_edge_edge.py +327 -0
  355. warp/tests/test_codegen.py +974 -0
  356. warp/tests/test_codegen_instancing.py +1495 -0
  357. warp/tests/test_compile_consts.py +215 -0
  358. warp/tests/test_conditional.py +298 -0
  359. warp/tests/test_context.py +35 -0
  360. warp/tests/test_copy.py +319 -0
  361. warp/tests/test_ctypes.py +618 -0
  362. warp/tests/test_dense.py +73 -0
  363. warp/tests/test_devices.py +127 -0
  364. warp/tests/test_enum.py +136 -0
  365. warp/tests/test_examples.py +424 -0
  366. warp/tests/test_fabricarray.py +998 -0
  367. warp/tests/test_fast_math.py +72 -0
  368. warp/tests/test_fem.py +2204 -0
  369. warp/tests/test_fixedarray.py +229 -0
  370. warp/tests/test_fp16.py +136 -0
  371. warp/tests/test_func.py +501 -0
  372. warp/tests/test_future_annotations.py +100 -0
  373. warp/tests/test_generics.py +656 -0
  374. warp/tests/test_grad.py +893 -0
  375. warp/tests/test_grad_customs.py +339 -0
  376. warp/tests/test_grad_debug.py +341 -0
  377. warp/tests/test_implicit_init.py +411 -0
  378. warp/tests/test_import.py +45 -0
  379. warp/tests/test_indexedarray.py +1140 -0
  380. warp/tests/test_intersect.py +103 -0
  381. warp/tests/test_iter.py +76 -0
  382. warp/tests/test_large.py +177 -0
  383. warp/tests/test_launch.py +411 -0
  384. warp/tests/test_lerp.py +151 -0
  385. warp/tests/test_linear_solvers.py +223 -0
  386. warp/tests/test_lvalue.py +427 -0
  387. warp/tests/test_map.py +526 -0
  388. warp/tests/test_mat.py +3515 -0
  389. warp/tests/test_mat_assign_copy.py +178 -0
  390. warp/tests/test_mat_constructors.py +573 -0
  391. warp/tests/test_mat_lite.py +122 -0
  392. warp/tests/test_mat_scalar_ops.py +2913 -0
  393. warp/tests/test_math.py +212 -0
  394. warp/tests/test_module_aot.py +287 -0
  395. warp/tests/test_module_hashing.py +258 -0
  396. warp/tests/test_modules_lite.py +70 -0
  397. warp/tests/test_noise.py +252 -0
  398. warp/tests/test_operators.py +299 -0
  399. warp/tests/test_options.py +129 -0
  400. warp/tests/test_overwrite.py +551 -0
  401. warp/tests/test_print.py +408 -0
  402. warp/tests/test_quat.py +2653 -0
  403. warp/tests/test_quat_assign_copy.py +145 -0
  404. warp/tests/test_rand.py +339 -0
  405. warp/tests/test_reload.py +303 -0
  406. warp/tests/test_rounding.py +157 -0
  407. warp/tests/test_runlength_encode.py +196 -0
  408. warp/tests/test_scalar_ops.py +133 -0
  409. warp/tests/test_smoothstep.py +108 -0
  410. warp/tests/test_snippet.py +318 -0
  411. warp/tests/test_sparse.py +845 -0
  412. warp/tests/test_spatial.py +2859 -0
  413. warp/tests/test_spatial_assign_copy.py +160 -0
  414. warp/tests/test_special_values.py +361 -0
  415. warp/tests/test_static.py +640 -0
  416. warp/tests/test_struct.py +901 -0
  417. warp/tests/test_tape.py +242 -0
  418. warp/tests/test_transient_module.py +93 -0
  419. warp/tests/test_triangle_closest_point.py +192 -0
  420. warp/tests/test_tuple.py +361 -0
  421. warp/tests/test_types.py +615 -0
  422. warp/tests/test_utils.py +594 -0
  423. warp/tests/test_vec.py +1408 -0
  424. warp/tests/test_vec_assign_copy.py +143 -0
  425. warp/tests/test_vec_constructors.py +325 -0
  426. warp/tests/test_vec_lite.py +80 -0
  427. warp/tests/test_vec_scalar_ops.py +2327 -0
  428. warp/tests/test_verify_fp.py +100 -0
  429. warp/tests/test_version.py +75 -0
  430. warp/tests/tile/__init__.py +0 -0
  431. warp/tests/tile/test_tile.py +1519 -0
  432. warp/tests/tile/test_tile_atomic_bitwise.py +403 -0
  433. warp/tests/tile/test_tile_cholesky.py +608 -0
  434. warp/tests/tile/test_tile_load.py +724 -0
  435. warp/tests/tile/test_tile_mathdx.py +156 -0
  436. warp/tests/tile/test_tile_matmul.py +179 -0
  437. warp/tests/tile/test_tile_mlp.py +400 -0
  438. warp/tests/tile/test_tile_reduce.py +950 -0
  439. warp/tests/tile/test_tile_shared_memory.py +376 -0
  440. warp/tests/tile/test_tile_sort.py +121 -0
  441. warp/tests/tile/test_tile_view.py +173 -0
  442. warp/tests/unittest_serial.py +47 -0
  443. warp/tests/unittest_suites.py +430 -0
  444. warp/tests/unittest_utils.py +469 -0
  445. warp/tests/walkthrough_debug.py +95 -0
  446. warp/torch.py +24 -0
  447. warp/types.py +51 -0
  448. warp/utils.py +31 -0
  449. warp_lang-1.10.0.dist-info/METADATA +459 -0
  450. warp_lang-1.10.0.dist-info/RECORD +468 -0
  451. warp_lang-1.10.0.dist-info/WHEEL +5 -0
  452. warp_lang-1.10.0.dist-info/licenses/LICENSE.md +176 -0
  453. warp_lang-1.10.0.dist-info/licenses/licenses/Gaia-LICENSE.txt +6 -0
  454. warp_lang-1.10.0.dist-info/licenses/licenses/appdirs-LICENSE.txt +22 -0
  455. warp_lang-1.10.0.dist-info/licenses/licenses/asset_pixel_jpg-LICENSE.txt +3 -0
  456. warp_lang-1.10.0.dist-info/licenses/licenses/cuda-LICENSE.txt +1582 -0
  457. warp_lang-1.10.0.dist-info/licenses/licenses/dlpack-LICENSE.txt +201 -0
  458. warp_lang-1.10.0.dist-info/licenses/licenses/fp16-LICENSE.txt +28 -0
  459. warp_lang-1.10.0.dist-info/licenses/licenses/libmathdx-LICENSE.txt +220 -0
  460. warp_lang-1.10.0.dist-info/licenses/licenses/llvm-LICENSE.txt +279 -0
  461. warp_lang-1.10.0.dist-info/licenses/licenses/moller-LICENSE.txt +16 -0
  462. warp_lang-1.10.0.dist-info/licenses/licenses/nanovdb-LICENSE.txt +2 -0
  463. warp_lang-1.10.0.dist-info/licenses/licenses/nvrtc-LICENSE.txt +1592 -0
  464. warp_lang-1.10.0.dist-info/licenses/licenses/svd-LICENSE.txt +23 -0
  465. warp_lang-1.10.0.dist-info/licenses/licenses/unittest_parallel-LICENSE.txt +21 -0
  466. warp_lang-1.10.0.dist-info/licenses/licenses/usd-LICENSE.txt +213 -0
  467. warp_lang-1.10.0.dist-info/licenses/licenses/windingnumber-LICENSE.txt +21 -0
  468. warp_lang-1.10.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,597 @@
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 Any, Optional
17
+
18
+ import warp as wp
19
+ from warp._src.fem.cache import (
20
+ TemporaryStore,
21
+ borrow_temporary,
22
+ borrow_temporary_like,
23
+ )
24
+ from warp._src.fem.types import OUTSIDE, Coords, ElementIndex, Sample
25
+
26
+ from .closest_point import project_on_seg_at_origin
27
+ from .element import Element
28
+ from .geometry import Geometry
29
+
30
+ _wp_module_name_ = "warp.fem.geometry.quadmesh"
31
+
32
+
33
+ @wp.struct
34
+ class QuadmeshCellArg:
35
+ quad_vertex_indices: wp.array2d(dtype=int)
36
+
37
+ quad_bvh: wp.uint64
38
+
39
+
40
+ @wp.struct
41
+ class QuadmeshSideArg:
42
+ cell_arg: QuadmeshCellArg
43
+ edge_vertex_indices: wp.array(dtype=wp.vec2i)
44
+ edge_quad_indices: wp.array(dtype=wp.vec2i)
45
+
46
+
47
+ class Quadmesh(Geometry):
48
+ """Quadrilateral mesh geometry"""
49
+
50
+ def __init__(
51
+ self,
52
+ quad_vertex_indices: wp.array,
53
+ positions: wp.array,
54
+ build_bvh: bool = False,
55
+ temporary_store: Optional[TemporaryStore] = None,
56
+ ):
57
+ """
58
+ Constructs a D-dimensional quadrilateral mesh.
59
+
60
+ Args:
61
+ quad_vertex_indices: warp array of shape (num_tris, 4) containing vertex indices for each quad, in counter-clockwise order
62
+ positions: warp array of shape (num_vertices, D) containing the position of each vertex
63
+ temporary_store: shared pool from which to allocate temporary arrays
64
+ """
65
+
66
+ self.quad_vertex_indices = quad_vertex_indices
67
+ self.positions = positions
68
+
69
+ self._edge_vertex_indices: wp.array = None
70
+ self._edge_quad_indices: wp.array = None
71
+ self._vertex_quad_offsets: wp.array = None
72
+ self._vertex_quad_indices: wp.array = None
73
+ self._build_topology(temporary_store)
74
+
75
+ # Flip edges so that normals point away from inner cell
76
+ wp.launch(
77
+ kernel=self._orient_edges,
78
+ device=positions.device,
79
+ dim=self.side_count(),
80
+ inputs=[self._edge_vertex_indices, self._edge_quad_indices, self.quad_vertex_indices, self.positions],
81
+ )
82
+
83
+ self._make_default_dependent_implementations()
84
+ self.cell_closest_point = self._make_cell_closest_point()
85
+ self.cell_coordinates = self._make_cell_coordinates()
86
+ self.side_coordinates = self._make_side_coordinates(assume_linear=True)
87
+
88
+ if build_bvh:
89
+ self.build_bvh(self.positions.device)
90
+
91
+ def cell_count(self):
92
+ return self.quad_vertex_indices.shape[0]
93
+
94
+ def vertex_count(self):
95
+ return self.positions.shape[0]
96
+
97
+ def side_count(self):
98
+ return self._edge_vertex_indices.shape[0]
99
+
100
+ def boundary_side_count(self):
101
+ return self._boundary_edge_indices.shape[0]
102
+
103
+ def reference_cell(self) -> Element:
104
+ return Element.SQUARE
105
+
106
+ def reference_side(self) -> Element:
107
+ return Element.LINE_SEGMENT
108
+
109
+ @property
110
+ def edge_quad_indices(self) -> wp.array:
111
+ return self._edge_quad_indices
112
+
113
+ @property
114
+ def edge_vertex_indices(self) -> wp.array:
115
+ return self._edge_vertex_indices
116
+
117
+ @wp.struct
118
+ class SideIndexArg:
119
+ boundary_edge_indices: wp.array(dtype=int)
120
+
121
+ def fill_cell_topo_arg(self, args: QuadmeshCellArg, device):
122
+ args.quad_vertex_indices = self.quad_vertex_indices.to(device)
123
+ args.quad_bvh = self.bvh_id(device)
124
+
125
+ def fill_side_topo_arg(self, args: QuadmeshSideArg, device):
126
+ self.fill_cell_topo_arg(args.cell_arg, device)
127
+ args.edge_vertex_indices = self._edge_vertex_indices.to(device)
128
+ args.edge_quad_indices = self._edge_quad_indices.to(device)
129
+
130
+ def fill_cell_arg(self, args: "Quadmesh.CellArg", device):
131
+ self.fill_cell_topo_arg(args.topology, device)
132
+ args.positions = self.positions.to(device)
133
+
134
+ def fill_side_arg(self, args: "Quadmesh.SideArg", device):
135
+ self.fill_side_topo_arg(args.topology, device)
136
+ args.positions = self.positions.to(device)
137
+
138
+ def fill_side_index_arg(self, args: "SideIndexArg", device):
139
+ args.boundary_edge_indices = self._boundary_edge_indices.to(device)
140
+
141
+ @wp.func
142
+ def _edge_to_quad_coords(
143
+ args: QuadmeshSideArg, side_index: ElementIndex, quad_index: ElementIndex, side_coords: Coords
144
+ ):
145
+ edge_vidx = args.edge_vertex_indices[side_index]
146
+ quad_vidx = args.cell_arg.quad_vertex_indices[quad_index]
147
+
148
+ vs = edge_vidx[0]
149
+ ve = edge_vidx[1]
150
+
151
+ s = side_coords[0]
152
+
153
+ if vs == quad_vidx[0]:
154
+ return wp.where(ve == quad_vidx[1], Coords(s, 0.0, 0.0), Coords(0.0, s, 0.0))
155
+ elif vs == quad_vidx[1]:
156
+ return wp.where(ve == quad_vidx[2], Coords(1.0, s, 0.0), Coords(1.0 - s, 0.0, 0.0))
157
+ elif vs == quad_vidx[2]:
158
+ return wp.where(ve == quad_vidx[3], Coords(1.0 - s, 1.0, 0.0), Coords(1.0, 1.0 - s, 0.0))
159
+
160
+ return wp.where(ve == quad_vidx[0], Coords(0.0, 1.0 - s, 0.0), Coords(s, 1.0, 0.0))
161
+
162
+ @wp.func
163
+ def _quad_to_edge_coords(
164
+ args: QuadmeshSideArg,
165
+ side_index: ElementIndex,
166
+ quad_index: ElementIndex,
167
+ quad_coords: Coords,
168
+ ):
169
+ edge_vidx = args.edge_vertex_indices[side_index]
170
+ quad_vidx = args.cell_arg.quad_vertex_indices[quad_index]
171
+
172
+ vs = edge_vidx[0]
173
+ ve = edge_vidx[1]
174
+
175
+ cx = quad_coords[0]
176
+ cy = quad_coords[1]
177
+
178
+ if vs == quad_vidx[0]:
179
+ oc = wp.where(ve == quad_vidx[1], cy, cx)
180
+ ec = wp.where(ve == quad_vidx[1], cx, cy)
181
+ elif vs == quad_vidx[1]:
182
+ oc = wp.where(ve == quad_vidx[2], 1.0 - cx, cy)
183
+ ec = wp.where(ve == quad_vidx[2], cy, 1.0 - cx)
184
+ elif vs == quad_vidx[2]:
185
+ oc = wp.where(ve == quad_vidx[3], 1.0 - cy, 1.0 - cx)
186
+ ec = wp.where(ve == quad_vidx[3], 1.0 - cx, 1.0 - cy)
187
+ else:
188
+ oc = wp.where(ve == quad_vidx[0], cx, 1.0 - cy)
189
+ ec = wp.where(ve == quad_vidx[0], 1.0 - cy, cx)
190
+ return wp.where(oc == 0.0, Coords(ec, 0.0, 0.0), Coords(OUTSIDE))
191
+
192
+ @wp.func
193
+ def boundary_side_index(args: SideIndexArg, boundary_side_index: int):
194
+ """Boundary side to side index"""
195
+
196
+ return args.boundary_edge_indices[boundary_side_index]
197
+
198
+ def _build_topology(self, temporary_store: TemporaryStore):
199
+ from warp._src.fem.utils import compress_node_indices, host_read_at_index, masked_indices
200
+ from warp._src.utils import array_scan
201
+
202
+ device = self.quad_vertex_indices.device
203
+
204
+ vertex_quad_offsets, vertex_quad_indices = compress_node_indices(
205
+ self.vertex_count(), self.quad_vertex_indices, temporary_store=temporary_store
206
+ )
207
+ self._vertex_quad_offsets = vertex_quad_offsets.detach()
208
+ self._vertex_quad_indices = vertex_quad_indices.detach()
209
+
210
+ vertex_start_edge_count = borrow_temporary(temporary_store, dtype=int, device=device, shape=self.vertex_count())
211
+ vertex_start_edge_count.zero_()
212
+ vertex_start_edge_offsets = borrow_temporary_like(vertex_start_edge_count, temporary_store=temporary_store)
213
+
214
+ vertex_edge_ends = borrow_temporary(temporary_store, dtype=int, device=device, shape=(4 * self.cell_count()))
215
+ vertex_edge_quads = borrow_temporary(
216
+ temporary_store, dtype=int, device=device, shape=(4 * self.cell_count(), 2)
217
+ )
218
+
219
+ # Count face edges starting at each vertex
220
+ wp.launch(
221
+ kernel=Quadmesh2D._count_starting_edges_kernel,
222
+ device=device,
223
+ dim=self.cell_count(),
224
+ inputs=[self.quad_vertex_indices, vertex_start_edge_count],
225
+ )
226
+
227
+ array_scan(in_array=vertex_start_edge_count, out_array=vertex_start_edge_offsets, inclusive=False)
228
+
229
+ # Count number of unique edges (deduplicate across faces)
230
+ vertex_unique_edge_count = vertex_start_edge_count
231
+ wp.launch(
232
+ kernel=Quadmesh2D._count_unique_starting_edges_kernel,
233
+ device=device,
234
+ dim=self.vertex_count(),
235
+ inputs=[
236
+ self._vertex_quad_offsets,
237
+ self._vertex_quad_indices,
238
+ self.quad_vertex_indices,
239
+ vertex_start_edge_offsets,
240
+ vertex_unique_edge_count,
241
+ vertex_edge_ends,
242
+ vertex_edge_quads,
243
+ ],
244
+ )
245
+
246
+ vertex_unique_edge_offsets = borrow_temporary_like(vertex_start_edge_offsets, temporary_store=temporary_store)
247
+ array_scan(in_array=vertex_start_edge_count, out_array=vertex_unique_edge_offsets, inclusive=False)
248
+
249
+ # Get back edge count to host
250
+ edge_count = int(
251
+ host_read_at_index(vertex_unique_edge_offsets, self.vertex_count() - 1, temporary_store=temporary_store)
252
+ )
253
+
254
+ self._edge_vertex_indices = wp.empty(shape=(edge_count,), dtype=wp.vec2i, device=device)
255
+ self._edge_quad_indices = wp.empty(shape=(edge_count,), dtype=wp.vec2i, device=device)
256
+
257
+ boundary_mask = borrow_temporary(temporary_store=temporary_store, shape=(edge_count,), dtype=int, device=device)
258
+
259
+ # Compress edge data
260
+ wp.launch(
261
+ kernel=Quadmesh2D._compress_edges_kernel,
262
+ device=device,
263
+ dim=self.vertex_count(),
264
+ inputs=[
265
+ vertex_start_edge_offsets,
266
+ vertex_unique_edge_offsets,
267
+ vertex_unique_edge_count,
268
+ vertex_edge_ends,
269
+ vertex_edge_quads,
270
+ self._edge_vertex_indices,
271
+ self._edge_quad_indices,
272
+ boundary_mask,
273
+ ],
274
+ )
275
+
276
+ vertex_start_edge_offsets.release()
277
+ vertex_unique_edge_offsets.release()
278
+ vertex_unique_edge_count.release()
279
+ vertex_edge_ends.release()
280
+ vertex_edge_quads.release()
281
+
282
+ boundary_edge_indices, _ = masked_indices(boundary_mask, temporary_store=temporary_store)
283
+ self._boundary_edge_indices = boundary_edge_indices.detach()
284
+
285
+ boundary_mask.release()
286
+
287
+ @wp.kernel
288
+ def _count_starting_edges_kernel(
289
+ quad_vertex_indices: wp.array2d(dtype=int), vertex_start_edge_count: wp.array(dtype=int)
290
+ ):
291
+ t = wp.tid()
292
+ for k in range(4):
293
+ v0 = quad_vertex_indices[t, k]
294
+ v1 = quad_vertex_indices[t, (k + 1) % 4]
295
+
296
+ if v0 < v1:
297
+ wp.atomic_add(vertex_start_edge_count, v0, 1)
298
+ else:
299
+ wp.atomic_add(vertex_start_edge_count, v1, 1)
300
+
301
+ @wp.func
302
+ def _find(
303
+ needle: int,
304
+ values: wp.array(dtype=int),
305
+ beg: int,
306
+ end: int,
307
+ ):
308
+ for i in range(beg, end):
309
+ if values[i] == needle:
310
+ return i
311
+
312
+ return -1
313
+
314
+ @wp.kernel
315
+ def _count_unique_starting_edges_kernel(
316
+ vertex_quad_offsets: wp.array(dtype=int),
317
+ vertex_quad_indices: wp.array(dtype=int),
318
+ quad_vertex_indices: wp.array2d(dtype=int),
319
+ vertex_start_edge_offsets: wp.array(dtype=int),
320
+ vertex_start_edge_count: wp.array(dtype=int),
321
+ edge_ends: wp.array(dtype=int),
322
+ edge_quads: wp.array2d(dtype=int),
323
+ ):
324
+ v = wp.tid()
325
+
326
+ edge_beg = vertex_start_edge_offsets[v]
327
+
328
+ quad_beg = vertex_quad_offsets[v]
329
+ quad_end = vertex_quad_offsets[v + 1]
330
+
331
+ edge_cur = edge_beg
332
+
333
+ for quad in range(quad_beg, quad_end):
334
+ q = vertex_quad_indices[quad]
335
+
336
+ for k in range(4):
337
+ v0 = quad_vertex_indices[q, k]
338
+ v1 = quad_vertex_indices[q, (k + 1) % 4]
339
+
340
+ if v == wp.min(v0, v1):
341
+ other_v = wp.max(v0, v1)
342
+
343
+ # Check if other_v has been seen
344
+ seen_idx = Quadmesh2D._find(other_v, edge_ends, edge_beg, edge_cur)
345
+
346
+ if seen_idx == -1:
347
+ edge_ends[edge_cur] = other_v
348
+ edge_quads[edge_cur, 0] = q
349
+ edge_quads[edge_cur, 1] = q
350
+ edge_cur += 1
351
+ else:
352
+ edge_quads[seen_idx, 1] = q
353
+
354
+ vertex_start_edge_count[v] = edge_cur - edge_beg
355
+
356
+ @wp.kernel
357
+ def _compress_edges_kernel(
358
+ vertex_start_edge_offsets: wp.array(dtype=int),
359
+ vertex_unique_edge_offsets: wp.array(dtype=int),
360
+ vertex_unique_edge_count: wp.array(dtype=int),
361
+ uncompressed_edge_ends: wp.array(dtype=int),
362
+ uncompressed_edge_quads: wp.array2d(dtype=int),
363
+ edge_vertex_indices: wp.array(dtype=wp.vec2i),
364
+ edge_quad_indices: wp.array(dtype=wp.vec2i),
365
+ boundary_mask: wp.array(dtype=int),
366
+ ):
367
+ v = wp.tid()
368
+
369
+ start_beg = vertex_start_edge_offsets[v]
370
+ unique_beg = vertex_unique_edge_offsets[v]
371
+ unique_count = vertex_unique_edge_count[v]
372
+
373
+ for e in range(unique_count):
374
+ src_index = start_beg + e
375
+ edge_index = unique_beg + e
376
+
377
+ edge_vertex_indices[edge_index] = wp.vec2i(v, uncompressed_edge_ends[src_index])
378
+
379
+ q0 = uncompressed_edge_quads[src_index, 0]
380
+ q1 = uncompressed_edge_quads[src_index, 1]
381
+ edge_quad_indices[edge_index] = wp.vec2i(q0, q1)
382
+ if q0 == q1:
383
+ boundary_mask[edge_index] = 1
384
+ else:
385
+ boundary_mask[edge_index] = 0
386
+
387
+ @wp.func
388
+ def cell_position(args: Any, s: Sample):
389
+ quad_idx = args.topology.quad_vertex_indices[s.element_index]
390
+
391
+ w_p = s.element_coords
392
+ w_m = Coords(1.0) - s.element_coords
393
+
394
+ # 0 : m m
395
+ # 1 : p m
396
+ # 2 : p p
397
+ # 3 : m p
398
+
399
+ return (
400
+ w_m[0] * w_m[1] * args.positions[quad_idx[0]]
401
+ + w_p[0] * w_m[1] * args.positions[quad_idx[1]]
402
+ + w_p[0] * w_p[1] * args.positions[quad_idx[2]]
403
+ + w_m[0] * w_p[1] * args.positions[quad_idx[3]]
404
+ )
405
+
406
+ @wp.func
407
+ def cell_deformation_gradient(cell_arg: Any, s: Sample):
408
+ """Deformation gradient at `coords`"""
409
+ quad_idx = cell_arg.topology.quad_vertex_indices[s.element_index]
410
+
411
+ w_p = s.element_coords
412
+ w_m = Coords(1.0) - s.element_coords
413
+
414
+ return (
415
+ wp.outer(cell_arg.positions[quad_idx[0]], wp.vec2(-w_m[1], -w_m[0]))
416
+ + wp.outer(cell_arg.positions[quad_idx[1]], wp.vec2(w_m[1], -w_p[0]))
417
+ + wp.outer(cell_arg.positions[quad_idx[2]], wp.vec2(w_p[1], w_p[0]))
418
+ + wp.outer(cell_arg.positions[quad_idx[3]], wp.vec2(-w_p[1], w_m[0]))
419
+ )
420
+
421
+ @wp.func
422
+ def side_position(args: Any, s: Sample):
423
+ edge_idx = args.topology.edge_vertex_indices[s.element_index]
424
+ return (1.0 - s.element_coords[0]) * args.positions[edge_idx[0]] + s.element_coords[0] * args.positions[
425
+ edge_idx[1]
426
+ ]
427
+
428
+ @wp.func
429
+ def side_deformation_gradient(args: Any, s: Sample):
430
+ edge_idx = args.topology.edge_vertex_indices[s.element_index]
431
+ v0 = args.positions[edge_idx[0]]
432
+ v1 = args.positions[edge_idx[1]]
433
+ return v1 - v0
434
+
435
+ @wp.func
436
+ def side_closest_point(args: Any, side_index: ElementIndex, pos: Any):
437
+ edge_idx = args.topology.edge_vertex_indices[side_index]
438
+ p0 = args.positions[edge_idx[0]]
439
+
440
+ q = pos - p0
441
+ e = args.positions[edge_idx[1]] - p0
442
+
443
+ dist, t = project_on_seg_at_origin(q, e, wp.length_sq(e))
444
+ return Coords(t, 0.0, 0.0), dist
445
+
446
+ @wp.func
447
+ def side_inner_cell_index(arg: Any, side_index: ElementIndex):
448
+ return arg.topology.edge_quad_indices[side_index][0]
449
+
450
+ @wp.func
451
+ def side_outer_cell_index(arg: Any, side_index: ElementIndex):
452
+ return arg.topology.edge_quad_indices[side_index][1]
453
+
454
+ @wp.func
455
+ def side_inner_cell_coords(args: Any, side_index: ElementIndex, side_coords: Coords):
456
+ inner_cell_index = Quadmesh3D.side_inner_cell_index(args, side_index)
457
+ return Quadmesh._edge_to_quad_coords(args.topology, side_index, inner_cell_index, side_coords)
458
+
459
+ @wp.func
460
+ def side_outer_cell_coords(args: Any, side_index: ElementIndex, side_coords: Coords):
461
+ outer_cell_index = Quadmesh3D.side_outer_cell_index(args, side_index)
462
+ return Quadmesh._edge_to_quad_coords(args.topology, side_index, outer_cell_index, side_coords)
463
+
464
+ @wp.func
465
+ def side_from_cell_coords(
466
+ args: Any,
467
+ side_index: ElementIndex,
468
+ quad_index: ElementIndex,
469
+ quad_coords: Coords,
470
+ ):
471
+ return Quadmesh._quad_to_edge_coords(args.topology, side_index, quad_index, quad_coords)
472
+
473
+ @wp.func
474
+ def cell_bvh_id(cell_arg: Any):
475
+ return cell_arg.topology.quad_bvh
476
+
477
+ @wp.func
478
+ def cell_bounds(cell_arg: Any, cell_index: ElementIndex):
479
+ vidx = cell_arg.topology.quad_vertex_indices[cell_index]
480
+ p0 = cell_arg.positions[vidx[0]]
481
+ p1 = cell_arg.positions[vidx[1]]
482
+ p2 = cell_arg.positions[vidx[2]]
483
+ p3 = cell_arg.positions[vidx[3]]
484
+
485
+ return wp.min(wp.min(p0, p1), wp.min(p2, p3)), wp.max(wp.max(p0, p1), wp.max(p2, p3))
486
+
487
+
488
+ @wp.struct
489
+ class Quadmesh2DCellArg:
490
+ topology: QuadmeshCellArg
491
+ positions: wp.array(dtype=wp.vec2)
492
+
493
+
494
+ @wp.struct
495
+ class Quadmesh2DSideArg:
496
+ topology: QuadmeshSideArg
497
+ positions: wp.array(dtype=wp.vec2)
498
+
499
+
500
+ class Quadmesh2D(Quadmesh):
501
+ """Two-dimensional quadrilateral mesh"""
502
+
503
+ dimension = 2
504
+ CellArg = Quadmesh2DCellArg
505
+ SideArg = Quadmesh2DSideArg
506
+
507
+ @wp.func
508
+ def side_to_cell_arg(side_arg: SideArg):
509
+ return Quadmesh2DCellArg(side_arg.topology.cell_arg, side_arg.positions)
510
+
511
+ @wp.kernel
512
+ def _orient_edges(
513
+ edge_vertex_indices: wp.array(dtype=wp.vec2i),
514
+ edge_quad_indices: wp.array(dtype=wp.vec2i),
515
+ quad_vertex_indices: wp.array2d(dtype=int),
516
+ positions: wp.array(dtype=wp.vec2),
517
+ ):
518
+ e = wp.tid()
519
+
520
+ tri = edge_quad_indices[e][0]
521
+
522
+ quad_vidx = quad_vertex_indices[tri]
523
+ edge_vidx = edge_vertex_indices[e]
524
+
525
+ quad_centroid = (
526
+ positions[quad_vidx[0]] + positions[quad_vidx[1]] + positions[quad_vidx[2]] + positions[quad_vidx[3]]
527
+ ) / 4.0
528
+
529
+ v0 = positions[edge_vidx[0]]
530
+ v1 = positions[edge_vidx[1]]
531
+
532
+ edge_center = 0.5 * (v1 + v0)
533
+ edge_vec = v1 - v0
534
+ edge_normal = Geometry._element_normal(edge_vec)
535
+
536
+ # if edge normal points toward first triangle centroid, flip indices
537
+ if wp.dot(quad_centroid - edge_center, edge_normal) > 0.0:
538
+ edge_vertex_indices[e] = wp.vec2i(edge_vidx[1], edge_vidx[0])
539
+
540
+
541
+ @wp.struct
542
+ class Quadmesh3DCellArg:
543
+ topology: QuadmeshCellArg
544
+ positions: wp.array(dtype=wp.vec3)
545
+
546
+
547
+ @wp.struct
548
+ class Quadmesh3DSideArg:
549
+ topology: QuadmeshSideArg
550
+ positions: wp.array(dtype=wp.vec3)
551
+
552
+
553
+ class Quadmesh3D(Quadmesh):
554
+ """Three-dimensional quadrilateral mesh"""
555
+
556
+ dimension = 3
557
+ CellArg = Quadmesh3DCellArg
558
+ SideArg = Quadmesh3DSideArg
559
+
560
+ @wp.func
561
+ def side_to_cell_arg(side_arg: SideArg):
562
+ return Quadmesh3DCellArg(side_arg.topology.cell_arg, side_arg.positions)
563
+
564
+ @wp.kernel
565
+ def _orient_edges(
566
+ edge_vertex_indices: wp.array(dtype=wp.vec2i),
567
+ edge_quad_indices: wp.array(dtype=wp.vec2i),
568
+ quad_vertex_indices: wp.array2d(dtype=int),
569
+ positions: wp.array(dtype=wp.vec3),
570
+ ):
571
+ e = wp.tid()
572
+
573
+ tri = edge_quad_indices[e][0]
574
+
575
+ quad_vidx = quad_vertex_indices[tri]
576
+ edge_vidx = edge_vertex_indices[e]
577
+
578
+ p0 = positions[quad_vidx[0]]
579
+ p1 = positions[quad_vidx[1]]
580
+ p2 = positions[quad_vidx[2]]
581
+ p3 = positions[quad_vidx[3]]
582
+
583
+ quad_centroid = (
584
+ positions[quad_vidx[0]] + positions[quad_vidx[1]] + positions[quad_vidx[2]] + positions[quad_vidx[3]]
585
+ ) / 4.0
586
+ quad_normal = wp.cross(p2 - p0, p3 - p1)
587
+
588
+ v0 = positions[edge_vidx[0]]
589
+ v1 = positions[edge_vidx[1]]
590
+
591
+ edge_center = 0.5 * (v1 + v0)
592
+ edge_vec = v1 - v0
593
+ edge_normal = wp.cross(edge_vec, quad_normal)
594
+
595
+ # if edge normal points toward first triangle centroid, flip indices
596
+ if wp.dot(quad_centroid - edge_center, edge_normal) > 0.0:
597
+ edge_vertex_indices[e] = wp.vec2i(edge_vidx[1], edge_vidx[0])