warp-lang 1.9.0__py3-none-manylinux_2_34_aarch64.whl → 1.10.0__py3-none-manylinux_2_34_aarch64.whl

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

Potentially problematic release.


This version of warp-lang might be problematic. Click here for more details.

Files changed (350) hide show
  1. warp/__init__.py +301 -287
  2. warp/__init__.pyi +2302 -307
  3. warp/_src/__init__.py +14 -0
  4. warp/_src/autograd.py +1077 -0
  5. warp/_src/build.py +620 -0
  6. warp/_src/build_dll.py +642 -0
  7. warp/{builtins.py → _src/builtins.py} +1546 -224
  8. warp/_src/codegen.py +4361 -0
  9. warp/{config.py → _src/config.py} +178 -169
  10. warp/_src/constants.py +59 -0
  11. warp/_src/context.py +8352 -0
  12. warp/_src/dlpack.py +464 -0
  13. warp/_src/fabric.py +362 -0
  14. warp/_src/fem/__init__.py +14 -0
  15. warp/_src/fem/adaptivity.py +510 -0
  16. warp/_src/fem/cache.py +689 -0
  17. warp/_src/fem/dirichlet.py +190 -0
  18. warp/{fem → _src/fem}/domain.py +42 -30
  19. warp/_src/fem/field/__init__.py +131 -0
  20. warp/_src/fem/field/field.py +703 -0
  21. warp/{fem → _src/fem}/field/nodal_field.py +32 -15
  22. warp/{fem → _src/fem}/field/restriction.py +3 -1
  23. warp/{fem → _src/fem}/field/virtual.py +55 -27
  24. warp/_src/fem/geometry/__init__.py +32 -0
  25. warp/{fem → _src/fem}/geometry/adaptive_nanogrid.py +79 -163
  26. warp/_src/fem/geometry/closest_point.py +99 -0
  27. warp/{fem → _src/fem}/geometry/deformed_geometry.py +16 -22
  28. warp/{fem → _src/fem}/geometry/element.py +34 -10
  29. warp/{fem → _src/fem}/geometry/geometry.py +50 -20
  30. warp/{fem → _src/fem}/geometry/grid_2d.py +14 -23
  31. warp/{fem → _src/fem}/geometry/grid_3d.py +14 -23
  32. warp/{fem → _src/fem}/geometry/hexmesh.py +42 -63
  33. warp/{fem → _src/fem}/geometry/nanogrid.py +256 -247
  34. warp/{fem → _src/fem}/geometry/partition.py +123 -63
  35. warp/{fem → _src/fem}/geometry/quadmesh.py +28 -45
  36. warp/{fem → _src/fem}/geometry/tetmesh.py +42 -63
  37. warp/{fem → _src/fem}/geometry/trimesh.py +28 -45
  38. warp/{fem → _src/fem}/integrate.py +166 -158
  39. warp/_src/fem/linalg.py +385 -0
  40. warp/_src/fem/operator.py +398 -0
  41. warp/_src/fem/polynomial.py +231 -0
  42. warp/{fem → _src/fem}/quadrature/pic_quadrature.py +17 -20
  43. warp/{fem → _src/fem}/quadrature/quadrature.py +97 -47
  44. warp/_src/fem/space/__init__.py +248 -0
  45. warp/{fem → _src/fem}/space/basis_function_space.py +22 -11
  46. warp/_src/fem/space/basis_space.py +681 -0
  47. warp/{fem → _src/fem}/space/dof_mapper.py +5 -3
  48. warp/{fem → _src/fem}/space/function_space.py +16 -13
  49. warp/{fem → _src/fem}/space/grid_2d_function_space.py +6 -7
  50. warp/{fem → _src/fem}/space/grid_3d_function_space.py +6 -4
  51. warp/{fem → _src/fem}/space/hexmesh_function_space.py +6 -10
  52. warp/{fem → _src/fem}/space/nanogrid_function_space.py +5 -9
  53. warp/{fem → _src/fem}/space/partition.py +119 -60
  54. warp/{fem → _src/fem}/space/quadmesh_function_space.py +6 -10
  55. warp/{fem → _src/fem}/space/restriction.py +68 -33
  56. warp/_src/fem/space/shape/__init__.py +152 -0
  57. warp/{fem → _src/fem}/space/shape/cube_shape_function.py +11 -9
  58. warp/{fem → _src/fem}/space/shape/shape_function.py +10 -9
  59. warp/{fem → _src/fem}/space/shape/square_shape_function.py +8 -6
  60. warp/{fem → _src/fem}/space/shape/tet_shape_function.py +5 -3
  61. warp/{fem → _src/fem}/space/shape/triangle_shape_function.py +5 -3
  62. warp/{fem → _src/fem}/space/tetmesh_function_space.py +5 -9
  63. warp/_src/fem/space/topology.py +461 -0
  64. warp/{fem → _src/fem}/space/trimesh_function_space.py +5 -9
  65. warp/_src/fem/types.py +114 -0
  66. warp/_src/fem/utils.py +488 -0
  67. warp/_src/jax.py +188 -0
  68. warp/_src/jax_experimental/__init__.py +14 -0
  69. warp/_src/jax_experimental/custom_call.py +389 -0
  70. warp/_src/jax_experimental/ffi.py +1286 -0
  71. warp/_src/jax_experimental/xla_ffi.py +658 -0
  72. warp/_src/marching_cubes.py +710 -0
  73. warp/_src/math.py +416 -0
  74. warp/_src/optim/__init__.py +14 -0
  75. warp/_src/optim/adam.py +165 -0
  76. warp/_src/optim/linear.py +1608 -0
  77. warp/_src/optim/sgd.py +114 -0
  78. warp/_src/paddle.py +408 -0
  79. warp/_src/render/__init__.py +14 -0
  80. warp/_src/render/imgui_manager.py +291 -0
  81. warp/_src/render/render_opengl.py +3638 -0
  82. warp/_src/render/render_usd.py +939 -0
  83. warp/_src/render/utils.py +162 -0
  84. warp/_src/sparse.py +2718 -0
  85. warp/_src/tape.py +1208 -0
  86. warp/{thirdparty → _src/thirdparty}/unittest_parallel.py +9 -2
  87. warp/_src/torch.py +393 -0
  88. warp/_src/types.py +5888 -0
  89. warp/_src/utils.py +1695 -0
  90. warp/autograd.py +12 -1054
  91. warp/bin/warp-clang.so +0 -0
  92. warp/bin/warp.so +0 -0
  93. warp/build.py +8 -588
  94. warp/build_dll.py +6 -471
  95. warp/codegen.py +6 -4246
  96. warp/constants.py +6 -39
  97. warp/context.py +12 -7851
  98. warp/dlpack.py +6 -444
  99. warp/examples/distributed/example_jacobi_mpi.py +4 -5
  100. warp/examples/fem/example_adaptive_grid.py +1 -1
  101. warp/examples/fem/example_apic_fluid.py +1 -1
  102. warp/examples/fem/example_burgers.py +8 -8
  103. warp/examples/fem/example_diffusion.py +1 -1
  104. warp/examples/fem/example_distortion_energy.py +1 -1
  105. warp/examples/fem/example_mixed_elasticity.py +2 -2
  106. warp/examples/fem/example_navier_stokes.py +1 -1
  107. warp/examples/fem/example_nonconforming_contact.py +7 -7
  108. warp/examples/fem/example_stokes.py +1 -1
  109. warp/examples/fem/example_stokes_transfer.py +1 -1
  110. warp/examples/fem/utils.py +2 -2
  111. warp/examples/interop/example_jax_callable.py +1 -1
  112. warp/examples/interop/example_jax_ffi_callback.py +1 -1
  113. warp/examples/interop/example_jax_kernel.py +3 -2
  114. warp/examples/tile/example_tile_mcgp.py +191 -0
  115. warp/fabric.py +6 -337
  116. warp/fem/__init__.py +159 -97
  117. warp/fem/adaptivity.py +7 -489
  118. warp/fem/cache.py +9 -648
  119. warp/fem/dirichlet.py +6 -184
  120. warp/fem/field/__init__.py +8 -109
  121. warp/fem/field/field.py +7 -652
  122. warp/fem/geometry/__init__.py +7 -18
  123. warp/fem/geometry/closest_point.py +11 -77
  124. warp/fem/linalg.py +18 -366
  125. warp/fem/operator.py +11 -369
  126. warp/fem/polynomial.py +9 -209
  127. warp/fem/space/__init__.py +5 -211
  128. warp/fem/space/basis_space.py +6 -662
  129. warp/fem/space/shape/__init__.py +41 -118
  130. warp/fem/space/topology.py +6 -437
  131. warp/fem/types.py +6 -81
  132. warp/fem/utils.py +11 -444
  133. warp/jax.py +8 -165
  134. warp/jax_experimental/__init__.py +14 -1
  135. warp/jax_experimental/custom_call.py +8 -342
  136. warp/jax_experimental/ffi.py +17 -853
  137. warp/jax_experimental/xla_ffi.py +5 -596
  138. warp/marching_cubes.py +5 -689
  139. warp/math.py +16 -393
  140. warp/native/array.h +385 -37
  141. warp/native/builtin.h +316 -39
  142. warp/native/bvh.cpp +43 -9
  143. warp/native/bvh.cu +62 -27
  144. warp/native/bvh.h +310 -309
  145. warp/native/clang/clang.cpp +102 -97
  146. warp/native/coloring.cpp +0 -1
  147. warp/native/crt.h +208 -0
  148. warp/native/exports.h +156 -0
  149. warp/native/hashgrid.cu +2 -0
  150. warp/native/intersect.h +24 -1
  151. warp/native/intersect_tri.h +44 -35
  152. warp/native/mat.h +1456 -276
  153. warp/native/mesh.cpp +4 -4
  154. warp/native/mesh.cu +4 -2
  155. warp/native/mesh.h +176 -61
  156. warp/native/quat.h +0 -52
  157. warp/native/scan.cu +2 -0
  158. warp/native/sort.cu +22 -13
  159. warp/native/sort.h +2 -0
  160. warp/native/sparse.cu +7 -3
  161. warp/native/spatial.h +12 -0
  162. warp/native/tile.h +837 -70
  163. warp/native/tile_radix_sort.h +3 -3
  164. warp/native/tile_reduce.h +394 -46
  165. warp/native/tile_scan.h +4 -4
  166. warp/native/vec.h +469 -53
  167. warp/native/version.h +23 -0
  168. warp/native/volume.cpp +1 -1
  169. warp/native/volume.cu +1 -0
  170. warp/native/volume.h +1 -1
  171. warp/native/volume_builder.cu +2 -0
  172. warp/native/warp.cpp +60 -32
  173. warp/native/warp.cu +581 -280
  174. warp/native/warp.h +14 -11
  175. warp/optim/__init__.py +6 -3
  176. warp/optim/adam.py +6 -145
  177. warp/optim/linear.py +14 -1585
  178. warp/optim/sgd.py +6 -94
  179. warp/paddle.py +6 -388
  180. warp/render/__init__.py +8 -4
  181. warp/render/imgui_manager.py +7 -267
  182. warp/render/render_opengl.py +6 -3616
  183. warp/render/render_usd.py +6 -918
  184. warp/render/utils.py +6 -142
  185. warp/sparse.py +37 -2563
  186. warp/tape.py +6 -1188
  187. warp/tests/__main__.py +1 -1
  188. warp/tests/cuda/test_async.py +4 -4
  189. warp/tests/cuda/test_conditional_captures.py +1 -1
  190. warp/tests/cuda/test_multigpu.py +1 -1
  191. warp/tests/cuda/test_streams.py +58 -1
  192. warp/tests/geometry/test_bvh.py +157 -22
  193. warp/tests/geometry/test_hash_grid.py +38 -0
  194. warp/tests/geometry/test_marching_cubes.py +0 -1
  195. warp/tests/geometry/test_mesh.py +5 -3
  196. warp/tests/geometry/test_mesh_query_aabb.py +5 -12
  197. warp/tests/geometry/test_mesh_query_point.py +5 -2
  198. warp/tests/geometry/test_mesh_query_ray.py +15 -3
  199. warp/tests/geometry/test_volume_write.py +5 -5
  200. warp/tests/interop/test_dlpack.py +18 -17
  201. warp/tests/interop/test_jax.py +1382 -79
  202. warp/tests/interop/test_paddle.py +1 -1
  203. warp/tests/test_adam.py +0 -1
  204. warp/tests/test_arithmetic.py +9 -9
  205. warp/tests/test_array.py +580 -100
  206. warp/tests/test_array_reduce.py +3 -3
  207. warp/tests/test_atomic.py +12 -8
  208. warp/tests/test_atomic_bitwise.py +209 -0
  209. warp/tests/test_atomic_cas.py +4 -4
  210. warp/tests/test_bool.py +2 -2
  211. warp/tests/test_builtins_resolution.py +5 -571
  212. warp/tests/test_codegen.py +34 -15
  213. warp/tests/test_conditional.py +1 -1
  214. warp/tests/test_context.py +6 -6
  215. warp/tests/test_copy.py +242 -161
  216. warp/tests/test_ctypes.py +3 -3
  217. warp/tests/test_devices.py +24 -2
  218. warp/tests/test_examples.py +16 -84
  219. warp/tests/test_fabricarray.py +35 -35
  220. warp/tests/test_fast_math.py +0 -2
  221. warp/tests/test_fem.py +60 -14
  222. warp/tests/test_fixedarray.py +3 -3
  223. warp/tests/test_func.py +8 -5
  224. warp/tests/test_generics.py +1 -1
  225. warp/tests/test_indexedarray.py +24 -24
  226. warp/tests/test_intersect.py +39 -9
  227. warp/tests/test_large.py +1 -1
  228. warp/tests/test_lerp.py +3 -1
  229. warp/tests/test_linear_solvers.py +1 -1
  230. warp/tests/test_map.py +49 -4
  231. warp/tests/test_mat.py +52 -62
  232. warp/tests/test_mat_constructors.py +4 -5
  233. warp/tests/test_mat_lite.py +1 -1
  234. warp/tests/test_mat_scalar_ops.py +121 -121
  235. warp/tests/test_math.py +34 -0
  236. warp/tests/test_module_aot.py +4 -4
  237. warp/tests/test_modules_lite.py +28 -2
  238. warp/tests/test_print.py +11 -11
  239. warp/tests/test_quat.py +93 -58
  240. warp/tests/test_runlength_encode.py +1 -1
  241. warp/tests/test_scalar_ops.py +38 -10
  242. warp/tests/test_smoothstep.py +1 -1
  243. warp/tests/test_sparse.py +126 -15
  244. warp/tests/test_spatial.py +105 -87
  245. warp/tests/test_special_values.py +6 -6
  246. warp/tests/test_static.py +7 -7
  247. warp/tests/test_struct.py +13 -2
  248. warp/tests/test_triangle_closest_point.py +48 -1
  249. warp/tests/test_tuple.py +96 -0
  250. warp/tests/test_types.py +82 -9
  251. warp/tests/test_utils.py +52 -52
  252. warp/tests/test_vec.py +29 -29
  253. warp/tests/test_vec_constructors.py +5 -5
  254. warp/tests/test_vec_scalar_ops.py +97 -97
  255. warp/tests/test_version.py +75 -0
  256. warp/tests/tile/test_tile.py +239 -0
  257. warp/tests/tile/test_tile_atomic_bitwise.py +403 -0
  258. warp/tests/tile/test_tile_cholesky.py +7 -4
  259. warp/tests/tile/test_tile_load.py +26 -2
  260. warp/tests/tile/test_tile_mathdx.py +3 -3
  261. warp/tests/tile/test_tile_matmul.py +1 -1
  262. warp/tests/tile/test_tile_mlp.py +2 -4
  263. warp/tests/tile/test_tile_reduce.py +214 -13
  264. warp/tests/unittest_suites.py +6 -14
  265. warp/tests/unittest_utils.py +10 -9
  266. warp/tests/walkthrough_debug.py +3 -1
  267. warp/torch.py +6 -373
  268. warp/types.py +29 -5750
  269. warp/utils.py +10 -1659
  270. {warp_lang-1.9.0.dist-info → warp_lang-1.10.0.dist-info}/METADATA +47 -103
  271. warp_lang-1.10.0.dist-info/RECORD +468 -0
  272. warp_lang-1.10.0.dist-info/licenses/licenses/Gaia-LICENSE.txt +6 -0
  273. warp_lang-1.10.0.dist-info/licenses/licenses/appdirs-LICENSE.txt +22 -0
  274. warp_lang-1.10.0.dist-info/licenses/licenses/asset_pixel_jpg-LICENSE.txt +3 -0
  275. warp_lang-1.10.0.dist-info/licenses/licenses/cuda-LICENSE.txt +1582 -0
  276. warp_lang-1.10.0.dist-info/licenses/licenses/dlpack-LICENSE.txt +201 -0
  277. warp_lang-1.10.0.dist-info/licenses/licenses/fp16-LICENSE.txt +28 -0
  278. warp_lang-1.10.0.dist-info/licenses/licenses/libmathdx-LICENSE.txt +220 -0
  279. warp_lang-1.10.0.dist-info/licenses/licenses/llvm-LICENSE.txt +279 -0
  280. warp_lang-1.10.0.dist-info/licenses/licenses/moller-LICENSE.txt +16 -0
  281. warp_lang-1.10.0.dist-info/licenses/licenses/nanovdb-LICENSE.txt +2 -0
  282. warp_lang-1.10.0.dist-info/licenses/licenses/nvrtc-LICENSE.txt +1592 -0
  283. warp_lang-1.10.0.dist-info/licenses/licenses/svd-LICENSE.txt +23 -0
  284. warp_lang-1.10.0.dist-info/licenses/licenses/unittest_parallel-LICENSE.txt +21 -0
  285. warp_lang-1.10.0.dist-info/licenses/licenses/usd-LICENSE.txt +213 -0
  286. warp_lang-1.10.0.dist-info/licenses/licenses/windingnumber-LICENSE.txt +21 -0
  287. warp/examples/assets/cartpole.urdf +0 -110
  288. warp/examples/assets/crazyflie.usd +0 -0
  289. warp/examples/assets/nv_ant.xml +0 -92
  290. warp/examples/assets/nv_humanoid.xml +0 -183
  291. warp/examples/assets/quadruped.urdf +0 -268
  292. warp/examples/optim/example_bounce.py +0 -266
  293. warp/examples/optim/example_cloth_throw.py +0 -228
  294. warp/examples/optim/example_drone.py +0 -870
  295. warp/examples/optim/example_inverse_kinematics.py +0 -182
  296. warp/examples/optim/example_inverse_kinematics_torch.py +0 -191
  297. warp/examples/optim/example_softbody_properties.py +0 -400
  298. warp/examples/optim/example_spring_cage.py +0 -245
  299. warp/examples/optim/example_trajectory.py +0 -227
  300. warp/examples/sim/example_cartpole.py +0 -143
  301. warp/examples/sim/example_cloth.py +0 -225
  302. warp/examples/sim/example_cloth_self_contact.py +0 -316
  303. warp/examples/sim/example_granular.py +0 -130
  304. warp/examples/sim/example_granular_collision_sdf.py +0 -202
  305. warp/examples/sim/example_jacobian_ik.py +0 -244
  306. warp/examples/sim/example_particle_chain.py +0 -124
  307. warp/examples/sim/example_quadruped.py +0 -203
  308. warp/examples/sim/example_rigid_chain.py +0 -203
  309. warp/examples/sim/example_rigid_contact.py +0 -195
  310. warp/examples/sim/example_rigid_force.py +0 -133
  311. warp/examples/sim/example_rigid_gyroscopic.py +0 -115
  312. warp/examples/sim/example_rigid_soft_contact.py +0 -140
  313. warp/examples/sim/example_soft_body.py +0 -196
  314. warp/examples/tile/example_tile_walker.py +0 -327
  315. warp/sim/__init__.py +0 -74
  316. warp/sim/articulation.py +0 -793
  317. warp/sim/collide.py +0 -2570
  318. warp/sim/graph_coloring.py +0 -307
  319. warp/sim/import_mjcf.py +0 -791
  320. warp/sim/import_snu.py +0 -227
  321. warp/sim/import_urdf.py +0 -579
  322. warp/sim/import_usd.py +0 -898
  323. warp/sim/inertia.py +0 -357
  324. warp/sim/integrator.py +0 -245
  325. warp/sim/integrator_euler.py +0 -2000
  326. warp/sim/integrator_featherstone.py +0 -2101
  327. warp/sim/integrator_vbd.py +0 -2487
  328. warp/sim/integrator_xpbd.py +0 -3295
  329. warp/sim/model.py +0 -4821
  330. warp/sim/particles.py +0 -121
  331. warp/sim/render.py +0 -431
  332. warp/sim/utils.py +0 -431
  333. warp/tests/sim/disabled_kinematics.py +0 -244
  334. warp/tests/sim/test_cloth.py +0 -863
  335. warp/tests/sim/test_collision.py +0 -743
  336. warp/tests/sim/test_coloring.py +0 -347
  337. warp/tests/sim/test_inertia.py +0 -161
  338. warp/tests/sim/test_model.py +0 -226
  339. warp/tests/sim/test_sim_grad.py +0 -287
  340. warp/tests/sim/test_sim_grad_bounce_linear.py +0 -212
  341. warp/tests/sim/test_sim_kinematics.py +0 -98
  342. warp/thirdparty/__init__.py +0 -0
  343. warp_lang-1.9.0.dist-info/RECORD +0 -456
  344. /warp/{fem → _src/fem}/quadrature/__init__.py +0 -0
  345. /warp/{tests/sim → _src/thirdparty}/__init__.py +0 -0
  346. /warp/{thirdparty → _src/thirdparty}/appdirs.py +0 -0
  347. /warp/{thirdparty → _src/thirdparty}/dlpack.py +0 -0
  348. {warp_lang-1.9.0.dist-info → warp_lang-1.10.0.dist-info}/WHEEL +0 -0
  349. {warp_lang-1.9.0.dist-info → warp_lang-1.10.0.dist-info}/licenses/LICENSE.md +0 -0
  350. {warp_lang-1.9.0.dist-info → warp_lang-1.10.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,461 @@
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 functools import cached_property
17
+ from typing import ClassVar, Optional, Tuple, Type
18
+
19
+ import warp as wp
20
+ from warp._src.fem import cache
21
+ from warp._src.fem.geometry import DeformedGeometry, Geometry
22
+ from warp._src.fem.types import NULL_ELEMENT_INDEX, NULL_NODE_INDEX, ElementIndex
23
+
24
+ _wp_module_name_ = "warp.fem.space.topology"
25
+
26
+
27
+ class SpaceTopology:
28
+ """
29
+ Interface class for defining the topology of a function space.
30
+
31
+ The topology only considers the indices of the nodes in each element, and as such,
32
+ the connectivity pattern of the function space.
33
+ It does not specify the actual location of the nodes within the elements, or the valuation function.
34
+ """
35
+
36
+ dimension: int
37
+ """Embedding dimension of the function space"""
38
+
39
+ MAX_NODES_PER_ELEMENT: int
40
+ """maximum number of interpolation nodes per element of the geometry.
41
+
42
+ .. note:: This will change to be defined per-element in future versions
43
+ """
44
+
45
+ _dynamic_attribute_constructors: ClassVar = {
46
+ "element_node_count": lambda obj: obj._make_constant_element_node_count(),
47
+ "element_node_sign": lambda obj: obj._make_constant_element_node_sign(),
48
+ "side_neighbor_node_counts": lambda obj: obj._make_constant_side_neighbor_node_counts(),
49
+ }
50
+
51
+ @wp.struct
52
+ class TopologyArg:
53
+ """Structure containing arguments to be passed to device functions"""
54
+
55
+ pass
56
+
57
+ def __init__(self, geometry: Geometry, max_nodes_per_element: int):
58
+ self._geometry = geometry
59
+ self.dimension = geometry.dimension
60
+ self.MAX_NODES_PER_ELEMENT = wp.constant(max_nodes_per_element)
61
+ self.ElementArg = geometry.CellArg
62
+
63
+ cache.setup_dynamic_attributes(self, cls=__class__)
64
+
65
+ @property
66
+ def geometry(self) -> Geometry:
67
+ """Underlying geometry"""
68
+ return self._geometry
69
+
70
+ def node_count(self) -> int:
71
+ """Number of nodes in the interpolation basis"""
72
+ raise NotImplementedError
73
+
74
+ @cache.cached_arg_value
75
+ def topo_arg_value(self, device) -> "TopologyArg":
76
+ """Value of the topology argument structure to be passed to device functions"""
77
+ arg = self.TopologyArg()
78
+ self.fill_topo_arg(arg, device)
79
+ return arg
80
+
81
+ def fill_topo_arg(self, arg, device):
82
+ pass
83
+
84
+ @cached_property
85
+ def name(self):
86
+ return f"{self.__class__.__name__}_{self.MAX_NODES_PER_ELEMENT}"
87
+
88
+ def __str__(self):
89
+ return self.name
90
+
91
+ @staticmethod
92
+ def element_node_count(
93
+ geo_arg: "ElementArg", # noqa: F821
94
+ topo_arg: "TopologyArg",
95
+ element_index: ElementIndex,
96
+ ) -> int:
97
+ """Returns the actual number of nodes in a given element"""
98
+ raise NotImplementedError
99
+
100
+ @staticmethod
101
+ def element_node_index(
102
+ geo_arg: "ElementArg", # noqa: F821
103
+ topo_arg: "TopologyArg",
104
+ element_index: ElementIndex,
105
+ node_index_in_elt: int,
106
+ ) -> int:
107
+ """Global node index for a given node in a given element"""
108
+ raise NotImplementedError
109
+
110
+ @staticmethod
111
+ def side_neighbor_node_counts(
112
+ side_arg: "ElementArg", # noqa: F821
113
+ side_index: ElementIndex,
114
+ ) -> Tuple[int, int]:
115
+ """Returns the number of nodes for both the inner and outer cells of a given sides"""
116
+ raise NotImplementedError
117
+
118
+ def element_node_indices(self, out: Optional[wp.array] = None) -> wp.array:
119
+ """Returns a temporary array containing the global index for each node of each element"""
120
+
121
+ MAX_NODES_PER_ELEMENT = self.MAX_NODES_PER_ELEMENT
122
+
123
+ @cache.dynamic_kernel(suffix=self.name)
124
+ def fill_element_node_indices(
125
+ geo_cell_arg: self.geometry.CellArg,
126
+ topo_arg: self.TopologyArg,
127
+ element_node_indices: wp.array2d(dtype=int),
128
+ ):
129
+ element_index = wp.tid()
130
+ element_node_count = self.element_node_count(geo_cell_arg, topo_arg, element_index)
131
+ for n in range(element_node_count):
132
+ element_node_indices[element_index, n] = self.element_node_index(
133
+ geo_cell_arg, topo_arg, element_index, n
134
+ )
135
+
136
+ shape = (self.geometry.cell_count(), MAX_NODES_PER_ELEMENT)
137
+ if out is None:
138
+ element_node_indices = wp.empty(
139
+ shape=shape,
140
+ dtype=int,
141
+ )
142
+ else:
143
+ if out.shape != shape or out.dtype != wp.int32:
144
+ raise ValueError(f"Out element node indices array must have shape {shape} and data type 'int32'")
145
+ element_node_indices = out
146
+
147
+ wp.launch(
148
+ dim=element_node_indices.shape[0],
149
+ kernel=fill_element_node_indices,
150
+ inputs=[
151
+ self.geometry.cell_arg_value(device=element_node_indices.device),
152
+ self.topo_arg_value(device=element_node_indices.device),
153
+ element_node_indices,
154
+ ],
155
+ device=element_node_indices.device,
156
+ )
157
+
158
+ return element_node_indices
159
+
160
+ # Interface generating trace space topology
161
+
162
+ def trace(self) -> "TraceSpaceTopology":
163
+ """Trace of the function space over lower-dimensional elements of the geometry"""
164
+
165
+ return TraceSpaceTopology(self)
166
+
167
+ @property
168
+ def is_trace(self) -> bool:
169
+ """Whether this topology is defined on the trace of the geometry"""
170
+ return self.dimension == self.geometry.dimension - 1
171
+
172
+ def full_space_topology(self) -> "SpaceTopology":
173
+ """Returns the full space topology from which this topology is derived"""
174
+ return self
175
+
176
+ def __eq__(self, other: "SpaceTopology") -> bool:
177
+ """Checks whether two topologies are compatible"""
178
+ return self.geometry == other.geometry and self.name == other.name
179
+
180
+ def is_derived_from(self, other: "SpaceTopology") -> bool:
181
+ """Checks whether two topologies are equal, or `self` is the trace of `other`"""
182
+ if self.dimension == other.dimension:
183
+ return self == other
184
+ if self.dimension + 1 == other.dimension:
185
+ return self.full_space_topology() == other
186
+ return False
187
+
188
+ def _make_constant_element_node_count(self):
189
+ NODES_PER_ELEMENT = wp.constant(self.MAX_NODES_PER_ELEMENT)
190
+
191
+ @cache.dynamic_func(suffix=self.name)
192
+ def constant_element_node_count(
193
+ geo_arg: self.geometry.CellArg,
194
+ topo_arg: self.TopologyArg,
195
+ element_index: ElementIndex,
196
+ ):
197
+ return NODES_PER_ELEMENT
198
+
199
+ return constant_element_node_count
200
+
201
+ def _make_constant_side_neighbor_node_counts(self):
202
+ NODES_PER_ELEMENT = wp.constant(self.MAX_NODES_PER_ELEMENT)
203
+
204
+ @cache.dynamic_func(suffix=self.name)
205
+ def constant_side_neighbor_node_counts(
206
+ side_arg: self.geometry.SideArg,
207
+ element_index: ElementIndex,
208
+ ):
209
+ return NODES_PER_ELEMENT, NODES_PER_ELEMENT
210
+
211
+ return constant_side_neighbor_node_counts
212
+
213
+ def _make_constant_element_node_sign(self):
214
+ @cache.dynamic_func(suffix=self.name)
215
+ def constant_element_node_sign(
216
+ geo_arg: self.geometry.CellArg,
217
+ topo_arg: self.TopologyArg,
218
+ element_index: ElementIndex,
219
+ node_index_in_element: int,
220
+ ):
221
+ return 1.0
222
+
223
+ return constant_element_node_sign
224
+
225
+
226
+ class TraceSpaceTopology(SpaceTopology):
227
+ """Auto-generated trace topology defining the node indices associated to the geometry sides"""
228
+
229
+ _dynamic_attribute_constructors: ClassVar = {
230
+ "inner_cell_index": lambda obj: obj._make_inner_cell_index(),
231
+ "outer_cell_index": lambda obj: obj._make_outer_cell_index(),
232
+ "neighbor_cell_index": lambda obj: obj._make_neighbor_cell_index(),
233
+ "element_node_index": lambda obj: obj._make_element_node_index(),
234
+ "element_node_count": lambda obj: obj._make_element_node_count(),
235
+ "element_node_sign": lambda obj: obj._make_element_node_sign(),
236
+ }
237
+
238
+ def __init__(self, topo: SpaceTopology):
239
+ self._topo = topo
240
+
241
+ super().__init__(topo.geometry, 2 * topo.MAX_NODES_PER_ELEMENT)
242
+
243
+ self.dimension = topo.dimension - 1
244
+ self.ElementArg = topo.geometry.SideArg
245
+
246
+ self.TopologyArg = topo.TopologyArg
247
+ self.topo_arg_value = topo.topo_arg_value
248
+ self.fill_topo_arg = topo.fill_topo_arg
249
+
250
+ self.side_neighbor_node_counts = None
251
+ cache.setup_dynamic_attributes(self, cls=__class__)
252
+
253
+ def node_count(self) -> int:
254
+ return self._topo.node_count()
255
+
256
+ @cached_property
257
+ def name(self):
258
+ return f"{self._topo.name}_Trace"
259
+
260
+ def _make_inner_cell_index(self):
261
+ @cache.dynamic_func(suffix=self.name)
262
+ def inner_cell_index(side_arg: self.geometry.SideArg, element_index: ElementIndex, node_index_in_elt: int):
263
+ inner_count, outer_count = self._topo.side_neighbor_node_counts(side_arg, element_index)
264
+ if node_index_in_elt >= inner_count:
265
+ return NULL_ELEMENT_INDEX, NULL_NODE_INDEX
266
+ return self.geometry.side_inner_cell_index(side_arg, element_index), node_index_in_elt
267
+
268
+ return inner_cell_index
269
+
270
+ def _make_outer_cell_index(self):
271
+ @cache.dynamic_func(suffix=self.name)
272
+ def outer_cell_index(side_arg: self.geometry.SideArg, element_index: ElementIndex, node_index_in_elt: int):
273
+ inner_count, outer_count = self._topo.side_neighbor_node_counts(side_arg, element_index)
274
+ if node_index_in_elt < inner_count:
275
+ return NULL_ELEMENT_INDEX, NULL_NODE_INDEX
276
+ return self.geometry.side_outer_cell_index(side_arg, element_index), node_index_in_elt - inner_count
277
+
278
+ return outer_cell_index
279
+
280
+ def _make_neighbor_cell_index(self):
281
+ @cache.dynamic_func(suffix=self.name)
282
+ def neighbor_cell_index(side_arg: self.geometry.SideArg, element_index: ElementIndex, node_index_in_elt: int):
283
+ inner_count, outer_count = self._topo.side_neighbor_node_counts(side_arg, element_index)
284
+ if node_index_in_elt < inner_count:
285
+ return self.geometry.side_inner_cell_index(side_arg, element_index), node_index_in_elt
286
+
287
+ return (
288
+ self.geometry.side_outer_cell_index(side_arg, element_index),
289
+ node_index_in_elt - inner_count,
290
+ )
291
+
292
+ return neighbor_cell_index
293
+
294
+ def _make_element_node_count(self):
295
+ @cache.dynamic_func(suffix=self.name)
296
+ def trace_element_node_count(
297
+ geo_side_arg: self.geometry.SideArg,
298
+ topo_arg: self._topo.TopologyArg,
299
+ element_index: ElementIndex,
300
+ ):
301
+ inner_count, outer_count = self._topo.side_neighbor_node_counts(geo_side_arg, element_index)
302
+ return inner_count + outer_count
303
+
304
+ return trace_element_node_count
305
+
306
+ def _make_element_node_index(self):
307
+ @cache.dynamic_func(suffix=self.name)
308
+ def trace_element_node_index(
309
+ geo_side_arg: self.geometry.SideArg,
310
+ topo_arg: self._topo.TopologyArg,
311
+ element_index: ElementIndex,
312
+ node_index_in_elt: int,
313
+ ):
314
+ cell_index, index_in_cell = self.neighbor_cell_index(geo_side_arg, element_index, node_index_in_elt)
315
+
316
+ geo_cell_arg = self.geometry.side_to_cell_arg(geo_side_arg)
317
+ return self._topo.element_node_index(geo_cell_arg, topo_arg, cell_index, index_in_cell)
318
+
319
+ return trace_element_node_index
320
+
321
+ def _make_element_node_sign(self):
322
+ @cache.dynamic_func(suffix=self.name)
323
+ def trace_element_node_sign(
324
+ geo_side_arg: self.geometry.SideArg,
325
+ topo_arg: self._topo.TopologyArg,
326
+ element_index: ElementIndex,
327
+ node_index_in_elt: int,
328
+ ):
329
+ cell_index, index_in_cell = self.neighbor_cell_index(geo_side_arg, element_index, node_index_in_elt)
330
+
331
+ geo_cell_arg = self.geometry.side_to_cell_arg(geo_side_arg)
332
+ return self._topo.element_node_sign(geo_cell_arg, topo_arg, cell_index, index_in_cell)
333
+
334
+ return trace_element_node_sign
335
+
336
+ def full_space_topology(self) -> SpaceTopology:
337
+ """Returns the full space topology from which this topology is derived"""
338
+ return self._topo
339
+
340
+ def __eq__(self, other: "TraceSpaceTopology") -> bool:
341
+ return self._topo == other._topo
342
+
343
+
344
+ class RegularDiscontinuousSpaceTopologyMixin:
345
+ """Helper for defining discontinuous topologies (per-element nodes)"""
346
+
347
+ def __init__(self, *args, **kwargs):
348
+ super().__init__(*args, **kwargs)
349
+ self.element_node_index = self._make_element_node_index()
350
+
351
+ def node_count(self):
352
+ return self.geometry.cell_count() * self.MAX_NODES_PER_ELEMENT
353
+
354
+ @cached_property
355
+ def name(self):
356
+ return f"{self.geometry.name}_D{self.MAX_NODES_PER_ELEMENT}"
357
+
358
+ def _make_element_node_index(self):
359
+ NODES_PER_ELEMENT = self.MAX_NODES_PER_ELEMENT
360
+
361
+ @cache.dynamic_func(suffix=self.name)
362
+ def element_node_index(
363
+ elt_arg: self.geometry.CellArg,
364
+ topo_arg: self.TopologyArg,
365
+ element_index: ElementIndex,
366
+ node_index_in_elt: int,
367
+ ):
368
+ return NODES_PER_ELEMENT * element_index + node_index_in_elt
369
+
370
+ return element_node_index
371
+
372
+
373
+ class RegularDiscontinuousSpaceTopology(RegularDiscontinuousSpaceTopologyMixin, SpaceTopology):
374
+ """Topology for generic discontinuous spaces"""
375
+
376
+ pass
377
+
378
+
379
+ class DeformedGeometrySpaceTopology(SpaceTopology):
380
+ _dynamic_attribute_constructors: ClassVar = {
381
+ "element_node_index": lambda obj: obj._make_element_node_index(),
382
+ "element_node_count": lambda obj: obj._make_element_node_count(),
383
+ "element_node_sign": lambda obj: obj._make_element_node_sign(),
384
+ "side_neighbor_node_counts": lambda obj: obj._make_side_neighbor_node_counts(),
385
+ }
386
+
387
+ def __init__(self, geometry: DeformedGeometry, base_topology: SpaceTopology):
388
+ self.base = base_topology
389
+ super().__init__(geometry, base_topology.MAX_NODES_PER_ELEMENT)
390
+
391
+ self.node_count = self.base.node_count
392
+ self.topo_arg_value = self.base.topo_arg_value
393
+ self.fill_topo_arg = self.base.fill_topo_arg
394
+ self.TopologyArg = self.base.TopologyArg
395
+
396
+ cache.setup_dynamic_attributes(self, cls=__class__)
397
+
398
+ @cached_property
399
+ def name(self):
400
+ return f"{self.base.name}_{self.geometry.field.name}"
401
+
402
+ def _make_element_node_index(self):
403
+ @cache.dynamic_func(suffix=self.name)
404
+ def element_node_index(
405
+ elt_arg: self.geometry.CellArg,
406
+ topo_arg: self.TopologyArg,
407
+ element_index: ElementIndex,
408
+ node_index_in_elt: int,
409
+ ):
410
+ return self.base.element_node_index(elt_arg.base_arg, topo_arg, element_index, node_index_in_elt)
411
+
412
+ return element_node_index
413
+
414
+ def _make_element_node_count(self):
415
+ @cache.dynamic_func(suffix=self.name)
416
+ def element_node_count(
417
+ elt_arg: self.geometry.CellArg,
418
+ topo_arg: self.TopologyArg,
419
+ element_count: ElementIndex,
420
+ ):
421
+ return self.base.element_node_count(elt_arg.base_arg, topo_arg, element_count)
422
+
423
+ return element_node_count
424
+
425
+ def _make_side_neighbor_node_counts(self):
426
+ @cache.dynamic_func(suffix=self.name)
427
+ def side_neighbor_node_counts(
428
+ side_arg: self.geometry.SideArg,
429
+ element_index: ElementIndex,
430
+ ):
431
+ inner_count, outer_count = self.base.side_neighbor_node_counts(side_arg.base_arg, element_index)
432
+ return inner_count, outer_count
433
+
434
+ return side_neighbor_node_counts
435
+
436
+ def _make_element_node_sign(self):
437
+ @cache.dynamic_func(suffix=self.name)
438
+ def element_node_sign(
439
+ elt_arg: self.geometry.CellArg,
440
+ topo_arg: self.TopologyArg,
441
+ element_index: ElementIndex,
442
+ node_index_in_elt: int,
443
+ ):
444
+ return self.base.element_node_sign(elt_arg.base_arg, topo_arg, element_index, node_index_in_elt)
445
+
446
+ return element_node_sign
447
+
448
+
449
+ def forward_base_topology(topology_class: Type[SpaceTopology], geometry: Geometry, *args, **kwargs) -> SpaceTopology:
450
+ """
451
+ If `geometry` is *not* a :class:`DeformedGeometry`, constructs a normal instance of `topology_class` over `geometry`, forwarding additional arguments.
452
+
453
+ If `geometry` *is* a :class:`DeformedGeometry`, constructs an instance of `topology_class` over the base (undeformed) geometry of `geometry`, then warp it
454
+ in a :class:`DeformedGeometrySpaceTopology` forwarding the calls to the underlying topology.
455
+ """
456
+
457
+ if isinstance(geometry, DeformedGeometry):
458
+ base_topo = topology_class(geometry.base, *args, **kwargs)
459
+ return DeformedGeometrySpaceTopology(geometry, base_topo)
460
+
461
+ return topology_class(geometry, *args, **kwargs)
@@ -14,13 +14,15 @@
14
14
  # limitations under the License.
15
15
 
16
16
  import warp as wp
17
- from warp.fem import cache
18
- from warp.fem.geometry import Trimesh
19
- from warp.fem.types import ElementIndex
17
+ from warp._src.fem import cache
18
+ from warp._src.fem.geometry import Trimesh
19
+ from warp._src.fem.types import ElementIndex
20
20
 
21
21
  from .shape import TriangleShapeFunction
22
22
  from .topology import SpaceTopology, forward_base_topology
23
23
 
24
+ _wp_module_name_ = "warp.fem.space.trimesh_function_space"
25
+
24
26
 
25
27
  @wp.struct
26
28
  class TrimeshTopologyArg:
@@ -47,12 +49,6 @@ class TrimeshSpaceTopology(SpaceTopology):
47
49
  def name(self):
48
50
  return f"{self.geometry.name}_{self._shape.name}"
49
51
 
50
- @cache.cached_arg_value
51
- def topo_arg_value(self, device):
52
- arg = TrimeshTopologyArg()
53
- self.fill_topo_arg(arg, device)
54
- return arg
55
-
56
52
  def fill_topo_arg(self, arg: TrimeshTopologyArg, device):
57
53
  arg.tri_edge_indices = self._tri_edge_indices.to(device)
58
54
  arg.edge_vertex_indices = self._mesh.edge_vertex_indices.to(device)
warp/_src/fem/types.py ADDED
@@ -0,0 +1,114 @@
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 enum import IntEnum
17
+
18
+ import warp as wp
19
+
20
+ _wp_module_name_ = "warp.fem.types"
21
+
22
+ # kept to avoid breaking existing example code, no longer used internally
23
+ vec2i = wp.vec2i
24
+ vec3i = wp.vec3i
25
+ vec4i = wp.vec4i
26
+
27
+ Coords = wp.vec3
28
+ """Type representing coordinates within elements"""
29
+ OUTSIDE = -1.0e8
30
+ """Constant indicating an invalid element coordinate"""
31
+
32
+ ElementIndex = int
33
+ """Type representing the index of an element in the geometry"""
34
+ QuadraturePointIndex = int
35
+ """Type representing the index of a quadrature point"""
36
+ NodeIndex = int
37
+ """Type representing the index of a node in a function space"""
38
+
39
+ NULL_ELEMENT_INDEX: ElementIndex = wp.constant(-1)
40
+ """Constant indicating an invalid element index"""
41
+ NULL_QP_INDEX: QuadraturePointIndex = wp.constant(-1)
42
+ """Constant indicating an invalid quadrature point index"""
43
+ NULL_NODE_INDEX: NodeIndex = wp.constant((1 << 31) - 1) # this should be larger than normal nodes when sorting
44
+ """Constant indicating an invalid node index"""
45
+
46
+ DofIndex = wp.vec2i
47
+ """Opaque descriptor for indexing degrees of freedom within elements"""
48
+ NULL_DOF_INDEX: DofIndex = wp.constant(DofIndex(-1, -1))
49
+ """Constant indicating an invalid degree of freedom index"""
50
+
51
+
52
+ @wp.func
53
+ def get_node_index_in_element(dof_idx: DofIndex):
54
+ return dof_idx[0]
55
+
56
+
57
+ @wp.func
58
+ def get_node_coord(dof_idx: DofIndex):
59
+ return dof_idx[1]
60
+
61
+
62
+ class ElementKind(IntEnum):
63
+ """Type of geometry elements"""
64
+
65
+ CELL = 0
66
+ """Cells: elements that have the same dimension as the geometry"""
67
+ SIDE = 1
68
+ """Sides: elements that have one dimension less than the geometry"""
69
+
70
+
71
+ @wp.struct
72
+ class NodeElementIndex:
73
+ domain_element_index: ElementIndex
74
+ node_index_in_element: int
75
+
76
+
77
+ @wp.struct
78
+ class Sample:
79
+ """Per-sample point context for evaluating fields and related operators in integrands"""
80
+
81
+ element_index: ElementIndex
82
+ """Index of the geometry element the sample point is in"""
83
+ element_coords: Coords
84
+ """Coordinates of the sample point inside the element"""
85
+ qp_index: QuadraturePointIndex = NULL_QP_INDEX
86
+ """If the sample corresponds to a quadrature point, its global index"""
87
+ qp_weight: float = 0.0
88
+ """If the sample corresponds to a quadrature point, its weight"""
89
+ test_dof: DofIndex = NULL_DOF_INDEX
90
+ """For linear of bilinear form assembly, index of the test degree-of-freedom currently being considered"""
91
+ trial_dof: DofIndex = NULL_DOF_INDEX
92
+ """For bilinear form assembly, index of the trial degree-of-freedom currently being considered"""
93
+
94
+
95
+ @wp.func
96
+ def make_free_sample(element_index: ElementIndex, element_coords: Coords):
97
+ """Returns a :class:`Sample` that is not associated to any quadrature point or dof"""
98
+ return Sample(element_index, element_coords, NULL_QP_INDEX, 0.0, NULL_DOF_INDEX, NULL_DOF_INDEX)
99
+
100
+
101
+ class Field:
102
+ """
103
+ Tag for field-like integrand arguments
104
+ """
105
+
106
+ call_operator: "warp.fem.operator.Operator" = None # noqa: F821 Set in operator.py
107
+
108
+
109
+ class Domain:
110
+ """
111
+ Tag for domain-like integrand arguments
112
+ """
113
+
114
+ call_operator: "warp.fem.operator.Operator" = None # noqa: F821 Set in operator.py