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,834 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2023 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
+ import numpy as np
17
+
18
+ import warp as wp
19
+ from warp.fem import cache
20
+ from warp.fem.types import Coords
21
+
22
+ from .shape_function import ShapeFunction
23
+
24
+
25
+ def _tet_node_index(tx: int, ty: int, tz: int, degree: int):
26
+ from .triangle_shape_function import _triangle_node_index
27
+
28
+ VERTEX_NODE_COUNT = 4
29
+ EDGE_INTERIOR_NODE_COUNT = degree - 1
30
+ VERTEX_EDGE_NODE_COUNT = VERTEX_NODE_COUNT + 6 * EDGE_INTERIOR_NODE_COUNT
31
+ FACE_INTERIOR_NODE_COUNT = (degree - 1) * (degree - 2) // 2
32
+ VERTEX_EDGE_FACE_NODE_COUNT = VERTEX_EDGE_NODE_COUNT + 4 * FACE_INTERIOR_NODE_COUNT
33
+
34
+ # Index in similar order to e.g. VTK
35
+ # First vertices, then edges (counterclockwise), then faces, then interior points (recursively)
36
+
37
+ if tx == 0:
38
+ if ty == 0:
39
+ if tz == 0:
40
+ return 0
41
+ elif tz == degree:
42
+ return 3
43
+ else:
44
+ # 0-3 edge
45
+ edge_index = 3
46
+ return VERTEX_NODE_COUNT + EDGE_INTERIOR_NODE_COUNT * edge_index + (tz - 1)
47
+ elif tz == 0:
48
+ if ty == degree:
49
+ return 2
50
+ else:
51
+ # 2-0 edge
52
+ edge_index = 2
53
+ return VERTEX_NODE_COUNT + EDGE_INTERIOR_NODE_COUNT * edge_index + (EDGE_INTERIOR_NODE_COUNT - ty)
54
+ elif tz + ty == degree:
55
+ # 2-3 edge
56
+ edge_index = 5
57
+ return VERTEX_NODE_COUNT + EDGE_INTERIOR_NODE_COUNT * edge_index + (tz - 1)
58
+ else:
59
+ # 2-3-0 face
60
+ face_index = 2
61
+ return (
62
+ VERTEX_EDGE_NODE_COUNT
63
+ + FACE_INTERIOR_NODE_COUNT * face_index
64
+ + _triangle_node_index(degree - 1 - ty - tz, tz - 1, degree - 3)
65
+ )
66
+ elif ty == 0:
67
+ if tz == 0:
68
+ if tx == degree:
69
+ return 1
70
+ else:
71
+ # 0-1 edge
72
+ edge_index = 0
73
+ return VERTEX_NODE_COUNT + EDGE_INTERIOR_NODE_COUNT * edge_index + (tx - 1)
74
+ elif tz + tx == degree:
75
+ # 1-3 edge
76
+ edge_index = 4
77
+ return VERTEX_NODE_COUNT + EDGE_INTERIOR_NODE_COUNT * edge_index + (tz - 1)
78
+ else:
79
+ # 3-0-1 face
80
+ face_index = 3
81
+ return (
82
+ VERTEX_EDGE_NODE_COUNT
83
+ + FACE_INTERIOR_NODE_COUNT * face_index
84
+ + _triangle_node_index(tx - 1, tz - 1, degree - 3)
85
+ )
86
+ elif tz == 0:
87
+ if tx + ty == degree:
88
+ # 1-2 edge
89
+ edge_index = 1
90
+ return VERTEX_NODE_COUNT + EDGE_INTERIOR_NODE_COUNT * edge_index + (ty - 1)
91
+ else:
92
+ # 0-1-2 face
93
+ face_index = 0
94
+ return (
95
+ VERTEX_EDGE_NODE_COUNT
96
+ + FACE_INTERIOR_NODE_COUNT * face_index
97
+ + _triangle_node_index(tx - 1, ty - 1, degree - 3)
98
+ )
99
+ elif tx + ty + tz == degree:
100
+ # 1-2-3 face
101
+ face_index = 1
102
+ return (
103
+ VERTEX_EDGE_NODE_COUNT
104
+ + FACE_INTERIOR_NODE_COUNT * face_index
105
+ + _triangle_node_index(tx - 1, tz - 1, degree - 3)
106
+ )
107
+
108
+ return VERTEX_EDGE_FACE_NODE_COUNT + _tet_node_index(tx - 1, ty - 1, tz - 1, degree - 4)
109
+
110
+
111
+ class TetrahedronShapeFunction(ShapeFunction):
112
+ VERTEX = wp.constant(0)
113
+ EDGE = wp.constant(1)
114
+ FACE = wp.constant(2)
115
+ INTERIOR = wp.constant(3)
116
+
117
+ VERTEX_NODE_COUNT: int
118
+ """Number of shape function nodes per vertex"""
119
+
120
+ EDGE_NODE_COUNT: int
121
+ """Number of shape function nodes per tet edge (excluding vertex nodes)"""
122
+
123
+ FACE_NODE_COUNT: int
124
+ """Number of shape function nodes per tet face (excluding edge and vertex nodes)"""
125
+
126
+ INTERIOR_NODE_COUNT: int
127
+ """Number of shape function nodes per tet (excluding face, edge and vertex nodes)"""
128
+
129
+ @staticmethod
130
+ def node_type_and_index(node_index_in_elt: int):
131
+ pass
132
+
133
+ @wp.func
134
+ def edge_vidx(edge: int):
135
+ if edge < 3:
136
+ c1 = edge
137
+ c2 = (edge + 1) % 3
138
+ else:
139
+ c1 = edge - 3
140
+ c2 = 3
141
+ return c1, c2
142
+
143
+ @wp.func
144
+ def opposite_edge_vidx(edge: int):
145
+ if edge < 3:
146
+ e1 = (edge + 2) % 3
147
+ e2 = 3
148
+ else:
149
+ e1 = (edge - 2) % 3
150
+ e2 = (edge - 1) % 3
151
+ return e1, e2
152
+
153
+ @wp.func
154
+ def _vertex_coords(vidx: int):
155
+ return wp.vec3(
156
+ float(vidx == 1),
157
+ float(vidx == 2),
158
+ float(vidx == 3),
159
+ )
160
+
161
+
162
+ class TetrahedronPolynomialShapeFunctions(TetrahedronShapeFunction):
163
+ def __init__(self, degree: int):
164
+ self.ORDER = wp.constant(degree)
165
+
166
+ self.NODES_PER_ELEMENT = wp.constant((degree + 1) * (degree + 2) * (degree + 3) // 6)
167
+ self.NODES_PER_SIDE = wp.constant((degree + 1) * (degree + 2) // 2)
168
+
169
+ self.VERTEX_NODE_COUNT = wp.constant(1)
170
+ self.EDGE_NODE_COUNT = wp.constant(degree - 1)
171
+ self.NODES_PER_ELEMENT = wp.constant((degree + 1) * (degree + 2) * (degree + 3) // 6)
172
+ self.NODES_PER_SIDE = wp.constant((degree + 1) * (degree + 2) // 2)
173
+
174
+ self.SIDE_NODE_COUNT = wp.constant(self.NODES_PER_ELEMENT - 3 * (self.VERTEX_NODE_COUNT + self.EDGE_NODE_COUNT))
175
+ self.INTERIOR_NODE_COUNT = wp.constant(
176
+ self.NODES_PER_ELEMENT - 3 * (self.VERTEX_NODE_COUNT + self.EDGE_NODE_COUNT)
177
+ )
178
+
179
+ self.VERTEX_NODE_COUNT = wp.constant(1)
180
+ self.EDGE_NODE_COUNT = wp.constant(degree - 1)
181
+ self.FACE_NODE_COUNT = wp.constant(max(0, degree - 2) * max(0, degree - 1) // 2)
182
+ self.INERIOR_NODE_COUNT = wp.constant(max(0, degree - 1) * max(0, degree - 2) * max(0, degree - 3) // 6)
183
+
184
+ tet_coords = np.empty((self.NODES_PER_ELEMENT, 3), dtype=int)
185
+
186
+ for tx in range(degree + 1):
187
+ for ty in range(degree + 1 - tx):
188
+ for tz in range(degree + 1 - tx - ty):
189
+ index = _tet_node_index(tx, ty, tz, degree)
190
+ tet_coords[index] = [tx, ty, tz]
191
+
192
+ CoordTypeVec = wp.mat(dtype=int, shape=(self.NODES_PER_ELEMENT, 3))
193
+ self.NODE_TET_COORDS = wp.constant(CoordTypeVec(tet_coords))
194
+
195
+ self.node_type_and_type_index = self._get_node_type_and_type_index()
196
+ self._node_tet_coordinates = self._get_node_tet_coordinates()
197
+
198
+ @property
199
+ def name(self) -> str:
200
+ return f"Tet_P{self.ORDER}"
201
+
202
+ def _get_node_tet_coordinates(self):
203
+ NODE_TET_COORDS = self.NODE_TET_COORDS
204
+
205
+ def node_tet_coordinates(
206
+ node_index_in_elt: int,
207
+ ):
208
+ return NODE_TET_COORDS[node_index_in_elt]
209
+
210
+ return cache.get_func(node_tet_coordinates, self.name)
211
+
212
+ def _get_node_type_and_type_index(self):
213
+ ORDER = self.ORDER
214
+
215
+ def node_type_and_index(
216
+ node_index_in_elt: int,
217
+ ):
218
+ if node_index_in_elt < 4:
219
+ return TetrahedronPolynomialShapeFunctions.VERTEX, node_index_in_elt
220
+
221
+ if node_index_in_elt < (6 * ORDER - 2):
222
+ return TetrahedronPolynomialShapeFunctions.EDGE, (node_index_in_elt - 4)
223
+
224
+ if node_index_in_elt < (2 * ORDER * ORDER + 2):
225
+ return TetrahedronPolynomialShapeFunctions.FACE, (node_index_in_elt - (6 * ORDER - 2))
226
+
227
+ return TetrahedronPolynomialShapeFunctions.INTERIOR, (node_index_in_elt - (2 * ORDER * ORDER + 2))
228
+
229
+ return cache.get_func(node_type_and_index, self.name)
230
+
231
+ def make_node_coords_in_element(self):
232
+ ORDER = self.ORDER
233
+
234
+ def node_coords_in_element(
235
+ node_index_in_elt: int,
236
+ ):
237
+ tet_coords = self._node_tet_coordinates(node_index_in_elt)
238
+ cx = float(tet_coords[0]) / float(ORDER)
239
+ cy = float(tet_coords[1]) / float(ORDER)
240
+ cz = float(tet_coords[2]) / float(ORDER)
241
+ return Coords(cx, cy, cz)
242
+
243
+ return cache.get_func(node_coords_in_element, self.name)
244
+
245
+ def make_node_quadrature_weight(self):
246
+ if self.ORDER == 3:
247
+ # Order 1, but optimized quadrature weights for monomials of order <= 6
248
+ vertex_weight = 0.007348845656
249
+ edge_weight = 0.020688129855
250
+ face_weight = 0.180586764778
251
+ interior_weight = 0.0
252
+ else:
253
+ vertex_weight = 1.0 / self.NODES_PER_ELEMENT
254
+ edge_weight = 1.0 / self.NODES_PER_ELEMENT
255
+ face_weight = 1.0 / self.NODES_PER_ELEMENT
256
+ interior_weight = 1.0 / self.NODES_PER_ELEMENT
257
+
258
+ VERTEX_WEIGHT = wp.constant(vertex_weight)
259
+ EDGE_WEIGHT = wp.constant(edge_weight)
260
+ FACE_WEIGHT = wp.constant(face_weight)
261
+ INTERIOR_WEIGHT = wp.constant(interior_weight)
262
+
263
+ @cache.dynamic_func(suffix=self.name)
264
+ def node_quadrature_weight(node_index_in_element: int):
265
+ node_type, type_index = self.node_type_and_type_index(node_index_in_element)
266
+
267
+ if node_type == TetrahedronPolynomialShapeFunctions.VERTEX:
268
+ return VERTEX_WEIGHT
269
+ elif node_type == TetrahedronPolynomialShapeFunctions.EDGE:
270
+ return EDGE_WEIGHT
271
+ elif node_type == TetrahedronPolynomialShapeFunctions.FACE:
272
+ return FACE_WEIGHT
273
+
274
+ return INTERIOR_WEIGHT
275
+
276
+ return node_quadrature_weight
277
+
278
+ def make_trace_node_quadrature_weight(self):
279
+ if self.ORDER == 3:
280
+ # P3 intrinsic quadrature
281
+ vertex_weight = 1.0 / 30
282
+ edge_weight = 0.075
283
+ interior_weight = 0.45
284
+ elif self.ORDER == 2:
285
+ # Order 1, but optimized quadrature weights for monomials of order <= 4
286
+ vertex_weight = 0.022335964126
287
+ edge_weight = 0.310997369207
288
+ interior_weight = 0.0
289
+ else:
290
+ vertex_weight = 1.0 / self.NODES_PER_SIDE
291
+ edge_weight = 1.0 / self.NODES_PER_SIDE
292
+ interior_weight = 1.0 / self.NODES_PER_SIDE
293
+
294
+ VERTEX_WEIGHT = wp.constant(vertex_weight)
295
+ EDGE_WEIGHT = wp.constant(edge_weight)
296
+ FACE_INTERIOR_WEIGHT = wp.constant(interior_weight)
297
+
298
+ @cache.dynamic_func(suffix=self.name)
299
+ def trace_node_quadrature_weight(node_index_in_element: int):
300
+ node_type, type_index = self.node_type_and_type_index(node_index_in_element)
301
+
302
+ if node_type == TetrahedronPolynomialShapeFunctions.VERTEX:
303
+ return VERTEX_WEIGHT
304
+ elif node_type == TetrahedronPolynomialShapeFunctions.EDGE:
305
+ return EDGE_WEIGHT
306
+
307
+ return FACE_INTERIOR_WEIGHT
308
+
309
+ return trace_node_quadrature_weight
310
+
311
+ def make_element_inner_weight(self):
312
+ ORDER = self.ORDER
313
+
314
+ def element_inner_weight_linear(
315
+ coords: Coords,
316
+ node_index_in_elt: int,
317
+ ):
318
+ if node_index_in_elt < 0 or node_index_in_elt >= 4:
319
+ return 0.0
320
+
321
+ tet_coords = wp.vec4(1.0 - coords[0] - coords[1] - coords[2], coords[0], coords[1], coords[2])
322
+ return tet_coords[node_index_in_elt]
323
+
324
+ def element_inner_weight_quadratic(
325
+ coords: Coords,
326
+ node_index_in_elt: int,
327
+ ):
328
+ node_type, type_index = self.node_type_and_type_index(node_index_in_elt)
329
+
330
+ tet_coords = wp.vec4(1.0 - coords[0] - coords[1] - coords[2], coords[0], coords[1], coords[2])
331
+
332
+ if node_type == TetrahedronPolynomialShapeFunctions.VERTEX:
333
+ # Vertex
334
+ return tet_coords[type_index] * (2.0 * tet_coords[type_index] - 1.0)
335
+
336
+ elif node_type == TetrahedronPolynomialShapeFunctions.EDGE:
337
+ # Edge
338
+ c1, c2 = TetrahedronShapeFunction.edge_vidx(type_index)
339
+ return 4.0 * tet_coords[c1] * tet_coords[c2]
340
+
341
+ return 0.0
342
+
343
+ def element_inner_weight_cubic(
344
+ coords: Coords,
345
+ node_index_in_elt: int,
346
+ ):
347
+ node_type, type_index = self.node_type_and_type_index(node_index_in_elt)
348
+
349
+ tet_coords = wp.vec4(1.0 - coords[0] - coords[1] - coords[2], coords[0], coords[1], coords[2])
350
+
351
+ if node_type == TetrahedronPolynomialShapeFunctions.VERTEX:
352
+ # Vertex
353
+ return (
354
+ 0.5
355
+ * tet_coords[type_index]
356
+ * (3.0 * tet_coords[type_index] - 1.0)
357
+ * (3.0 * tet_coords[type_index] - 2.0)
358
+ )
359
+
360
+ elif node_type == TetrahedronPolynomialShapeFunctions.EDGE:
361
+ # Edge
362
+ edge = type_index // 2
363
+ edge_node = type_index - 2 * edge
364
+
365
+ if edge < 3:
366
+ c1 = (edge + edge_node) % 3
367
+ c2 = (edge + 1 - edge_node) % 3
368
+ elif edge_node == 0:
369
+ c1 = edge - 3
370
+ c2 = 3
371
+ else:
372
+ c1 = 3
373
+ c2 = edge - 3
374
+
375
+ return 4.5 * tet_coords[c1] * tet_coords[c2] * (3.0 * tet_coords[c1] - 1.0)
376
+
377
+ elif node_type == TetrahedronPolynomialShapeFunctions.FACE:
378
+ # Interior
379
+ c1 = type_index
380
+ c2 = (c1 + 1) % 4
381
+ c3 = (c1 + 2) % 4
382
+ return 27.0 * tet_coords[c1] * tet_coords[c2] * tet_coords[c3]
383
+
384
+ return 0.0
385
+
386
+ if ORDER == 1:
387
+ return cache.get_func(element_inner_weight_linear, self.name)
388
+ elif ORDER == 2:
389
+ return cache.get_func(element_inner_weight_quadratic, self.name)
390
+ elif ORDER == 3:
391
+ return cache.get_func(element_inner_weight_cubic, self.name)
392
+
393
+ return None
394
+
395
+ def make_element_inner_weight_gradient(self):
396
+ ORDER = self.ORDER
397
+
398
+ def element_inner_weight_gradient_linear(
399
+ coords: Coords,
400
+ node_index_in_elt: int,
401
+ ):
402
+ if node_index_in_elt < 0 or node_index_in_elt >= 4:
403
+ return wp.vec3(0.0)
404
+
405
+ dw_dc = wp.vec4(0.0)
406
+ dw_dc[node_index_in_elt] = 1.0
407
+
408
+ dw_du = wp.vec3(dw_dc[1] - dw_dc[0], dw_dc[2] - dw_dc[0], dw_dc[3] - dw_dc[0])
409
+
410
+ return dw_du
411
+
412
+ def element_inner_weight_gradient_quadratic(
413
+ coords: Coords,
414
+ node_index_in_elt: int,
415
+ ):
416
+ node_type, type_index = self.node_type_and_type_index(node_index_in_elt)
417
+
418
+ tet_coords = wp.vec4(1.0 - coords[0] - coords[1] - coords[2], coords[0], coords[1], coords[2])
419
+ dw_dc = wp.vec4(0.0)
420
+
421
+ if node_type == TetrahedronPolynomialShapeFunctions.VERTEX:
422
+ # Vertex
423
+ dw_dc[type_index] = 4.0 * tet_coords[type_index] - 1.0
424
+
425
+ elif node_type == TetrahedronPolynomialShapeFunctions.EDGE:
426
+ # Edge
427
+ c1, c2 = TetrahedronShapeFunction.edge_vidx(type_index)
428
+ dw_dc[c1] = 4.0 * tet_coords[c2]
429
+ dw_dc[c2] = 4.0 * tet_coords[c1]
430
+
431
+ dw_du = wp.vec3(dw_dc[1] - dw_dc[0], dw_dc[2] - dw_dc[0], dw_dc[3] - dw_dc[0])
432
+ return dw_du
433
+
434
+ def element_inner_weight_gradient_cubic(
435
+ coords: Coords,
436
+ node_index_in_elt: int,
437
+ ):
438
+ node_type, type_index = self.node_type_and_type_index(node_index_in_elt)
439
+
440
+ tet_coords = wp.vec4(1.0 - coords[0] - coords[1] - coords[2], coords[0], coords[1], coords[2])
441
+
442
+ dw_dc = wp.vec4(0.0)
443
+
444
+ if node_type == TetrahedronPolynomialShapeFunctions.VERTEX:
445
+ # Vertex
446
+ dw_dc[type_index] = (
447
+ 0.5 * 27.0 * tet_coords[type_index] * tet_coords[type_index] - 9.0 * tet_coords[type_index] + 1.0
448
+ )
449
+
450
+ elif node_type == TetrahedronPolynomialShapeFunctions.EDGE:
451
+ # Edge
452
+ edge = type_index // 2
453
+ edge_node = type_index - 2 * edge
454
+
455
+ if edge < 3:
456
+ c1 = (edge + edge_node) % 3
457
+ c2 = (edge + 1 - edge_node) % 3
458
+ elif edge_node == 0:
459
+ c1 = edge - 3
460
+ c2 = 3
461
+ else:
462
+ c1 = 3
463
+ c2 = edge - 3
464
+
465
+ dw_dc[c1] = 4.5 * tet_coords[c2] * (6.0 * tet_coords[c1] - 1.0)
466
+ dw_dc[c2] = 4.5 * tet_coords[c1] * (3.0 * tet_coords[c1] - 1.0)
467
+
468
+ elif node_type == TetrahedronPolynomialShapeFunctions.FACE:
469
+ # Interior
470
+ c1 = type_index
471
+ c2 = (c1 + 1) % 4
472
+ c3 = (c1 + 2) % 4
473
+
474
+ dw_dc[c1] = 27.0 * tet_coords[c2] * tet_coords[c3]
475
+ dw_dc[c2] = 27.0 * tet_coords[c3] * tet_coords[c1]
476
+ dw_dc[c3] = 27.0 * tet_coords[c1] * tet_coords[c2]
477
+
478
+ dw_du = wp.vec3(dw_dc[1] - dw_dc[0], dw_dc[2] - dw_dc[0], dw_dc[3] - dw_dc[0])
479
+ return dw_du
480
+
481
+ if ORDER == 1:
482
+ return cache.get_func(element_inner_weight_gradient_linear, self.name)
483
+ elif ORDER == 2:
484
+ return cache.get_func(element_inner_weight_gradient_quadratic, self.name)
485
+ elif ORDER == 3:
486
+ return cache.get_func(element_inner_weight_gradient_cubic, self.name)
487
+
488
+ return None
489
+
490
+ def element_node_tets(self):
491
+ if self.ORDER == 1:
492
+ element_tets = [[0, 1, 2, 3]]
493
+ if self.ORDER == 2:
494
+ element_tets = [
495
+ [0, 4, 6, 7],
496
+ [1, 5, 4, 8],
497
+ [2, 6, 5, 9],
498
+ [3, 7, 8, 9],
499
+ [4, 5, 6, 8],
500
+ [8, 7, 9, 6],
501
+ [6, 5, 9, 8],
502
+ [6, 8, 7, 4],
503
+ ]
504
+ elif self.ORDER == 3:
505
+ raise NotImplementedError()
506
+
507
+ return np.array(element_tets)
508
+
509
+ def element_vtk_cells(self):
510
+ cells = np.arange(self.NODES_PER_ELEMENT)
511
+ if self.ORDER == 1:
512
+ cell_type = 10 # VTK_TETRA
513
+ else:
514
+ cell_type = 71 # VTK_LAGRANGE_TETRAHEDRON
515
+ return cells[np.newaxis, :], np.array([cell_type], dtype=np.int8)
516
+
517
+
518
+ class TetrahedronNonConformingPolynomialShapeFunctions(ShapeFunction):
519
+ def __init__(self, degree: int):
520
+ self._tet_shape = TetrahedronPolynomialShapeFunctions(degree=degree)
521
+ self.ORDER = self._tet_shape.ORDER
522
+ self.NODES_PER_ELEMENT = self._tet_shape.NODES_PER_ELEMENT
523
+
524
+ self.element_node_tets = self._tet_shape.element_node_tets
525
+ self.element_vtk_cells = self._tet_shape.element_vtk_cells
526
+
527
+ if self.ORDER == 1:
528
+ self._TET_SCALE = 0.4472135955 # so v at 0.5854101966249680 (order 2)
529
+ elif self.ORDER == 2:
530
+ self._TET_SCALE = 0.6123779296874996 # optimized for low intrinsic quadrature error of deg 4
531
+ elif self.ORDER == 3:
532
+ self._TET_SCALE = 0.7153564453124999 # optimized for low intrinsic quadrature error of deg 6
533
+ else:
534
+ self._TET_SCALE = 1.0
535
+
536
+ self._TET_SCALE = wp.constant(self._TET_SCALE)
537
+ self._TET_OFFSET = wp.constant((1.0 - self._TET_SCALE) * wp.vec3(0.25, 0.25, 0.25))
538
+
539
+ @property
540
+ def name(self) -> str:
541
+ return f"Tet_P{self.ORDER}d"
542
+
543
+ def make_node_coords_in_element(self):
544
+ node_coords_in_tet = self._tet_shape.make_node_coords_in_element()
545
+
546
+ TET_SCALE = self._TET_SCALE
547
+ TET_OFFSET = self._TET_OFFSET
548
+
549
+ @cache.dynamic_func(suffix=self.name)
550
+ def node_coords_in_element(
551
+ node_index_in_elt: int,
552
+ ):
553
+ tet_coords = node_coords_in_tet(node_index_in_elt)
554
+ return TET_SCALE * tet_coords + TET_OFFSET
555
+
556
+ return node_coords_in_element
557
+
558
+ def make_node_quadrature_weight(self):
559
+ # Intrinsic quadrature -- precomputed integral of node shape functions
560
+ # over element. Order equal to self.ORDER
561
+
562
+ if self.ORDER == 2:
563
+ vertex_weight = 0.07499641
564
+ edge_weight = 0.11666908
565
+ face_interior_weight = 0.0
566
+ elif self.ORDER == 3:
567
+ vertex_weight = 0.03345134
568
+ edge_weight = 0.04521887
569
+ face_interior_weight = 0.08089206
570
+ else:
571
+ vertex_weight = 1.0 / self.NODES_PER_ELEMENT
572
+ edge_weight = 1.0 / self.NODES_PER_ELEMENT
573
+ face_interior_weight = 1.0 / self.NODES_PER_ELEMENT
574
+
575
+ VERTEX_WEIGHT = wp.constant(vertex_weight)
576
+ EDGE_WEIGHT = wp.constant(edge_weight)
577
+ FACE_INTERIOR_WEIGHT = wp.constant(face_interior_weight)
578
+
579
+ @cache.dynamic_func(suffix=self.name)
580
+ def node_quadrature_weight(node_index_in_element: int):
581
+ node_type, type_index = self._tet_shape.node_type_and_type_index(node_index_in_element)
582
+
583
+ if node_type == TetrahedronPolynomialShapeFunctions.VERTEX:
584
+ return VERTEX_WEIGHT
585
+ elif node_type == TetrahedronPolynomialShapeFunctions.EDGE:
586
+ return EDGE_WEIGHT
587
+
588
+ return FACE_INTERIOR_WEIGHT
589
+
590
+ return node_quadrature_weight
591
+
592
+ def make_trace_node_quadrature_weight(self):
593
+ # Non-conforming, zero measure on sides
594
+
595
+ @wp.func
596
+ def zero(node_index_in_elt: int):
597
+ return 0.0
598
+
599
+ return zero
600
+
601
+ def make_element_inner_weight(self):
602
+ tet_inner_weight = self._tet_shape.make_element_inner_weight()
603
+
604
+ TET_SCALE = self._TET_SCALE
605
+ TET_OFFSET = self._TET_OFFSET
606
+
607
+ @cache.dynamic_func(suffix=self.name)
608
+ def element_inner_weight(
609
+ coords: Coords,
610
+ node_index_in_elt: int,
611
+ ):
612
+ tet_coords = (coords - TET_OFFSET) / TET_SCALE
613
+
614
+ return tet_inner_weight(tet_coords, node_index_in_elt)
615
+
616
+ return element_inner_weight
617
+
618
+ def make_element_inner_weight_gradient(self):
619
+ tet_inner_weight_gradient = self._tet_shape.make_element_inner_weight_gradient()
620
+
621
+ TET_SCALE = self._TET_SCALE
622
+ TET_OFFSET = self._TET_OFFSET
623
+
624
+ @cache.dynamic_func(suffix=self.name)
625
+ def element_inner_weight_gradient(
626
+ coords: Coords,
627
+ node_index_in_elt: int,
628
+ ):
629
+ tet_coords = (coords - TET_OFFSET) / TET_SCALE
630
+ grad = tet_inner_weight_gradient(tet_coords, node_index_in_elt)
631
+ return grad / TET_SCALE
632
+
633
+ return element_inner_weight_gradient
634
+
635
+
636
+ class TetrahedronNedelecFirstKindShapeFunctions(TetrahedronShapeFunction):
637
+ value = ShapeFunction.Value.CovariantVector
638
+
639
+ def __init__(self, degree: int):
640
+ if degree != 1:
641
+ raise NotImplementedError("Only linear Nédélec implemented right now")
642
+
643
+ self.ORDER = wp.constant(degree)
644
+
645
+ self.NODES_PER_ELEMENT = wp.constant(6)
646
+ self.NODES_PER_SIDE = wp.constant(3)
647
+
648
+ self.VERTEX_NODE_COUNT = wp.constant(0)
649
+ self.EDGE_NODE_COUNT = wp.constant(1)
650
+ self.FACE_NODE_COUNT = wp.constant(0)
651
+ self.INTERIOR_NODE_COUNT = wp.constant(0)
652
+
653
+ self.node_type_and_type_index = self._get_node_type_and_type_index()
654
+
655
+ @property
656
+ def name(self) -> str:
657
+ return f"TetN1_{self.ORDER}"
658
+
659
+ def _get_node_type_and_type_index(self):
660
+ @cache.dynamic_func(suffix=self.name)
661
+ def node_type_and_index(
662
+ node_index_in_elt: int,
663
+ ):
664
+ return TetrahedronShapeFunction.EDGE, node_index_in_elt
665
+
666
+ return node_type_and_index
667
+
668
+ def make_node_coords_in_element(self):
669
+ @cache.dynamic_func(suffix=self.name)
670
+ def node_coords_in_element(
671
+ node_index_in_elt: int,
672
+ ):
673
+ c1, c2 = TetrahedronShapeFunction.edge_vidx(node_index_in_elt)
674
+
675
+ coords = wp.vec4(0.0)
676
+ coords[c1] = 0.5
677
+ coords[c2] = 0.5
678
+
679
+ return Coords(coords[1], coords[2], coords[3])
680
+
681
+ return node_coords_in_element
682
+
683
+ def make_node_quadrature_weight(self):
684
+ NODES_PER_ELEMENT = self.NODES_PER_ELEMENT
685
+
686
+ @cache.dynamic_func(suffix=self.name)
687
+ def node_quadrature_weight(node_index_in_element: int):
688
+ return 1.0 / float(NODES_PER_ELEMENT)
689
+
690
+ return node_quadrature_weight
691
+
692
+ def make_trace_node_quadrature_weight(self):
693
+ NODES_PER_SIDE = self.NODES_PER_SIDE
694
+
695
+ @cache.dynamic_func(suffix=self.name)
696
+ def trace_node_quadrature_weight(node_index_in_element: int):
697
+ return 1.0 / float(NODES_PER_SIDE)
698
+
699
+ return trace_node_quadrature_weight
700
+
701
+ def make_element_inner_weight(self):
702
+ ORDER = self.ORDER
703
+
704
+ def element_inner_weight_linear(
705
+ coords: Coords,
706
+ node_index_in_elt: int,
707
+ ):
708
+ e1, e2 = TetrahedronShapeFunction.opposite_edge_vidx(node_index_in_elt)
709
+
710
+ v1 = self._vertex_coords(e1)
711
+ v2 = self._vertex_coords(e2)
712
+
713
+ nor = v2 - v1
714
+ return wp.cross(nor, coords - v1)
715
+
716
+ if ORDER == 1:
717
+ return cache.get_func(element_inner_weight_linear, self.name)
718
+
719
+ return None
720
+
721
+ def make_element_inner_weight_gradient(self):
722
+ ORDER = self.ORDER
723
+
724
+ def element_inner_weight_gradient_linear(
725
+ coords: Coords,
726
+ node_index_in_elt: int,
727
+ ):
728
+ e1, e2 = TetrahedronShapeFunction.opposite_edge_vidx(node_index_in_elt)
729
+
730
+ v1 = self._vertex_coords(e1)
731
+ v2 = self._vertex_coords(e2)
732
+
733
+ nor = v2 - v1
734
+ return wp.skew(nor)
735
+
736
+ if ORDER == 1:
737
+ return cache.get_func(element_inner_weight_gradient_linear, self.name)
738
+
739
+ return None
740
+
741
+
742
+ class TetrahedronRaviartThomasShapeFunctions(TetrahedronShapeFunction):
743
+ value = ShapeFunction.Value.ContravariantVector
744
+
745
+ def __init__(self, degree: int):
746
+ if degree != 1:
747
+ raise NotImplementedError("Only linear Raviart-Thomas implemented right now")
748
+
749
+ self.ORDER = wp.constant(degree)
750
+
751
+ self.NODES_PER_ELEMENT = wp.constant(4)
752
+ self.NODES_PER_SIDE = wp.constant(1)
753
+
754
+ self.VERTEX_NODE_COUNT = wp.constant(0)
755
+ self.EDGE_NODE_COUNT = wp.constant(0)
756
+ self.FACE_NODE_COUNT = wp.constant(1)
757
+ self.INTERIOR_NODE_COUNT = wp.constant(0)
758
+
759
+ self.node_type_and_type_index = self._get_node_type_and_type_index()
760
+
761
+ @property
762
+ def name(self) -> str:
763
+ return f"TetRT_{self.ORDER}"
764
+
765
+ def _get_node_type_and_type_index(self):
766
+ @cache.dynamic_func(suffix=self.name)
767
+ def node_type_and_index(
768
+ node_index_in_elt: int,
769
+ ):
770
+ return TetrahedronShapeFunction.FACE, node_index_in_elt
771
+
772
+ return node_type_and_index
773
+
774
+ def make_node_coords_in_element(self):
775
+ @cache.dynamic_func(suffix=self.name)
776
+ def node_coords_in_element(
777
+ node_index_in_elt: int,
778
+ ):
779
+ v = (node_index_in_elt + 3) % 4
780
+
781
+ coords = wp.vec4(1.0 / 3.0)
782
+ coords[v] = 0.0
783
+
784
+ return Coords(coords[1], coords[2], coords[3])
785
+
786
+ return node_coords_in_element
787
+
788
+ def make_node_quadrature_weight(self):
789
+ NODES_PER_ELEMENT = self.NODES_PER_ELEMENT
790
+
791
+ @cache.dynamic_func(suffix=self.name)
792
+ def node_quadrature_weight(node_index_in_element: int):
793
+ return 1.0 / float(NODES_PER_ELEMENT)
794
+
795
+ return node_quadrature_weight
796
+
797
+ def make_trace_node_quadrature_weight(self):
798
+ NODES_PER_SIDE = self.NODES_PER_SIDE
799
+
800
+ @cache.dynamic_func(suffix=self.name)
801
+ def trace_node_quadrature_weight(node_index_in_element: int):
802
+ return 1.0 / float(NODES_PER_SIDE)
803
+
804
+ return trace_node_quadrature_weight
805
+
806
+ def make_element_inner_weight(self):
807
+ ORDER = self.ORDER
808
+
809
+ def element_inner_weight_linear(
810
+ coords: Coords,
811
+ node_index_in_elt: int,
812
+ ):
813
+ v = (node_index_in_elt + 3) % 4
814
+
815
+ return 2.0 * (coords - self._vertex_coords(v))
816
+
817
+ if ORDER == 1:
818
+ return cache.get_func(element_inner_weight_linear, self.name)
819
+
820
+ return None
821
+
822
+ def make_element_inner_weight_gradient(self):
823
+ ORDER = self.ORDER
824
+
825
+ def element_inner_weight_gradient_linear(
826
+ coords: Coords,
827
+ node_index_in_elt: int,
828
+ ):
829
+ return 2.0 * wp.identity(n=3, dtype=float)
830
+
831
+ if ORDER == 1:
832
+ return cache.get_func(element_inner_weight_gradient_linear, self.name)
833
+
834
+ return None