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
warp/fem/linalg.py ADDED
@@ -0,0 +1,419 @@
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
17
+
18
+ import warp as wp
19
+
20
+
21
+ @wp.func
22
+ def generalized_outer(x: Any, y: Any):
23
+ """Generalized outer product allowing for the first argument to be a scalar"""
24
+ return wp.outer(x, y)
25
+
26
+
27
+ @wp.func
28
+ def generalized_outer(x: wp.float32, y: wp.vec2):
29
+ return x * y
30
+
31
+
32
+ @wp.func
33
+ def generalized_outer(x: wp.float32, y: wp.vec3):
34
+ return x * y
35
+
36
+
37
+ @wp.func
38
+ def generalized_inner(x: Any, y: Any):
39
+ """Generalized inner product allowing for the first argument to be a tensor"""
40
+ return wp.dot(x, y)
41
+
42
+
43
+ @wp.func
44
+ def generalized_inner(x: float, y: float):
45
+ return x * y
46
+
47
+
48
+ @wp.func
49
+ def generalized_inner(x: wp.mat22, y: wp.vec2):
50
+ return x[0] * y[0] + x[1] * y[1]
51
+
52
+
53
+ @wp.func
54
+ def generalized_inner(x: wp.mat33, y: wp.vec3):
55
+ return x[0] * y[0] + x[1] * y[1] + x[2] * y[2]
56
+
57
+
58
+ @wp.func
59
+ def basis_element(template_type: Any, coord: int):
60
+ """Returns a instance of `template_type` with a single coordinate set to 1 in the canonical basis"""
61
+
62
+ t = type(template_type)(0.0)
63
+ t[coord] = 1.0
64
+ return t
65
+
66
+
67
+ @wp.func
68
+ def basis_element(template_type: wp.float32, coord: int):
69
+ return 1.0
70
+
71
+
72
+ @wp.func
73
+ def basis_element(template_type: wp.mat22, coord: int):
74
+ t = wp.mat22(0.0)
75
+ row = coord // 2
76
+ col = coord - 2 * row
77
+ t[row, col] = 1.0
78
+ return t
79
+
80
+
81
+ @wp.func
82
+ def basis_element(template_type: wp.mat33, coord: int):
83
+ t = wp.mat33(0.0)
84
+ row = coord // 3
85
+ col = coord - 3 * row
86
+ t[row, col] = 1.0
87
+ return t
88
+
89
+
90
+ @wp.func
91
+ def basis_coefficient(val: wp.float32, i: int):
92
+ return val
93
+
94
+
95
+ @wp.func
96
+ def basis_coefficient(val: Any, i: int):
97
+ return val[i]
98
+
99
+
100
+ @wp.func
101
+ def basis_coefficient(val: wp.vec2, i: int, j: int):
102
+ # treat as row vector
103
+ return val[j]
104
+
105
+
106
+ @wp.func
107
+ def basis_coefficient(val: wp.vec3, i: int, j: int):
108
+ # treat as row vector
109
+ return val[j]
110
+
111
+
112
+ @wp.func
113
+ def basis_coefficient(val: Any, i: int, j: int):
114
+ return val[i, j]
115
+
116
+
117
+ @wp.func
118
+ def basis_coefficient(template_type: wp.mat33, coord: int):
119
+ t = wp.mat33(0.0)
120
+ row = coord // 3
121
+ col = coord - 3 * row
122
+ t[row, col] = 1.0
123
+ return t
124
+
125
+
126
+ @wp.func
127
+ def symmetric_part(x: Any):
128
+ """Symmetric part of a square tensor"""
129
+ return 0.5 * (x + wp.transpose(x))
130
+
131
+
132
+ @wp.func
133
+ def spherical_part(x: wp.mat22):
134
+ """Spherical part of a square tensor"""
135
+ return 0.5 * wp.trace(x) * wp.identity(n=2, dtype=float)
136
+
137
+
138
+ @wp.func
139
+ def spherical_part(x: wp.mat33):
140
+ """Spherical part of a square tensor"""
141
+ return (wp.trace(x) / 3.0) * wp.identity(n=3, dtype=float)
142
+
143
+
144
+ @wp.func
145
+ def skew_part(x: wp.mat22):
146
+ """Skew part of a 2x2 tensor as corresponding rotation angle"""
147
+ return 0.5 * (x[1, 0] - x[0, 1])
148
+
149
+
150
+ @wp.func
151
+ def skew_part(x: wp.mat33):
152
+ """Skew part of a 3x3 tensor as the corresponding rotation vector"""
153
+ a = 0.5 * (x[2, 1] - x[1, 2])
154
+ b = 0.5 * (x[0, 2] - x[2, 0])
155
+ c = 0.5 * (x[1, 0] - x[0, 1])
156
+ return wp.vec3(a, b, c)
157
+
158
+
159
+ @wp.func
160
+ def householder_qr_decomposition(A: Any):
161
+ """
162
+ QR decomposition of a square matrix using Householder reflections
163
+
164
+ Returns Q and R such that Q R = A, Q orthonormal (such that QQ^T = Id), R upper triangular
165
+ """
166
+
167
+ x = type(A[0])()
168
+ Q = wp.identity(n=type(x).length, dtype=A.dtype)
169
+
170
+ zero = x.dtype(0.0)
171
+ two = x.dtype(2.0)
172
+
173
+ for i in range(type(x).length):
174
+ for k in range(type(x).length):
175
+ x[k] = wp.where(k < i, zero, A[k, i])
176
+
177
+ alpha = wp.length(x) * wp.sign(x[i])
178
+ x[i] += alpha
179
+ two_over_x_sq = wp.where(alpha == zero, zero, two / wp.length_sq(x))
180
+
181
+ A -= wp.outer(two_over_x_sq * x, x * A)
182
+ Q -= wp.outer(Q * x, two_over_x_sq * x)
183
+
184
+ return Q, A
185
+
186
+
187
+ @wp.func
188
+ def householder_make_hessenberg(A: Any):
189
+ """Transforms a square matrix to Hessenberg form (single lower diagonal) using Householder reflections
190
+
191
+ Returns:
192
+ Q and H such that Q H Q^T = A, Q orthonormal, H under Hessenberg form
193
+ If A is symmetric, H will be tridiagonal
194
+ """
195
+
196
+ x = type(A[0])()
197
+ Q = wp.identity(n=type(x).length, dtype=A.dtype)
198
+
199
+ zero = x.dtype(0.0)
200
+ two = x.dtype(2.0)
201
+
202
+ for i in range(1, type(x).length):
203
+ for k in range(type(x).length):
204
+ x[k] = wp.where(k < i, zero, A[k, i - 1])
205
+
206
+ alpha = wp.length(x) * wp.sign(x[i])
207
+ x[i] += alpha
208
+ two_over_x_sq = wp.where(alpha == zero, zero, two / wp.length_sq(x))
209
+
210
+ # apply on both sides
211
+ A -= wp.outer(two_over_x_sq * x, x * A)
212
+ A -= wp.outer(A * x, two_over_x_sq * x)
213
+ Q -= wp.outer(Q * x, two_over_x_sq * x)
214
+
215
+ return Q, A
216
+
217
+
218
+ @wp.func
219
+ def solve_triangular(R: Any, b: Any):
220
+ """Solves for R x = b where R is an upper triangular matrix
221
+
222
+ Returns x
223
+ """
224
+ zero = b.dtype(0)
225
+ x = type(b)(b.dtype(0))
226
+ for i in range(b.length, 0, -1):
227
+ j = i - 1
228
+ r = b[j] - wp.dot(R[j], x)
229
+ x[j] = wp.where(R[j, j] == zero, zero, r / R[j, j])
230
+
231
+ return x
232
+
233
+
234
+ @wp.func
235
+ def inverse_qr(A: Any):
236
+ # Computes a square matrix inverse using QR factorization
237
+
238
+ Q, R = householder_qr_decomposition(A)
239
+
240
+ A_inv = type(A)()
241
+ for i in range(type(A[0]).length):
242
+ A_inv[i] = solve_triangular(R, Q[i]) # ith column of Q^T
243
+
244
+ return wp.transpose(A_inv)
245
+
246
+
247
+ @wp.func
248
+ def _wilkinson_shift(a: Any, b: Any, c: Any, tol: Any):
249
+ # Wilkinson shift: estimate eigenvalue of 2x2 symmetric matrix [a, c, c, b]
250
+ d = (a - b) * type(tol)(0.5)
251
+ return b + d - wp.sign(d) * wp.sqrt(d * d + c * c)
252
+
253
+
254
+ @wp.func
255
+ def _givens_rotation(a: Any, b: Any):
256
+ # Givens rotation [[c -s], [s c]] such that sa+cb =0
257
+ zero = type(a)(0.0)
258
+ one = type(a)(1.0)
259
+
260
+ b2 = b * b
261
+ if b2 == zero:
262
+ # id rotation
263
+ return one, zero
264
+
265
+ scale = one / wp.sqrt(a * a + b2)
266
+ return a * scale, -b * scale
267
+
268
+
269
+ @wp.func
270
+ def tridiagonal_symmetric_eigenvalues_qr(D: Any, L: Any, Q: Any, tol: Any):
271
+ """
272
+ Computes the eigenvalues and eigen vectors of a symmetric tridiagonal matrix using the
273
+ Symmetric tridiagonal QR algorithm with implicit Wilkinson shift
274
+
275
+ Args:
276
+ D: Main diagonal of the matrix
277
+ L: Lower diagonal of the matrix, indexed such that L[i] = A[i+1, i]
278
+ Q: Initialization for the eigenvectors, useful if a pre-transformation has been applied, otherwise may be identity
279
+ tol: Tolerance for the diagonalization residual (Linf norm of off-diagonal over diagonal terms)
280
+
281
+ Returns a tuple (D: vector of eigenvalues, P: matrix with one eigenvector per row) such that A = P^T D P
282
+
283
+
284
+ Ref: Arbenz P, Numerical Methods for Solving Large Scale Eigenvalue Problems, Chapter 4 (QR algorithm, Mar 13, 2018)
285
+ """
286
+
287
+ two = D.dtype(2.0)
288
+
289
+ # so that we can use the type length in expressions
290
+ # this will prevent unrolling by warp, but should be ok for native code
291
+ m = int(0)
292
+ for _ in range(type(D).length):
293
+ m += 1
294
+
295
+ start = int(0)
296
+ y = D.dtype(0.0) # moving buldge
297
+ x = D.dtype(0.0) # coeff atop buldge
298
+
299
+ for _ in range(32 * m): # failsafe, usually converges faster than that
300
+ # Iterate over all independent (deflated) blocks
301
+ end = int(-1)
302
+
303
+ for k in range(m - 1):
304
+ if k >= end:
305
+ # Check if new block is starting
306
+ if k == end or wp.abs(L[k]) <= tol * (wp.abs(D[k]) + wp.abs(D[k + 1])):
307
+ continue
308
+
309
+ # Find end of block
310
+ start = k
311
+ end = start + 1
312
+ while end + 1 < m:
313
+ if wp.abs(L[end]) <= tol * (wp.abs(D[end + 1]) + wp.abs(D[end])):
314
+ break
315
+ end += 1
316
+
317
+ # Wilkinson shift (an eigenvalue of the last 2x2 block)
318
+ shift = _wilkinson_shift(D[end - 1], D[end], L[end - 1], tol)
319
+
320
+ # start with eliminating lower diag of first column of shifted matrix
321
+ # (i.e. first step of explicit QR factorization)
322
+ # Then all further steps eliminate the buldge (second diag) of the non-shifted matrix
323
+ x = D[start] - shift
324
+ y = L[start]
325
+
326
+ c, s = _givens_rotation(x, y)
327
+
328
+ # Apply Givens rotation on both sides of tridiagonal matrix
329
+
330
+ # middle block
331
+ d = D[k] - D[k + 1]
332
+ z = (two * c * L[k] + d * s) * s
333
+ D[k] -= z
334
+ D[k + 1] += z
335
+ L[k] = d * c * s + (c * c - s * s) * L[k]
336
+
337
+ if k > start:
338
+ L[k - 1] = c * x - s * y
339
+
340
+ x = L[k]
341
+ y = -s * L[k + 1] # new buldge
342
+ L[k + 1] *= c
343
+
344
+ # apply givens rotation on left of Q
345
+ # note: Q is transposed compared to usual impls, as Warp makes it easier to index rows
346
+ Qk0 = Q[k]
347
+ Qk1 = Q[k + 1]
348
+ Q[k] = c * Qk0 - s * Qk1
349
+ Q[k + 1] = c * Qk1 + s * Qk0
350
+
351
+ if end <= 0:
352
+ # We did nothing, so diagonalization must have been achieved
353
+ break
354
+
355
+ return D, Q
356
+
357
+
358
+ @wp.func
359
+ def symmetric_eigenvalues_qr(A: Any, tol: Any):
360
+ """
361
+ Computes the eigenvalues and eigen vectors of a square symmetric matrix A using the QR algorithm
362
+
363
+ Args:
364
+ A: square symmetric matrix
365
+ tol: Tolerance for the diagonalization residual (Linf norm of off-diagonal over diagonal terms)
366
+
367
+ Returns a tuple (D: vector of eigenvalues, P: matrix with one eigenvector per row) such that A = P^T D P
368
+ """
369
+
370
+ # Put A under Hessenberg form (tridiagonal)
371
+ Q, H = householder_make_hessenberg(A)
372
+
373
+ # tridiagonal storage for H
374
+ D = wp.get_diag(H)
375
+ L = type(D)(A.dtype(0.0))
376
+ for i in range(1, type(D).length):
377
+ L[i - 1] = H[i, i - 1]
378
+
379
+ Qt = wp.transpose(Q)
380
+ ev, P = tridiagonal_symmetric_eigenvalues_qr(D, L, Qt, tol)
381
+ return ev, P
382
+
383
+
384
+ def array_axpy(x: wp.array, y: wp.array, alpha: float = 1.0, beta: float = 1.0):
385
+ """Performs y = alpha*x + beta*y"""
386
+
387
+ dtype = wp.types.type_scalar_type(y.dtype)
388
+
389
+ alpha = dtype(alpha)
390
+ beta = dtype(beta)
391
+
392
+ if x.shape != y.shape or x.device != y.device:
393
+ raise ValueError("x and y arrays must have the same shape and device")
394
+
395
+ # array_axpy requires a custom adjoint; unfortunately we cannot use `wp.func_grad`
396
+ # as generic functions are not supported yet. Instead we use a non-differentiable kernel
397
+ # and record a custom adjoint function on the tape.
398
+
399
+ # temporarily disable tape to avoid printing warning that kernel is not differentiable
400
+ (tape, wp.context.runtime.tape) = (wp.context.runtime.tape, None)
401
+ wp.launch(kernel=_array_axpy_kernel, dim=x.shape, device=x.device, inputs=[x, y, alpha, beta])
402
+ wp.context.runtime.tape = tape
403
+
404
+ if tape is not None and (x.requires_grad or y.requires_grad):
405
+
406
+ def backward_axpy():
407
+ # adj_x += adj_y * alpha
408
+ # adj_y = adj_y * beta
409
+ array_axpy(x=y.grad, y=x.grad, alpha=alpha, beta=1.0)
410
+ if beta != 1.0:
411
+ array_axpy(x=y.grad, y=y.grad, alpha=0.0, beta=beta)
412
+
413
+ tape.record_func(backward_axpy, arrays=[x, y])
414
+
415
+
416
+ @wp.kernel(enable_backward=False)
417
+ def _array_axpy_kernel(x: wp.array(dtype=Any), y: wp.array(dtype=Any), alpha: Any, beta: Any):
418
+ i = wp.tid()
419
+ y[i] = beta * y[i] + alpha * y.dtype(x[i])
warp/fem/operator.py ADDED
@@ -0,0 +1,293 @@
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
+ from typing import Any, Callable, Dict, Optional, Set
17
+
18
+ import warp as wp
19
+ from warp.fem.linalg import skew_part, symmetric_part
20
+ from warp.fem.types import Coords, Domain, ElementIndex, Field, NodeIndex, Sample, make_free_sample
21
+
22
+
23
+ class Integrand:
24
+ """An integrand is a device function containing arbitrary expressions over Field and Domain variables.
25
+ It will get transformed to a proper warp.Function by resolving concrete Field types at call time.
26
+ """
27
+
28
+ def __init__(self, func: Callable, kernel_options: Optional[Dict[str, Any]] = None):
29
+ self.func = func
30
+ self.name = wp.codegen.make_full_qualified_name(self.func)
31
+ self.module = wp.get_module(self.func.__module__)
32
+ self.argspec = wp.codegen.get_full_arg_spec(self.func)
33
+ self.kernel_options = {} if kernel_options is None else kernel_options
34
+
35
+ # Operators for each field argument. This will be populated at first integrate call
36
+ self.operators: Dict[str, Set[Operator]] = None
37
+
38
+
39
+ class Operator:
40
+ """
41
+ Operators provide syntactic sugar over Field and Domain evaluation functions and arguments
42
+ """
43
+
44
+ def __init__(self, func: Callable, resolver: Callable, field_result: Callable = None):
45
+ self.func = func
46
+ self.name = func.__name__
47
+ self.resolver = resolver
48
+ self.field_result = field_result
49
+
50
+
51
+ def integrand(func: Callable = None, kernel_options: Optional[Dict[str, Any]] = None):
52
+ """Decorator for functions to be integrated (or interpolated) using warp.fem
53
+
54
+ Args:
55
+ func: Decorated function
56
+ kernel_options: Supplemental code-generation options to be passed to the generated kernel.
57
+ """
58
+
59
+ if func is not None:
60
+ itg = Integrand(func)
61
+ itg.__doc__ = func.__doc__
62
+ return itg
63
+
64
+ def wrap_integrand(func: Callable):
65
+ itg = Integrand(func, kernel_options)
66
+ itg.__doc__ = func.__doc__
67
+ return itg
68
+
69
+ return wrap_integrand
70
+
71
+
72
+ def operator(**kwargs):
73
+ """Decorator for functions operating on Field-like or Domain-like data inside warp.fem integrands"""
74
+
75
+ def wrap_operator(func: Callable):
76
+ op = Operator(func, **kwargs)
77
+ op.__doc__ = func.__doc__
78
+ return op
79
+
80
+ return wrap_operator
81
+
82
+
83
+ # Domain operators
84
+
85
+
86
+ @operator(resolver=lambda dmn: dmn.element_position)
87
+ def position(domain: Domain, s: Sample):
88
+ """Evaluates the world position of the sample point `s`"""
89
+ pass
90
+
91
+
92
+ @operator(resolver=lambda dmn: dmn.element_normal)
93
+ def normal(domain: Domain, s: Sample):
94
+ """Evaluates the element normal at the sample point `s`. Non zero if the element is a side or the geometry is embedded in a higher-dimensional space (e.g. :class:`Trimesh3D`)"""
95
+ pass
96
+
97
+
98
+ @operator(resolver=lambda dmn: dmn.element_deformation_gradient)
99
+ def deformation_gradient(domain: Domain, s: Sample):
100
+ """Evaluates the gradient of the domain position with respect to the element reference space at the sample point `s`"""
101
+ pass
102
+
103
+
104
+ @operator(resolver=lambda dmn: dmn.element_lookup)
105
+ def lookup(domain: Domain, x: Any) -> Sample:
106
+ """Looks-up the sample point corresponding to a world position `x`, projecting to the closest point on the domain.
107
+
108
+ Args:
109
+ x: world position of the point to look-up in the geometry
110
+ guess: (optional) :class:`Sample` initial guess, may help perform the query
111
+
112
+ Note:
113
+ Currently this operator is unsupported for :class:`Hexmesh`, :class:`Quadmesh2D`, :class:`Quadmesh3D` and deformed geometries.
114
+ """
115
+ pass
116
+
117
+
118
+ @operator(resolver=lambda dmn: dmn.element_measure)
119
+ def measure(domain: Domain, s: Sample) -> float:
120
+ """Returns the measure (volume, area, or length) determinant of an element at a sample point `s`"""
121
+ pass
122
+
123
+
124
+ @operator(resolver=lambda dmn: dmn.element_measure_ratio)
125
+ def measure_ratio(domain: Domain, s: Sample) -> float:
126
+ """Returns the maximum ratio between the measure of this element and that of higher-dimensional neighbors."""
127
+ pass
128
+
129
+
130
+ # Operators for evaluating cell-level quantities on domains defined on sides
131
+
132
+
133
+ @operator(
134
+ resolver=lambda dmn: dmn.domain_cell_arg, field_result=lambda dmn: (dmn.cell_domain(), Domain, dmn.geometry.CellArg)
135
+ )
136
+ def cells(domain: Domain) -> Domain:
137
+ """Converts a domain defined on geometry sides to a domain defined of cells."""
138
+ pass
139
+
140
+
141
+ @operator(resolver=lambda dmn: dmn.element_inner_cell_index)
142
+ def _inner_cell_index(domain: Domain, side_index: ElementIndex, side_coords: Coords) -> Sample:
143
+ pass
144
+
145
+
146
+ @operator(resolver=lambda dmn: dmn.element_outer_cell_index)
147
+ def _outer_cell_index(domain: Domain, side_index: ElementIndex, side_coords: Coords) -> Sample:
148
+ pass
149
+
150
+
151
+ @operator(resolver=lambda dmn: dmn.element_inner_cell_coords)
152
+ def _inner_cell_coords(domain: Domain, side_index: ElementIndex, side_coords: Coords) -> Sample:
153
+ pass
154
+
155
+
156
+ @operator(resolver=lambda dmn: dmn.element_outer_cell_coords)
157
+ def _outer_cell_coords(domain: Domain, side_index: ElementIndex, side_coords: Coords) -> Sample:
158
+ pass
159
+
160
+
161
+ @operator(resolver=lambda dmn: dmn.cell_to_element_coords)
162
+ def _cell_to_element_coords(
163
+ domain: Domain, side_index: ElementIndex, cell_index: ElementIndex, cell_coords: Coords
164
+ ) -> Sample:
165
+ pass
166
+
167
+
168
+ @integrand
169
+ def to_inner_cell(domain: Domain, s: Sample):
170
+ """Converts a :class:`Sample` defined on a side to a sample defined on the side's inner cell"""
171
+ return make_free_sample(
172
+ _inner_cell_index(domain, s.element_index), _inner_cell_coords(domain, s.element_index, s.element_coords)
173
+ )
174
+
175
+
176
+ @integrand
177
+ def to_outer_cell(domain: Domain, s: Sample):
178
+ """Converts a :class:`Sample` defined on a side to a sample defined on the side's outer cell"""
179
+ return make_free_sample(
180
+ _outer_cell_index(domain, s.element_index), _outer_cell_coords(domain, s.element_index, s.element_coords)
181
+ )
182
+
183
+
184
+ @integrand
185
+ def to_cell_side(domain: Domain, cell_s: Sample, side_index: ElementIndex):
186
+ """Converts a :class:`Sample` defined on a cell to a sample defined on one of its side.
187
+ If the result does not lie on the side `side_index`, the resulting coordinates will be set to ``OUTSIDE``."""
188
+ return make_free_sample(
189
+ side_index, _cell_to_element_coords(domain, side_index, cell_s.element_index, cell_s.element_coords)
190
+ )
191
+
192
+
193
+ # Field operators
194
+ # On a side, inner and outer are such that normal goes from inner to outer
195
+
196
+
197
+ @operator(resolver=lambda f: f.eval_inner)
198
+ def inner(f: Field, s: Sample):
199
+ """Evaluates the field at a sample point `s`. On oriented sides, uses the inner element"""
200
+ pass
201
+
202
+
203
+ @operator(resolver=lambda f: f.eval_grad_inner)
204
+ def grad(f: Field, s: Sample):
205
+ """Evaluates the field gradient at a sample point `s`. On oriented sides, uses the inner element"""
206
+ pass
207
+
208
+
209
+ @operator(resolver=lambda f: f.eval_div_inner)
210
+ def div(f: Field, s: Sample):
211
+ """Evaluates the field divergence at a sample point `s`. On oriented sides, uses the inner element"""
212
+ pass
213
+
214
+
215
+ @operator(resolver=lambda f: f.eval_outer)
216
+ def outer(f: Field, s: Sample):
217
+ """Evaluates the field at a sample point `s`. On oriented sides, uses the outer element. On interior points and on domain boundaries, this is equivalent to :func:`inner`."""
218
+ pass
219
+
220
+
221
+ @operator(resolver=lambda f: f.eval_grad_outer)
222
+ def grad_outer(f: Field, s: Sample):
223
+ """Evaluates the field gradient at a sample point `s`. On oriented sides, uses the outer element. On interior points and on domain boundaries, this is equivalent to :func:`grad`."""
224
+ pass
225
+
226
+
227
+ @operator(resolver=lambda f: f.eval_grad_outer)
228
+ def div_outer(f: Field, s: Sample):
229
+ """Evaluates the field divergence at a sample point `s`. On oriented sides, uses the outer element. On interior points and on domain boundaries, this is equivalent to :func:`div`."""
230
+ pass
231
+
232
+
233
+ @operator(resolver=lambda f: f.eval_degree)
234
+ def degree(f: Field):
235
+ """Polynomial degree of a field"""
236
+ pass
237
+
238
+
239
+ @operator(resolver=lambda f: f.at_node)
240
+ def at_node(f: Field, s: Sample):
241
+ """For a Test or Trial field `f`, returns a copy of the Sample `s` moved to the coordinates of the node being evaluated"""
242
+ pass
243
+
244
+
245
+ @operator(resolver=lambda f: f.node_partition_index)
246
+ def node_partition_index(f: Field, node_index: NodeIndex):
247
+ """For a NodalField `f`, returns the index of a given node in the fields's space partition,
248
+ or ``NULL_NODE_INDEX`` if it does not exists"""
249
+ pass
250
+
251
+
252
+ # Common derived operators, for convenience
253
+
254
+
255
+ @integrand
256
+ def D(f: Field, s: Sample):
257
+ """Symmetric part of the (inner) gradient of the field at `s`"""
258
+ return symmetric_part(grad(f, s))
259
+
260
+
261
+ @integrand
262
+ def curl(f: Field, s: Sample):
263
+ """Skew part of the (inner) gradient of the field at `s`, as a vector such that ``wp.cross(curl(u), v) = skew(grad(u)) v``"""
264
+ return skew_part(grad(f, s))
265
+
266
+
267
+ @integrand
268
+ def jump(f: Field, s: Sample):
269
+ """Jump between inner and outer element values on an interior side. Zero for interior points or domain boundaries"""
270
+ return inner(f, s) - outer(f, s)
271
+
272
+
273
+ @integrand
274
+ def average(f: Field, s: Sample):
275
+ """Average between inner and outer element values"""
276
+ return 0.5 * (inner(f, s) + outer(f, s))
277
+
278
+
279
+ @integrand
280
+ def grad_jump(f: Field, s: Sample):
281
+ """Jump between inner and outer element gradients on an interior side. Zero for interior points or domain boundaries"""
282
+ return grad(f, s) - grad_outer(f, s)
283
+
284
+
285
+ @integrand
286
+ def grad_average(f: Field, s: Sample):
287
+ """Average between inner and outer element gradients"""
288
+ return 0.5 * (grad(f, s) + grad_outer(f, s))
289
+
290
+
291
+ # Set default call operators for argument types, so that field(s) = inner(field, s) and domain(s) = position(domain, s)
292
+ Field.call_operator = inner
293
+ Domain.call_operator = position