warp-lang 1.7.0__py3-none-manylinux_2_28_x86_64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

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,663 @@
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 warp as wp
19
+ from warp.fem.cache import (
20
+ TemporaryStore,
21
+ borrow_temporary,
22
+ borrow_temporary_like,
23
+ cached_arg_value,
24
+ )
25
+ from warp.fem.types import OUTSIDE, Coords, ElementIndex, Sample
26
+
27
+ from .element import LinearEdge, Square
28
+ from .geometry import Geometry
29
+
30
+
31
+ @wp.struct
32
+ class QuadmeshCellArg:
33
+ quad_vertex_indices: wp.array2d(dtype=int)
34
+
35
+ # for neighbor cell lookup
36
+ vertex_quad_offsets: wp.array(dtype=int)
37
+ vertex_quad_indices: wp.array(dtype=int)
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, quad_vertex_indices: wp.array, positions: wp.array, temporary_store: Optional[TemporaryStore] = None
52
+ ):
53
+ """
54
+ Constructs a D-dimensional quadrilateral mesh.
55
+
56
+ Args:
57
+ quad_vertex_indices: warp array of shape (num_tris, 4) containing vertex indices for each quad, in counter-clockwise order
58
+ positions: warp array of shape (num_vertices, D) containing the position of each vertex
59
+ temporary_store: shared pool from which to allocate temporary arrays
60
+ """
61
+
62
+ self.quad_vertex_indices = quad_vertex_indices
63
+ self.positions = positions
64
+
65
+ self._edge_vertex_indices: wp.array = None
66
+ self._edge_quad_indices: wp.array = None
67
+ self._vertex_quad_offsets: wp.array = None
68
+ self._vertex_quad_indices: wp.array = None
69
+ self._build_topology(temporary_store)
70
+
71
+ # Flip edges so that normals point away from inner cell
72
+ wp.launch(
73
+ kernel=self._orient_edges,
74
+ device=positions.device,
75
+ dim=self.side_count(),
76
+ inputs=[self._edge_vertex_indices, self._edge_quad_indices, self.quad_vertex_indices, self.positions],
77
+ )
78
+
79
+ self._make_default_dependent_implementations()
80
+
81
+ def cell_count(self):
82
+ return self.quad_vertex_indices.shape[0]
83
+
84
+ def vertex_count(self):
85
+ return self.positions.shape[0]
86
+
87
+ def side_count(self):
88
+ return self._edge_vertex_indices.shape[0]
89
+
90
+ def boundary_side_count(self):
91
+ return self._boundary_edge_indices.shape[0]
92
+
93
+ def reference_cell(self) -> Square:
94
+ return Square()
95
+
96
+ def reference_side(self) -> LinearEdge:
97
+ return LinearEdge()
98
+
99
+ @property
100
+ def edge_quad_indices(self) -> wp.array:
101
+ return self._edge_quad_indices
102
+
103
+ @property
104
+ def edge_vertex_indices(self) -> wp.array:
105
+ return self._edge_vertex_indices
106
+
107
+ @wp.struct
108
+ class SideIndexArg:
109
+ boundary_edge_indices: wp.array(dtype=int)
110
+
111
+ @cached_arg_value
112
+ def _cell_topo_arg_value(self, device):
113
+ args = QuadmeshCellArg()
114
+
115
+ args.quad_vertex_indices = self.quad_vertex_indices.to(device)
116
+ args.vertex_quad_offsets = self._vertex_quad_offsets.to(device)
117
+ args.vertex_quad_indices = self._vertex_quad_indices.to(device)
118
+
119
+ return args
120
+
121
+ @cached_arg_value
122
+ def _side_topo_arg_value(self, device):
123
+ args = QuadmeshSideArg()
124
+
125
+ args.cell_arg = self._cell_topo_arg_value(device)
126
+ args.edge_vertex_indices = self._edge_vertex_indices.to(device)
127
+ args.edge_quad_indices = self._edge_quad_indices.to(device)
128
+
129
+ return args
130
+
131
+ def cell_arg_value(self, device):
132
+ args = self.CellArg()
133
+
134
+ args.topology = self._cell_topo_arg_value(device)
135
+ args.positions = self.positions.to(device)
136
+
137
+ return args
138
+
139
+ def side_arg_value(self, device):
140
+ args = self.SideArg()
141
+
142
+ args.topology = self._side_topo_arg_value(device)
143
+ args.positions = self.positions.to(device)
144
+
145
+ return args
146
+
147
+ @cached_arg_value
148
+ def side_index_arg_value(self, device) -> SideIndexArg:
149
+ args = self.SideIndexArg()
150
+
151
+ args.boundary_edge_indices = self._boundary_edge_indices.to(device)
152
+
153
+ return args
154
+
155
+ @wp.func
156
+ def _edge_to_quad_coords(
157
+ args: QuadmeshSideArg, side_index: ElementIndex, quad_index: ElementIndex, side_coords: Coords
158
+ ):
159
+ edge_vidx = args.edge_vertex_indices[side_index]
160
+ quad_vidx = args.cell_arg.quad_vertex_indices[quad_index]
161
+
162
+ vs = edge_vidx[0]
163
+ ve = edge_vidx[1]
164
+
165
+ s = side_coords[0]
166
+
167
+ if vs == quad_vidx[0]:
168
+ return wp.where(ve == quad_vidx[1], Coords(s, 0.0, 0.0), Coords(0.0, s, 0.0))
169
+ elif vs == quad_vidx[1]:
170
+ return wp.where(ve == quad_vidx[2], Coords(1.0, s, 0.0), Coords(1.0 - s, 0.0, 0.0))
171
+ elif vs == quad_vidx[2]:
172
+ return wp.where(ve == quad_vidx[3], Coords(1.0 - s, 1.0, 0.0), Coords(1.0, 1.0 - s, 0.0))
173
+
174
+ return wp.where(ve == quad_vidx[0], Coords(0.0, 1.0 - s, 0.0), Coords(s, 1.0, 0.0))
175
+
176
+ @wp.func
177
+ def _quad_to_edge_coords(
178
+ args: QuadmeshSideArg,
179
+ side_index: ElementIndex,
180
+ quad_index: ElementIndex,
181
+ quad_coords: Coords,
182
+ ):
183
+ edge_vidx = args.edge_vertex_indices[side_index]
184
+ quad_vidx = args.cell_arg.quad_vertex_indices[quad_index]
185
+
186
+ vs = edge_vidx[0]
187
+ ve = edge_vidx[1]
188
+
189
+ cx = quad_coords[0]
190
+ cy = quad_coords[1]
191
+
192
+ if vs == quad_vidx[0]:
193
+ oc = wp.where(ve == quad_vidx[1], cy, cx)
194
+ ec = wp.where(ve == quad_vidx[1], cx, cy)
195
+ elif vs == quad_vidx[1]:
196
+ oc = wp.where(ve == quad_vidx[2], 1.0 - cx, cy)
197
+ ec = wp.where(ve == quad_vidx[2], cy, 1.0 - cx)
198
+ elif vs == quad_vidx[2]:
199
+ oc = wp.where(ve == quad_vidx[3], 1.0 - cy, 1.0 - cx)
200
+ ec = wp.where(ve == quad_vidx[3], 1.0 - cx, 1.0 - cy)
201
+ else:
202
+ oc = wp.where(ve == quad_vidx[0], cx, 1.0 - cy)
203
+ ec = wp.where(ve == quad_vidx[0], 1.0 - cy, cx)
204
+ return wp.where(oc == 0.0, Coords(ec, 0.0, 0.0), Coords(OUTSIDE))
205
+
206
+ @wp.func
207
+ def boundary_side_index(args: SideIndexArg, boundary_side_index: int):
208
+ """Boundary side to side index"""
209
+
210
+ return args.boundary_edge_indices[boundary_side_index]
211
+
212
+ def _build_topology(self, temporary_store: TemporaryStore):
213
+ from warp.fem.utils import compress_node_indices, host_read_at_index, masked_indices
214
+ from warp.utils import array_scan
215
+
216
+ device = self.quad_vertex_indices.device
217
+
218
+ vertex_quad_offsets, vertex_quad_indices = compress_node_indices(
219
+ self.vertex_count(), self.quad_vertex_indices, temporary_store=temporary_store
220
+ )
221
+ self._vertex_quad_offsets = vertex_quad_offsets.detach()
222
+ self._vertex_quad_indices = vertex_quad_indices.detach()
223
+
224
+ vertex_start_edge_count = borrow_temporary(temporary_store, dtype=int, device=device, shape=self.vertex_count())
225
+ vertex_start_edge_count.array.zero_()
226
+ vertex_start_edge_offsets = borrow_temporary_like(vertex_start_edge_count, temporary_store=temporary_store)
227
+
228
+ vertex_edge_ends = borrow_temporary(temporary_store, dtype=int, device=device, shape=(4 * self.cell_count()))
229
+ vertex_edge_quads = borrow_temporary(
230
+ temporary_store, dtype=int, device=device, shape=(4 * self.cell_count(), 2)
231
+ )
232
+
233
+ # Count face edges starting at each vertex
234
+ wp.launch(
235
+ kernel=Quadmesh2D._count_starting_edges_kernel,
236
+ device=device,
237
+ dim=self.cell_count(),
238
+ inputs=[self.quad_vertex_indices, vertex_start_edge_count.array],
239
+ )
240
+
241
+ array_scan(in_array=vertex_start_edge_count.array, out_array=vertex_start_edge_offsets.array, inclusive=False)
242
+
243
+ # Count number of unique edges (deduplicate across faces)
244
+ vertex_unique_edge_count = vertex_start_edge_count
245
+ wp.launch(
246
+ kernel=Quadmesh2D._count_unique_starting_edges_kernel,
247
+ device=device,
248
+ dim=self.vertex_count(),
249
+ inputs=[
250
+ self._vertex_quad_offsets,
251
+ self._vertex_quad_indices,
252
+ self.quad_vertex_indices,
253
+ vertex_start_edge_offsets.array,
254
+ vertex_unique_edge_count.array,
255
+ vertex_edge_ends.array,
256
+ vertex_edge_quads.array,
257
+ ],
258
+ )
259
+
260
+ vertex_unique_edge_offsets = borrow_temporary_like(vertex_start_edge_offsets, temporary_store=temporary_store)
261
+ array_scan(in_array=vertex_start_edge_count.array, out_array=vertex_unique_edge_offsets.array, inclusive=False)
262
+
263
+ # Get back edge count to host
264
+ edge_count = int(
265
+ host_read_at_index(
266
+ vertex_unique_edge_offsets.array, self.vertex_count() - 1, temporary_store=temporary_store
267
+ )
268
+ )
269
+
270
+ self._edge_vertex_indices = wp.empty(shape=(edge_count,), dtype=wp.vec2i, device=device)
271
+ self._edge_quad_indices = wp.empty(shape=(edge_count,), dtype=wp.vec2i, device=device)
272
+
273
+ boundary_mask = borrow_temporary(temporary_store=temporary_store, shape=(edge_count,), dtype=int, device=device)
274
+
275
+ # Compress edge data
276
+ wp.launch(
277
+ kernel=Quadmesh2D._compress_edges_kernel,
278
+ device=device,
279
+ dim=self.vertex_count(),
280
+ inputs=[
281
+ vertex_start_edge_offsets.array,
282
+ vertex_unique_edge_offsets.array,
283
+ vertex_unique_edge_count.array,
284
+ vertex_edge_ends.array,
285
+ vertex_edge_quads.array,
286
+ self._edge_vertex_indices,
287
+ self._edge_quad_indices,
288
+ boundary_mask.array,
289
+ ],
290
+ )
291
+
292
+ vertex_start_edge_offsets.release()
293
+ vertex_unique_edge_offsets.release()
294
+ vertex_unique_edge_count.release()
295
+ vertex_edge_ends.release()
296
+ vertex_edge_quads.release()
297
+
298
+ boundary_edge_indices, _ = masked_indices(boundary_mask.array, temporary_store=temporary_store)
299
+ self._boundary_edge_indices = boundary_edge_indices.detach()
300
+
301
+ boundary_mask.release()
302
+
303
+ @wp.kernel
304
+ def _count_starting_edges_kernel(
305
+ quad_vertex_indices: wp.array2d(dtype=int), vertex_start_edge_count: wp.array(dtype=int)
306
+ ):
307
+ t = wp.tid()
308
+ for k in range(4):
309
+ v0 = quad_vertex_indices[t, k]
310
+ v1 = quad_vertex_indices[t, (k + 1) % 4]
311
+
312
+ if v0 < v1:
313
+ wp.atomic_add(vertex_start_edge_count, v0, 1)
314
+ else:
315
+ wp.atomic_add(vertex_start_edge_count, v1, 1)
316
+
317
+ @wp.func
318
+ def _find(
319
+ needle: int,
320
+ values: wp.array(dtype=int),
321
+ beg: int,
322
+ end: int,
323
+ ):
324
+ for i in range(beg, end):
325
+ if values[i] == needle:
326
+ return i
327
+
328
+ return -1
329
+
330
+ @wp.kernel
331
+ def _count_unique_starting_edges_kernel(
332
+ vertex_quad_offsets: wp.array(dtype=int),
333
+ vertex_quad_indices: wp.array(dtype=int),
334
+ quad_vertex_indices: wp.array2d(dtype=int),
335
+ vertex_start_edge_offsets: wp.array(dtype=int),
336
+ vertex_start_edge_count: wp.array(dtype=int),
337
+ edge_ends: wp.array(dtype=int),
338
+ edge_quads: wp.array2d(dtype=int),
339
+ ):
340
+ v = wp.tid()
341
+
342
+ edge_beg = vertex_start_edge_offsets[v]
343
+
344
+ quad_beg = vertex_quad_offsets[v]
345
+ quad_end = vertex_quad_offsets[v + 1]
346
+
347
+ edge_cur = edge_beg
348
+
349
+ for quad in range(quad_beg, quad_end):
350
+ q = vertex_quad_indices[quad]
351
+
352
+ for k in range(4):
353
+ v0 = quad_vertex_indices[q, k]
354
+ v1 = quad_vertex_indices[q, (k + 1) % 4]
355
+
356
+ if v == wp.min(v0, v1):
357
+ other_v = wp.max(v0, v1)
358
+
359
+ # Check if other_v has been seen
360
+ seen_idx = Quadmesh2D._find(other_v, edge_ends, edge_beg, edge_cur)
361
+
362
+ if seen_idx == -1:
363
+ edge_ends[edge_cur] = other_v
364
+ edge_quads[edge_cur, 0] = q
365
+ edge_quads[edge_cur, 1] = q
366
+ edge_cur += 1
367
+ else:
368
+ edge_quads[seen_idx, 1] = q
369
+
370
+ vertex_start_edge_count[v] = edge_cur - edge_beg
371
+
372
+ @wp.kernel
373
+ def _compress_edges_kernel(
374
+ vertex_start_edge_offsets: wp.array(dtype=int),
375
+ vertex_unique_edge_offsets: wp.array(dtype=int),
376
+ vertex_unique_edge_count: wp.array(dtype=int),
377
+ uncompressed_edge_ends: wp.array(dtype=int),
378
+ uncompressed_edge_quads: wp.array2d(dtype=int),
379
+ edge_vertex_indices: wp.array(dtype=wp.vec2i),
380
+ edge_quad_indices: wp.array(dtype=wp.vec2i),
381
+ boundary_mask: wp.array(dtype=int),
382
+ ):
383
+ v = wp.tid()
384
+
385
+ start_beg = vertex_start_edge_offsets[v]
386
+ unique_beg = vertex_unique_edge_offsets[v]
387
+ unique_count = vertex_unique_edge_count[v]
388
+
389
+ for e in range(unique_count):
390
+ src_index = start_beg + e
391
+ edge_index = unique_beg + e
392
+
393
+ edge_vertex_indices[edge_index] = wp.vec2i(v, uncompressed_edge_ends[src_index])
394
+
395
+ q0 = uncompressed_edge_quads[src_index, 0]
396
+ q1 = uncompressed_edge_quads[src_index, 1]
397
+ edge_quad_indices[edge_index] = wp.vec2i(q0, q1)
398
+ if q0 == q1:
399
+ boundary_mask[edge_index] = 1
400
+ else:
401
+ boundary_mask[edge_index] = 0
402
+
403
+
404
+ @wp.struct
405
+ class Quadmesh2DCellArg:
406
+ topology: QuadmeshCellArg
407
+ positions: wp.array(dtype=wp.vec2)
408
+
409
+
410
+ @wp.struct
411
+ class Quadmesh2DSideArg:
412
+ topology: QuadmeshSideArg
413
+ positions: wp.array(dtype=wp.vec2)
414
+
415
+
416
+ class Quadmesh2D(Quadmesh):
417
+ """Two-dimensional quadrilateral mesh"""
418
+
419
+ dimension = 2
420
+ CellArg = Quadmesh2DCellArg
421
+ SideArg = Quadmesh2DSideArg
422
+
423
+ @wp.func
424
+ def cell_position(args: CellArg, s: Sample):
425
+ quad_idx = args.topology.quad_vertex_indices[s.element_index]
426
+
427
+ w_p = s.element_coords
428
+ w_m = Coords(1.0) - s.element_coords
429
+
430
+ # 0 : m m
431
+ # 1 : p m
432
+ # 2 : p p
433
+ # 3 : m p
434
+
435
+ return (
436
+ w_m[0] * w_m[1] * args.positions[quad_idx[0]]
437
+ + w_p[0] * w_m[1] * args.positions[quad_idx[1]]
438
+ + w_p[0] * w_p[1] * args.positions[quad_idx[2]]
439
+ + w_m[0] * w_p[1] * args.positions[quad_idx[3]]
440
+ )
441
+
442
+ @wp.func
443
+ def cell_deformation_gradient(cell_arg: CellArg, s: Sample):
444
+ """Deformation gradient at `coords`"""
445
+ quad_idx = cell_arg.topology.quad_vertex_indices[s.element_index]
446
+
447
+ w_p = s.element_coords
448
+ w_m = Coords(1.0) - s.element_coords
449
+
450
+ return (
451
+ wp.outer(cell_arg.positions[quad_idx[0]], wp.vec2(-w_m[1], -w_m[0]))
452
+ + wp.outer(cell_arg.positions[quad_idx[1]], wp.vec2(w_m[1], -w_p[0]))
453
+ + wp.outer(cell_arg.positions[quad_idx[2]], wp.vec2(w_p[1], w_p[0]))
454
+ + wp.outer(cell_arg.positions[quad_idx[3]], wp.vec2(-w_p[1], w_m[0]))
455
+ )
456
+
457
+ @wp.func
458
+ def side_position(args: SideArg, s: Sample):
459
+ edge_idx = args.topology.edge_vertex_indices[s.element_index]
460
+ return (1.0 - s.element_coords[0]) * args.positions[edge_idx[0]] + s.element_coords[0] * args.positions[
461
+ edge_idx[1]
462
+ ]
463
+
464
+ @wp.func
465
+ def side_deformation_gradient(args: SideArg, s: Sample):
466
+ edge_idx = args.topology.edge_vertex_indices[s.element_index]
467
+ v0 = args.positions[edge_idx[0]]
468
+ v1 = args.positions[edge_idx[1]]
469
+ return v1 - v0
470
+
471
+ @wp.func
472
+ def side_inner_cell_index(arg: SideArg, side_index: ElementIndex):
473
+ return arg.topology.edge_quad_indices[side_index][0]
474
+
475
+ @wp.func
476
+ def side_outer_cell_index(arg: SideArg, side_index: ElementIndex):
477
+ return arg.topology.edge_quad_indices[side_index][1]
478
+
479
+ @wp.func
480
+ def side_inner_cell_coords(args: SideArg, side_index: ElementIndex, side_coords: Coords):
481
+ inner_cell_index = Quadmesh2D.side_inner_cell_index(args, side_index)
482
+ return Quadmesh._edge_to_quad_coords(args.topology, side_index, inner_cell_index, side_coords)
483
+
484
+ @wp.func
485
+ def side_outer_cell_coords(args: SideArg, side_index: ElementIndex, side_coords: Coords):
486
+ outer_cell_index = Quadmesh2D.side_outer_cell_index(args, side_index)
487
+ return Quadmesh._edge_to_quad_coords(args.topology, side_index, outer_cell_index, side_coords)
488
+
489
+ @wp.func
490
+ def side_from_cell_coords(
491
+ args: SideArg,
492
+ side_index: ElementIndex,
493
+ quad_index: ElementIndex,
494
+ quad_coords: Coords,
495
+ ):
496
+ return Quadmesh._quad_to_edge_coords(args.topology, side_index, quad_index, quad_coords)
497
+
498
+ @wp.func
499
+ def side_to_cell_arg(side_arg: SideArg):
500
+ return Quadmesh2DCellArg(side_arg.topology.cell_arg, side_arg.positions)
501
+
502
+ @wp.kernel
503
+ def _orient_edges(
504
+ edge_vertex_indices: wp.array(dtype=wp.vec2i),
505
+ edge_quad_indices: wp.array(dtype=wp.vec2i),
506
+ quad_vertex_indices: wp.array2d(dtype=int),
507
+ positions: wp.array(dtype=wp.vec2),
508
+ ):
509
+ e = wp.tid()
510
+
511
+ tri = edge_quad_indices[e][0]
512
+
513
+ quad_vidx = quad_vertex_indices[tri]
514
+ edge_vidx = edge_vertex_indices[e]
515
+
516
+ quad_centroid = (
517
+ positions[quad_vidx[0]] + positions[quad_vidx[1]] + positions[quad_vidx[2]] + positions[quad_vidx[3]]
518
+ ) / 4.0
519
+
520
+ v0 = positions[edge_vidx[0]]
521
+ v1 = positions[edge_vidx[1]]
522
+
523
+ edge_center = 0.5 * (v1 + v0)
524
+ edge_vec = v1 - v0
525
+ edge_normal = wp.vec2(-edge_vec[1], edge_vec[0])
526
+
527
+ # if edge normal points toward first triangle centroid, flip indices
528
+ if wp.dot(quad_centroid - edge_center, edge_normal) > 0.0:
529
+ edge_vertex_indices[e] = wp.vec2i(edge_vidx[1], edge_vidx[0])
530
+
531
+
532
+ @wp.struct
533
+ class Quadmesh3DCellArg:
534
+ topology: QuadmeshCellArg
535
+ positions: wp.array(dtype=wp.vec3)
536
+
537
+
538
+ @wp.struct
539
+ class Quadmesh3DSideArg:
540
+ topology: QuadmeshSideArg
541
+ positions: wp.array(dtype=wp.vec3)
542
+
543
+
544
+ class Quadmesh3D(Quadmesh):
545
+ """Three-dimensional quadrilateral mesh"""
546
+
547
+ dimension = 3
548
+ CellArg = Quadmesh3DCellArg
549
+ SideArg = Quadmesh3DSideArg
550
+
551
+ @wp.func
552
+ def cell_position(args: CellArg, s: Sample):
553
+ quad_idx = args.topology.quad_vertex_indices[s.element_index]
554
+
555
+ w_p = s.element_coords
556
+ w_m = Coords(1.0) - s.element_coords
557
+
558
+ # 0 : m m
559
+ # 1 : p m
560
+ # 2 : p p
561
+ # 3 : m p
562
+
563
+ return (
564
+ w_m[0] * w_m[1] * args.positions[quad_idx[0]]
565
+ + w_p[0] * w_m[1] * args.positions[quad_idx[1]]
566
+ + w_p[0] * w_p[1] * args.positions[quad_idx[2]]
567
+ + w_m[0] * w_p[1] * args.positions[quad_idx[3]]
568
+ )
569
+
570
+ @wp.func
571
+ def cell_deformation_gradient(cell_arg: CellArg, s: Sample):
572
+ """Deformation gradient at `coords`"""
573
+ quad_idx = cell_arg.topology.quad_vertex_indices[s.element_index]
574
+
575
+ w_p = s.element_coords
576
+ w_m = Coords(1.0) - s.element_coords
577
+
578
+ return (
579
+ wp.outer(cell_arg.positions[quad_idx[0]], wp.vec2(-w_m[1], -w_m[0]))
580
+ + wp.outer(cell_arg.positions[quad_idx[1]], wp.vec2(w_m[1], -w_p[0]))
581
+ + wp.outer(cell_arg.positions[quad_idx[2]], wp.vec2(w_p[1], w_p[0]))
582
+ + wp.outer(cell_arg.positions[quad_idx[3]], wp.vec2(-w_p[1], w_m[0]))
583
+ )
584
+
585
+ @wp.func
586
+ def side_position(args: SideArg, s: Sample):
587
+ edge_idx = args.topology.edge_vertex_indices[s.element_index]
588
+ return (1.0 - s.element_coords[0]) * args.positions[edge_idx[0]] + s.element_coords[0] * args.positions[
589
+ edge_idx[1]
590
+ ]
591
+
592
+ @wp.func
593
+ def side_deformation_gradient(args: SideArg, s: Sample):
594
+ edge_idx = args.topology.edge_vertex_indices[s.element_index]
595
+ v0 = args.positions[edge_idx[0]]
596
+ v1 = args.positions[edge_idx[1]]
597
+ return v1 - v0
598
+
599
+ @wp.func
600
+ def side_inner_cell_index(arg: SideArg, side_index: ElementIndex):
601
+ return arg.topology.edge_quad_indices[side_index][0]
602
+
603
+ @wp.func
604
+ def side_outer_cell_index(arg: SideArg, side_index: ElementIndex):
605
+ return arg.topology.edge_quad_indices[side_index][1]
606
+
607
+ @wp.func
608
+ def side_inner_cell_coords(args: SideArg, side_index: ElementIndex, side_coords: Coords):
609
+ inner_cell_index = Quadmesh3D.side_inner_cell_index(args, side_index)
610
+ return Quadmesh._edge_to_quad_coords(args.topology, side_index, inner_cell_index, side_coords)
611
+
612
+ @wp.func
613
+ def side_outer_cell_coords(args: SideArg, side_index: ElementIndex, side_coords: Coords):
614
+ outer_cell_index = Quadmesh3D.side_outer_cell_index(args, side_index)
615
+ return Quadmesh._edge_to_quad_coords(args.topology, side_index, outer_cell_index, side_coords)
616
+
617
+ @wp.func
618
+ def side_from_cell_coords(
619
+ args: SideArg,
620
+ side_index: ElementIndex,
621
+ quad_index: ElementIndex,
622
+ quad_coords: Coords,
623
+ ):
624
+ return Quadmesh._quad_to_edge_coords(args.topology, side_index, quad_index, quad_coords)
625
+
626
+ @wp.func
627
+ def side_to_cell_arg(side_arg: SideArg):
628
+ return Quadmesh3DCellArg(side_arg.topology.cell_arg, side_arg.positions)
629
+
630
+ @wp.kernel
631
+ def _orient_edges(
632
+ edge_vertex_indices: wp.array(dtype=wp.vec2i),
633
+ edge_quad_indices: wp.array(dtype=wp.vec2i),
634
+ quad_vertex_indices: wp.array2d(dtype=int),
635
+ positions: wp.array(dtype=wp.vec3),
636
+ ):
637
+ e = wp.tid()
638
+
639
+ tri = edge_quad_indices[e][0]
640
+
641
+ quad_vidx = quad_vertex_indices[tri]
642
+ edge_vidx = edge_vertex_indices[e]
643
+
644
+ p0 = positions[quad_vidx[0]]
645
+ p1 = positions[quad_vidx[1]]
646
+ p2 = positions[quad_vidx[2]]
647
+ p3 = positions[quad_vidx[3]]
648
+
649
+ quad_centroid = (
650
+ positions[quad_vidx[0]] + positions[quad_vidx[1]] + positions[quad_vidx[2]] + positions[quad_vidx[3]]
651
+ ) / 4.0
652
+ quad_normal = wp.cross(p2 - p0, p3 - p1)
653
+
654
+ v0 = positions[edge_vidx[0]]
655
+ v1 = positions[edge_vidx[1]]
656
+
657
+ edge_center = 0.5 * (v1 + v0)
658
+ edge_vec = v1 - v0
659
+ edge_normal = wp.cross(edge_vec, quad_normal)
660
+
661
+ # if edge normal points toward first triangle centroid, flip indices
662
+ if wp.dot(quad_centroid - edge_center, edge_normal) > 0.0:
663
+ edge_vertex_indices[e] = wp.vec2i(edge_vidx[1], edge_vidx[0])