warp-lang 1.10.0__py3-none-macosx_11_0_arm64.whl

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

Potentially problematic release.


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

Files changed (468) hide show
  1. warp/__init__.py +334 -0
  2. warp/__init__.pyi +5856 -0
  3. warp/_src/__init__.py +14 -0
  4. warp/_src/autograd.py +1077 -0
  5. warp/_src/build.py +620 -0
  6. warp/_src/build_dll.py +642 -0
  7. warp/_src/builtins.py +10555 -0
  8. warp/_src/codegen.py +4361 -0
  9. warp/_src/config.py +178 -0
  10. warp/_src/constants.py +59 -0
  11. warp/_src/context.py +8352 -0
  12. warp/_src/dlpack.py +464 -0
  13. warp/_src/fabric.py +362 -0
  14. warp/_src/fem/__init__.py +14 -0
  15. warp/_src/fem/adaptivity.py +510 -0
  16. warp/_src/fem/cache.py +689 -0
  17. warp/_src/fem/dirichlet.py +190 -0
  18. warp/_src/fem/domain.py +553 -0
  19. warp/_src/fem/field/__init__.py +131 -0
  20. warp/_src/fem/field/field.py +703 -0
  21. warp/_src/fem/field/nodal_field.py +403 -0
  22. warp/_src/fem/field/restriction.py +39 -0
  23. warp/_src/fem/field/virtual.py +1021 -0
  24. warp/_src/fem/geometry/__init__.py +32 -0
  25. warp/_src/fem/geometry/adaptive_nanogrid.py +782 -0
  26. warp/_src/fem/geometry/closest_point.py +99 -0
  27. warp/_src/fem/geometry/deformed_geometry.py +277 -0
  28. warp/_src/fem/geometry/element.py +854 -0
  29. warp/_src/fem/geometry/geometry.py +693 -0
  30. warp/_src/fem/geometry/grid_2d.py +478 -0
  31. warp/_src/fem/geometry/grid_3d.py +539 -0
  32. warp/_src/fem/geometry/hexmesh.py +956 -0
  33. warp/_src/fem/geometry/nanogrid.py +660 -0
  34. warp/_src/fem/geometry/partition.py +483 -0
  35. warp/_src/fem/geometry/quadmesh.py +597 -0
  36. warp/_src/fem/geometry/tetmesh.py +762 -0
  37. warp/_src/fem/geometry/trimesh.py +588 -0
  38. warp/_src/fem/integrate.py +2507 -0
  39. warp/_src/fem/linalg.py +385 -0
  40. warp/_src/fem/operator.py +398 -0
  41. warp/_src/fem/polynomial.py +231 -0
  42. warp/_src/fem/quadrature/__init__.py +17 -0
  43. warp/_src/fem/quadrature/pic_quadrature.py +318 -0
  44. warp/_src/fem/quadrature/quadrature.py +665 -0
  45. warp/_src/fem/space/__init__.py +248 -0
  46. warp/_src/fem/space/basis_function_space.py +499 -0
  47. warp/_src/fem/space/basis_space.py +681 -0
  48. warp/_src/fem/space/dof_mapper.py +253 -0
  49. warp/_src/fem/space/function_space.py +312 -0
  50. warp/_src/fem/space/grid_2d_function_space.py +179 -0
  51. warp/_src/fem/space/grid_3d_function_space.py +229 -0
  52. warp/_src/fem/space/hexmesh_function_space.py +255 -0
  53. warp/_src/fem/space/nanogrid_function_space.py +199 -0
  54. warp/_src/fem/space/partition.py +435 -0
  55. warp/_src/fem/space/quadmesh_function_space.py +222 -0
  56. warp/_src/fem/space/restriction.py +221 -0
  57. warp/_src/fem/space/shape/__init__.py +152 -0
  58. warp/_src/fem/space/shape/cube_shape_function.py +1107 -0
  59. warp/_src/fem/space/shape/shape_function.py +134 -0
  60. warp/_src/fem/space/shape/square_shape_function.py +928 -0
  61. warp/_src/fem/space/shape/tet_shape_function.py +829 -0
  62. warp/_src/fem/space/shape/triangle_shape_function.py +674 -0
  63. warp/_src/fem/space/tetmesh_function_space.py +270 -0
  64. warp/_src/fem/space/topology.py +461 -0
  65. warp/_src/fem/space/trimesh_function_space.py +193 -0
  66. warp/_src/fem/types.py +114 -0
  67. warp/_src/fem/utils.py +488 -0
  68. warp/_src/jax.py +188 -0
  69. warp/_src/jax_experimental/__init__.py +14 -0
  70. warp/_src/jax_experimental/custom_call.py +389 -0
  71. warp/_src/jax_experimental/ffi.py +1286 -0
  72. warp/_src/jax_experimental/xla_ffi.py +658 -0
  73. warp/_src/marching_cubes.py +710 -0
  74. warp/_src/math.py +416 -0
  75. warp/_src/optim/__init__.py +14 -0
  76. warp/_src/optim/adam.py +165 -0
  77. warp/_src/optim/linear.py +1608 -0
  78. warp/_src/optim/sgd.py +114 -0
  79. warp/_src/paddle.py +408 -0
  80. warp/_src/render/__init__.py +14 -0
  81. warp/_src/render/imgui_manager.py +291 -0
  82. warp/_src/render/render_opengl.py +3638 -0
  83. warp/_src/render/render_usd.py +939 -0
  84. warp/_src/render/utils.py +162 -0
  85. warp/_src/sparse.py +2718 -0
  86. warp/_src/tape.py +1208 -0
  87. warp/_src/thirdparty/__init__.py +0 -0
  88. warp/_src/thirdparty/appdirs.py +598 -0
  89. warp/_src/thirdparty/dlpack.py +145 -0
  90. warp/_src/thirdparty/unittest_parallel.py +676 -0
  91. warp/_src/torch.py +393 -0
  92. warp/_src/types.py +5888 -0
  93. warp/_src/utils.py +1695 -0
  94. warp/autograd.py +33 -0
  95. warp/bin/libwarp-clang.dylib +0 -0
  96. warp/bin/libwarp.dylib +0 -0
  97. warp/build.py +29 -0
  98. warp/build_dll.py +24 -0
  99. warp/codegen.py +24 -0
  100. warp/constants.py +24 -0
  101. warp/context.py +33 -0
  102. warp/dlpack.py +24 -0
  103. warp/examples/__init__.py +24 -0
  104. warp/examples/assets/bear.usd +0 -0
  105. warp/examples/assets/bunny.usd +0 -0
  106. warp/examples/assets/cube.usd +0 -0
  107. warp/examples/assets/nonuniform.usd +0 -0
  108. warp/examples/assets/nvidia_logo.png +0 -0
  109. warp/examples/assets/pixel.jpg +0 -0
  110. warp/examples/assets/rocks.nvdb +0 -0
  111. warp/examples/assets/rocks.usd +0 -0
  112. warp/examples/assets/sphere.usd +0 -0
  113. warp/examples/assets/square_cloth.usd +0 -0
  114. warp/examples/benchmarks/benchmark_api.py +389 -0
  115. warp/examples/benchmarks/benchmark_cloth.py +296 -0
  116. warp/examples/benchmarks/benchmark_cloth_cupy.py +96 -0
  117. warp/examples/benchmarks/benchmark_cloth_jax.py +105 -0
  118. warp/examples/benchmarks/benchmark_cloth_numba.py +161 -0
  119. warp/examples/benchmarks/benchmark_cloth_numpy.py +85 -0
  120. warp/examples/benchmarks/benchmark_cloth_paddle.py +94 -0
  121. warp/examples/benchmarks/benchmark_cloth_pytorch.py +94 -0
  122. warp/examples/benchmarks/benchmark_cloth_taichi.py +120 -0
  123. warp/examples/benchmarks/benchmark_cloth_warp.py +153 -0
  124. warp/examples/benchmarks/benchmark_gemm.py +164 -0
  125. warp/examples/benchmarks/benchmark_interop_paddle.py +166 -0
  126. warp/examples/benchmarks/benchmark_interop_torch.py +166 -0
  127. warp/examples/benchmarks/benchmark_launches.py +301 -0
  128. warp/examples/benchmarks/benchmark_tile_load_store.py +103 -0
  129. warp/examples/benchmarks/benchmark_tile_sort.py +155 -0
  130. warp/examples/browse.py +37 -0
  131. warp/examples/core/example_cupy.py +86 -0
  132. warp/examples/core/example_dem.py +241 -0
  133. warp/examples/core/example_fluid.py +299 -0
  134. warp/examples/core/example_graph_capture.py +150 -0
  135. warp/examples/core/example_marching_cubes.py +195 -0
  136. warp/examples/core/example_mesh.py +180 -0
  137. warp/examples/core/example_mesh_intersect.py +211 -0
  138. warp/examples/core/example_nvdb.py +182 -0
  139. warp/examples/core/example_raycast.py +111 -0
  140. warp/examples/core/example_raymarch.py +205 -0
  141. warp/examples/core/example_render_opengl.py +290 -0
  142. warp/examples/core/example_sample_mesh.py +300 -0
  143. warp/examples/core/example_sph.py +411 -0
  144. warp/examples/core/example_spin_lock.py +93 -0
  145. warp/examples/core/example_torch.py +211 -0
  146. warp/examples/core/example_wave.py +269 -0
  147. warp/examples/core/example_work_queue.py +118 -0
  148. warp/examples/distributed/example_jacobi_mpi.py +506 -0
  149. warp/examples/fem/example_adaptive_grid.py +286 -0
  150. warp/examples/fem/example_apic_fluid.py +469 -0
  151. warp/examples/fem/example_burgers.py +261 -0
  152. warp/examples/fem/example_convection_diffusion.py +181 -0
  153. warp/examples/fem/example_convection_diffusion_dg.py +225 -0
  154. warp/examples/fem/example_darcy_ls_optimization.py +489 -0
  155. warp/examples/fem/example_deformed_geometry.py +172 -0
  156. warp/examples/fem/example_diffusion.py +196 -0
  157. warp/examples/fem/example_diffusion_3d.py +225 -0
  158. warp/examples/fem/example_diffusion_mgpu.py +225 -0
  159. warp/examples/fem/example_distortion_energy.py +228 -0
  160. warp/examples/fem/example_elastic_shape_optimization.py +387 -0
  161. warp/examples/fem/example_magnetostatics.py +242 -0
  162. warp/examples/fem/example_mixed_elasticity.py +293 -0
  163. warp/examples/fem/example_navier_stokes.py +263 -0
  164. warp/examples/fem/example_nonconforming_contact.py +300 -0
  165. warp/examples/fem/example_stokes.py +213 -0
  166. warp/examples/fem/example_stokes_transfer.py +262 -0
  167. warp/examples/fem/example_streamlines.py +357 -0
  168. warp/examples/fem/utils.py +1047 -0
  169. warp/examples/interop/example_jax_callable.py +146 -0
  170. warp/examples/interop/example_jax_ffi_callback.py +132 -0
  171. warp/examples/interop/example_jax_kernel.py +232 -0
  172. warp/examples/optim/example_diffray.py +561 -0
  173. warp/examples/optim/example_fluid_checkpoint.py +497 -0
  174. warp/examples/tile/example_tile_block_cholesky.py +502 -0
  175. warp/examples/tile/example_tile_cholesky.py +88 -0
  176. warp/examples/tile/example_tile_convolution.py +66 -0
  177. warp/examples/tile/example_tile_fft.py +55 -0
  178. warp/examples/tile/example_tile_filtering.py +113 -0
  179. warp/examples/tile/example_tile_matmul.py +85 -0
  180. warp/examples/tile/example_tile_mcgp.py +191 -0
  181. warp/examples/tile/example_tile_mlp.py +385 -0
  182. warp/examples/tile/example_tile_nbody.py +199 -0
  183. warp/fabric.py +24 -0
  184. warp/fem/__init__.py +173 -0
  185. warp/fem/adaptivity.py +26 -0
  186. warp/fem/cache.py +30 -0
  187. warp/fem/dirichlet.py +24 -0
  188. warp/fem/field/__init__.py +24 -0
  189. warp/fem/field/field.py +26 -0
  190. warp/fem/geometry/__init__.py +21 -0
  191. warp/fem/geometry/closest_point.py +31 -0
  192. warp/fem/linalg.py +38 -0
  193. warp/fem/operator.py +32 -0
  194. warp/fem/polynomial.py +29 -0
  195. warp/fem/space/__init__.py +22 -0
  196. warp/fem/space/basis_space.py +24 -0
  197. warp/fem/space/shape/__init__.py +68 -0
  198. warp/fem/space/topology.py +24 -0
  199. warp/fem/types.py +24 -0
  200. warp/fem/utils.py +32 -0
  201. warp/jax.py +29 -0
  202. warp/jax_experimental/__init__.py +29 -0
  203. warp/jax_experimental/custom_call.py +29 -0
  204. warp/jax_experimental/ffi.py +39 -0
  205. warp/jax_experimental/xla_ffi.py +24 -0
  206. warp/marching_cubes.py +24 -0
  207. warp/math.py +37 -0
  208. warp/native/array.h +1687 -0
  209. warp/native/builtin.h +2327 -0
  210. warp/native/bvh.cpp +562 -0
  211. warp/native/bvh.cu +826 -0
  212. warp/native/bvh.h +555 -0
  213. warp/native/clang/clang.cpp +541 -0
  214. warp/native/coloring.cpp +622 -0
  215. warp/native/crt.cpp +51 -0
  216. warp/native/crt.h +568 -0
  217. warp/native/cuda_crt.h +1058 -0
  218. warp/native/cuda_util.cpp +677 -0
  219. warp/native/cuda_util.h +313 -0
  220. warp/native/error.cpp +77 -0
  221. warp/native/error.h +36 -0
  222. warp/native/exports.h +2023 -0
  223. warp/native/fabric.h +246 -0
  224. warp/native/hashgrid.cpp +311 -0
  225. warp/native/hashgrid.cu +89 -0
  226. warp/native/hashgrid.h +240 -0
  227. warp/native/initializer_array.h +41 -0
  228. warp/native/intersect.h +1253 -0
  229. warp/native/intersect_adj.h +375 -0
  230. warp/native/intersect_tri.h +348 -0
  231. warp/native/mat.h +5189 -0
  232. warp/native/mathdx.cpp +93 -0
  233. warp/native/matnn.h +221 -0
  234. warp/native/mesh.cpp +266 -0
  235. warp/native/mesh.cu +406 -0
  236. warp/native/mesh.h +2097 -0
  237. warp/native/nanovdb/GridHandle.h +533 -0
  238. warp/native/nanovdb/HostBuffer.h +591 -0
  239. warp/native/nanovdb/NanoVDB.h +6246 -0
  240. warp/native/nanovdb/NodeManager.h +323 -0
  241. warp/native/nanovdb/PNanoVDB.h +3390 -0
  242. warp/native/noise.h +859 -0
  243. warp/native/quat.h +1664 -0
  244. warp/native/rand.h +342 -0
  245. warp/native/range.h +145 -0
  246. warp/native/reduce.cpp +174 -0
  247. warp/native/reduce.cu +363 -0
  248. warp/native/runlength_encode.cpp +79 -0
  249. warp/native/runlength_encode.cu +61 -0
  250. warp/native/scan.cpp +47 -0
  251. warp/native/scan.cu +55 -0
  252. warp/native/scan.h +23 -0
  253. warp/native/solid_angle.h +466 -0
  254. warp/native/sort.cpp +251 -0
  255. warp/native/sort.cu +286 -0
  256. warp/native/sort.h +35 -0
  257. warp/native/sparse.cpp +241 -0
  258. warp/native/sparse.cu +435 -0
  259. warp/native/spatial.h +1306 -0
  260. warp/native/svd.h +727 -0
  261. warp/native/temp_buffer.h +46 -0
  262. warp/native/tile.h +4124 -0
  263. warp/native/tile_radix_sort.h +1112 -0
  264. warp/native/tile_reduce.h +838 -0
  265. warp/native/tile_scan.h +240 -0
  266. warp/native/tuple.h +189 -0
  267. warp/native/vec.h +2199 -0
  268. warp/native/version.h +23 -0
  269. warp/native/volume.cpp +501 -0
  270. warp/native/volume.cu +68 -0
  271. warp/native/volume.h +970 -0
  272. warp/native/volume_builder.cu +483 -0
  273. warp/native/volume_builder.h +52 -0
  274. warp/native/volume_impl.h +70 -0
  275. warp/native/warp.cpp +1143 -0
  276. warp/native/warp.cu +4604 -0
  277. warp/native/warp.h +358 -0
  278. warp/optim/__init__.py +20 -0
  279. warp/optim/adam.py +24 -0
  280. warp/optim/linear.py +35 -0
  281. warp/optim/sgd.py +24 -0
  282. warp/paddle.py +24 -0
  283. warp/py.typed +0 -0
  284. warp/render/__init__.py +22 -0
  285. warp/render/imgui_manager.py +29 -0
  286. warp/render/render_opengl.py +24 -0
  287. warp/render/render_usd.py +24 -0
  288. warp/render/utils.py +24 -0
  289. warp/sparse.py +51 -0
  290. warp/tape.py +24 -0
  291. warp/tests/__init__.py +1 -0
  292. warp/tests/__main__.py +4 -0
  293. warp/tests/assets/curlnoise_golden.npy +0 -0
  294. warp/tests/assets/mlp_golden.npy +0 -0
  295. warp/tests/assets/pixel.npy +0 -0
  296. warp/tests/assets/pnoise_golden.npy +0 -0
  297. warp/tests/assets/spiky.usd +0 -0
  298. warp/tests/assets/test_grid.nvdb +0 -0
  299. warp/tests/assets/test_index_grid.nvdb +0 -0
  300. warp/tests/assets/test_int32_grid.nvdb +0 -0
  301. warp/tests/assets/test_vec_grid.nvdb +0 -0
  302. warp/tests/assets/torus.nvdb +0 -0
  303. warp/tests/assets/torus.usda +105 -0
  304. warp/tests/aux_test_class_kernel.py +34 -0
  305. warp/tests/aux_test_compile_consts_dummy.py +18 -0
  306. warp/tests/aux_test_conditional_unequal_types_kernels.py +29 -0
  307. warp/tests/aux_test_dependent.py +29 -0
  308. warp/tests/aux_test_grad_customs.py +29 -0
  309. warp/tests/aux_test_instancing_gc.py +26 -0
  310. warp/tests/aux_test_module_aot.py +7 -0
  311. warp/tests/aux_test_module_unload.py +23 -0
  312. warp/tests/aux_test_name_clash1.py +40 -0
  313. warp/tests/aux_test_name_clash2.py +40 -0
  314. warp/tests/aux_test_reference.py +9 -0
  315. warp/tests/aux_test_reference_reference.py +8 -0
  316. warp/tests/aux_test_square.py +16 -0
  317. warp/tests/aux_test_unresolved_func.py +22 -0
  318. warp/tests/aux_test_unresolved_symbol.py +22 -0
  319. warp/tests/cuda/__init__.py +0 -0
  320. warp/tests/cuda/test_async.py +676 -0
  321. warp/tests/cuda/test_conditional_captures.py +1147 -0
  322. warp/tests/cuda/test_ipc.py +124 -0
  323. warp/tests/cuda/test_mempool.py +233 -0
  324. warp/tests/cuda/test_multigpu.py +169 -0
  325. warp/tests/cuda/test_peer.py +139 -0
  326. warp/tests/cuda/test_pinned.py +84 -0
  327. warp/tests/cuda/test_streams.py +691 -0
  328. warp/tests/geometry/__init__.py +0 -0
  329. warp/tests/geometry/test_bvh.py +335 -0
  330. warp/tests/geometry/test_hash_grid.py +259 -0
  331. warp/tests/geometry/test_marching_cubes.py +294 -0
  332. warp/tests/geometry/test_mesh.py +318 -0
  333. warp/tests/geometry/test_mesh_query_aabb.py +392 -0
  334. warp/tests/geometry/test_mesh_query_point.py +935 -0
  335. warp/tests/geometry/test_mesh_query_ray.py +323 -0
  336. warp/tests/geometry/test_volume.py +1103 -0
  337. warp/tests/geometry/test_volume_write.py +346 -0
  338. warp/tests/interop/__init__.py +0 -0
  339. warp/tests/interop/test_dlpack.py +730 -0
  340. warp/tests/interop/test_jax.py +1673 -0
  341. warp/tests/interop/test_paddle.py +800 -0
  342. warp/tests/interop/test_torch.py +1001 -0
  343. warp/tests/run_coverage_serial.py +39 -0
  344. warp/tests/test_adam.py +162 -0
  345. warp/tests/test_arithmetic.py +1096 -0
  346. warp/tests/test_array.py +3756 -0
  347. warp/tests/test_array_reduce.py +156 -0
  348. warp/tests/test_assert.py +303 -0
  349. warp/tests/test_atomic.py +336 -0
  350. warp/tests/test_atomic_bitwise.py +209 -0
  351. warp/tests/test_atomic_cas.py +312 -0
  352. warp/tests/test_bool.py +220 -0
  353. warp/tests/test_builtins_resolution.py +732 -0
  354. warp/tests/test_closest_point_edge_edge.py +327 -0
  355. warp/tests/test_codegen.py +974 -0
  356. warp/tests/test_codegen_instancing.py +1495 -0
  357. warp/tests/test_compile_consts.py +215 -0
  358. warp/tests/test_conditional.py +298 -0
  359. warp/tests/test_context.py +35 -0
  360. warp/tests/test_copy.py +319 -0
  361. warp/tests/test_ctypes.py +618 -0
  362. warp/tests/test_dense.py +73 -0
  363. warp/tests/test_devices.py +127 -0
  364. warp/tests/test_enum.py +136 -0
  365. warp/tests/test_examples.py +424 -0
  366. warp/tests/test_fabricarray.py +998 -0
  367. warp/tests/test_fast_math.py +72 -0
  368. warp/tests/test_fem.py +2204 -0
  369. warp/tests/test_fixedarray.py +229 -0
  370. warp/tests/test_fp16.py +136 -0
  371. warp/tests/test_func.py +501 -0
  372. warp/tests/test_future_annotations.py +100 -0
  373. warp/tests/test_generics.py +656 -0
  374. warp/tests/test_grad.py +893 -0
  375. warp/tests/test_grad_customs.py +339 -0
  376. warp/tests/test_grad_debug.py +341 -0
  377. warp/tests/test_implicit_init.py +411 -0
  378. warp/tests/test_import.py +45 -0
  379. warp/tests/test_indexedarray.py +1140 -0
  380. warp/tests/test_intersect.py +103 -0
  381. warp/tests/test_iter.py +76 -0
  382. warp/tests/test_large.py +177 -0
  383. warp/tests/test_launch.py +411 -0
  384. warp/tests/test_lerp.py +151 -0
  385. warp/tests/test_linear_solvers.py +223 -0
  386. warp/tests/test_lvalue.py +427 -0
  387. warp/tests/test_map.py +526 -0
  388. warp/tests/test_mat.py +3515 -0
  389. warp/tests/test_mat_assign_copy.py +178 -0
  390. warp/tests/test_mat_constructors.py +573 -0
  391. warp/tests/test_mat_lite.py +122 -0
  392. warp/tests/test_mat_scalar_ops.py +2913 -0
  393. warp/tests/test_math.py +212 -0
  394. warp/tests/test_module_aot.py +287 -0
  395. warp/tests/test_module_hashing.py +258 -0
  396. warp/tests/test_modules_lite.py +70 -0
  397. warp/tests/test_noise.py +252 -0
  398. warp/tests/test_operators.py +299 -0
  399. warp/tests/test_options.py +129 -0
  400. warp/tests/test_overwrite.py +551 -0
  401. warp/tests/test_print.py +408 -0
  402. warp/tests/test_quat.py +2653 -0
  403. warp/tests/test_quat_assign_copy.py +145 -0
  404. warp/tests/test_rand.py +339 -0
  405. warp/tests/test_reload.py +303 -0
  406. warp/tests/test_rounding.py +157 -0
  407. warp/tests/test_runlength_encode.py +196 -0
  408. warp/tests/test_scalar_ops.py +133 -0
  409. warp/tests/test_smoothstep.py +108 -0
  410. warp/tests/test_snippet.py +318 -0
  411. warp/tests/test_sparse.py +845 -0
  412. warp/tests/test_spatial.py +2859 -0
  413. warp/tests/test_spatial_assign_copy.py +160 -0
  414. warp/tests/test_special_values.py +361 -0
  415. warp/tests/test_static.py +640 -0
  416. warp/tests/test_struct.py +901 -0
  417. warp/tests/test_tape.py +242 -0
  418. warp/tests/test_transient_module.py +93 -0
  419. warp/tests/test_triangle_closest_point.py +192 -0
  420. warp/tests/test_tuple.py +361 -0
  421. warp/tests/test_types.py +615 -0
  422. warp/tests/test_utils.py +594 -0
  423. warp/tests/test_vec.py +1408 -0
  424. warp/tests/test_vec_assign_copy.py +143 -0
  425. warp/tests/test_vec_constructors.py +325 -0
  426. warp/tests/test_vec_lite.py +80 -0
  427. warp/tests/test_vec_scalar_ops.py +2327 -0
  428. warp/tests/test_verify_fp.py +100 -0
  429. warp/tests/test_version.py +75 -0
  430. warp/tests/tile/__init__.py +0 -0
  431. warp/tests/tile/test_tile.py +1519 -0
  432. warp/tests/tile/test_tile_atomic_bitwise.py +403 -0
  433. warp/tests/tile/test_tile_cholesky.py +608 -0
  434. warp/tests/tile/test_tile_load.py +724 -0
  435. warp/tests/tile/test_tile_mathdx.py +156 -0
  436. warp/tests/tile/test_tile_matmul.py +179 -0
  437. warp/tests/tile/test_tile_mlp.py +400 -0
  438. warp/tests/tile/test_tile_reduce.py +950 -0
  439. warp/tests/tile/test_tile_shared_memory.py +376 -0
  440. warp/tests/tile/test_tile_sort.py +121 -0
  441. warp/tests/tile/test_tile_view.py +173 -0
  442. warp/tests/unittest_serial.py +47 -0
  443. warp/tests/unittest_suites.py +430 -0
  444. warp/tests/unittest_utils.py +469 -0
  445. warp/tests/walkthrough_debug.py +95 -0
  446. warp/torch.py +24 -0
  447. warp/types.py +51 -0
  448. warp/utils.py +31 -0
  449. warp_lang-1.10.0.dist-info/METADATA +459 -0
  450. warp_lang-1.10.0.dist-info/RECORD +468 -0
  451. warp_lang-1.10.0.dist-info/WHEEL +5 -0
  452. warp_lang-1.10.0.dist-info/licenses/LICENSE.md +176 -0
  453. warp_lang-1.10.0.dist-info/licenses/licenses/Gaia-LICENSE.txt +6 -0
  454. warp_lang-1.10.0.dist-info/licenses/licenses/appdirs-LICENSE.txt +22 -0
  455. warp_lang-1.10.0.dist-info/licenses/licenses/asset_pixel_jpg-LICENSE.txt +3 -0
  456. warp_lang-1.10.0.dist-info/licenses/licenses/cuda-LICENSE.txt +1582 -0
  457. warp_lang-1.10.0.dist-info/licenses/licenses/dlpack-LICENSE.txt +201 -0
  458. warp_lang-1.10.0.dist-info/licenses/licenses/fp16-LICENSE.txt +28 -0
  459. warp_lang-1.10.0.dist-info/licenses/licenses/libmathdx-LICENSE.txt +220 -0
  460. warp_lang-1.10.0.dist-info/licenses/licenses/llvm-LICENSE.txt +279 -0
  461. warp_lang-1.10.0.dist-info/licenses/licenses/moller-LICENSE.txt +16 -0
  462. warp_lang-1.10.0.dist-info/licenses/licenses/nanovdb-LICENSE.txt +2 -0
  463. warp_lang-1.10.0.dist-info/licenses/licenses/nvrtc-LICENSE.txt +1592 -0
  464. warp_lang-1.10.0.dist-info/licenses/licenses/svd-LICENSE.txt +23 -0
  465. warp_lang-1.10.0.dist-info/licenses/licenses/unittest_parallel-LICENSE.txt +21 -0
  466. warp_lang-1.10.0.dist-info/licenses/licenses/usd-LICENSE.txt +213 -0
  467. warp_lang-1.10.0.dist-info/licenses/licenses/windingnumber-LICENSE.txt +21 -0
  468. warp_lang-1.10.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,228 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2022 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
+ ###########################################################################
17
+ # Example Distortion Energy
18
+ #
19
+ # This example illustrates using a Newton loop to minimize distortion of a
20
+ # 3D surface (u,v) parameterization under a Symmetric Dirichlet energy,
21
+ #
22
+ # E(F) = 1/2 |F|^2 + |F^{-1}|^2
23
+ #
24
+ # with F := dx/du
25
+ ###########################################################################
26
+
27
+ import numpy as np
28
+
29
+ import warp as wp
30
+ import warp.examples.fem.utils as fem_example_utils
31
+ import warp.fem as fem
32
+
33
+
34
+ @fem.integrand
35
+ def distortion_gradient_form(s: fem.Sample, u_cur: fem.Field, v: fem.Field):
36
+ # Symmetric Dirichlet energy gradient (linear form)
37
+ # E = 1/2 (F:F + F^-T:F^-T)
38
+
39
+ F = fem.grad(u_cur, s)
40
+
41
+ F_inv_sq = wp.inverse(F * wp.transpose(F))
42
+ F_inv = F_inv_sq * F
43
+
44
+ dE_dF = F - F_inv_sq * F_inv
45
+
46
+ return wp.ddot(fem.grad(v, s), dE_dF)
47
+
48
+
49
+ @fem.integrand
50
+ def distortion_hessian_form(s: fem.Sample, u_cur: fem.Field, u: fem.Field, v: fem.Field):
51
+ # Symmetric Dirichlet energy approximate hessian (bilinear form)
52
+
53
+ # F:F term
54
+ H = wp.ddot(fem.grad(v, s), fem.grad(u, s))
55
+
56
+ # F^-T:F^-T term
57
+ F = fem.grad(u_cur, s)
58
+ F_inv_sq = wp.inverse(F * wp.transpose(F))
59
+
60
+ # Gauss--Newton (ignore F^-2 derivative)
61
+ H += wp.ddot(F_inv_sq * fem.grad(v, s), F_inv_sq * F_inv_sq * fem.grad(u, s))
62
+
63
+ return H
64
+
65
+
66
+ @fem.integrand
67
+ def initial_guess(
68
+ s: fem.Sample,
69
+ domain: fem.Domain,
70
+ ):
71
+ # initialization for UV parameter
72
+ x = domain(s)
73
+ return wp.vec2(x[0], x[1])
74
+
75
+
76
+ @fem.integrand
77
+ def boundary_projector_form(
78
+ s: fem.Sample,
79
+ domain: fem.Domain,
80
+ u: fem.Field,
81
+ v: fem.Field,
82
+ ):
83
+ # Fix a single point
84
+ # (underconstrained, solution up to a rotation in UV space)
85
+ w = wp.where(s.qp_index == 0, 1.0, 0.0)
86
+ return w * wp.dot(u(s), v(s))
87
+
88
+
89
+ @fem.integrand
90
+ def checkerboard(s: fem.Sample, domain: fem.Domain, u: fem.Field):
91
+ # checkerboard pattern for parameter visualization
92
+ u_s = u(s)
93
+ return wp.sign(wp.cos(16.0 * u_s[0]) * wp.sin(16.0 * u_s[1]))
94
+
95
+
96
+ class Example:
97
+ def __init__(
98
+ self,
99
+ quiet=False,
100
+ degree=2,
101
+ resolution=25,
102
+ mesh="grid",
103
+ nonconforming_stresses=False,
104
+ ):
105
+ self._quiet = quiet
106
+
107
+ def deform_along_z(positions, z_scale=1.0):
108
+ pos = positions.numpy()
109
+ pos_z = z_scale * np.cos(3.0 * pos[:, 0]) * np.sin(4.0 * pos[:, 1])
110
+ pos = np.hstack((pos, np.expand_dims(pos_z, axis=1)))
111
+ return wp.array(pos, dtype=wp.vec3)
112
+
113
+ # Grid or mesh geometry
114
+ if mesh == "tri":
115
+ positions, tri_vidx = fem_example_utils.gen_trimesh(res=wp.vec2i(resolution))
116
+ self._uv_geo = fem.Trimesh2D(tri_vertex_indices=tri_vidx, positions=wp.zeros_like(positions))
117
+
118
+ positions = deform_along_z(positions)
119
+ self._geo = fem.Trimesh3D(tri_vertex_indices=tri_vidx, positions=positions)
120
+ elif mesh == "quad":
121
+ positions, quad_vidx = fem_example_utils.gen_quadmesh(res=wp.vec2i(resolution))
122
+ self._uv_geo = fem.Quadmesh2D(quad_vertex_indices=quad_vidx, positions=wp.zeros_like(positions))
123
+
124
+ positions = deform_along_z(positions)
125
+ self._geo = fem.Quadmesh3D(quad_vertex_indices=quad_vidx, positions=positions)
126
+ else:
127
+ positions, quad_vidx = fem_example_utils.gen_quadmesh(res=wp.vec2i(resolution))
128
+ self._uv_geo = fem.Quadmesh2D(quad_vertex_indices=quad_vidx, positions=wp.zeros_like(positions))
129
+
130
+ undef_positions = deform_along_z(positions, z_scale=0.0)
131
+ flat_geo = fem.Quadmesh3D(quad_vertex_indices=quad_vidx, positions=undef_positions)
132
+
133
+ deformation_field = fem.make_discrete_field(fem.make_polynomial_space(flat_geo, dtype=wp.vec3))
134
+ deformation_field.dof_values = deform_along_z(positions)
135
+
136
+ self._geo = deformation_field.make_deformed_geometry(relative=False)
137
+
138
+ # parameter space
139
+ self._u_space = fem.make_polynomial_space(self._geo, degree=degree, dtype=wp.vec2)
140
+ self._u_field = self._u_space.make_field()
141
+ self._du_field = self._u_space.make_field()
142
+ fem.interpolate(initial_guess, dest=self._u_field)
143
+
144
+ # scalar parameter visualization function
145
+ viz_space = fem.make_polynomial_space(self._geo, degree=3, dtype=float)
146
+ self.viz_field = viz_space.make_field()
147
+ # For visualization of uv in 2D space
148
+ uv_space = fem.make_polynomial_space(self._uv_geo, degree=degree, dtype=wp.vec2)
149
+ self._uv_field = uv_space.make_field()
150
+
151
+ self.renderer = fem_example_utils.Plot()
152
+
153
+ def step(self):
154
+ boundary = fem.BoundarySides(self._geo)
155
+ domain = fem.Cells(geometry=self._geo)
156
+
157
+ # Parameter boundary conditions
158
+ u_bd_test = fem.make_test(space=self._u_space, domain=boundary)
159
+ u_bd_trial = fem.make_trial(space=self._u_space, domain=boundary)
160
+ u_bd_matrix = fem.integrate(
161
+ boundary_projector_form, fields={"u": u_bd_trial, "v": u_bd_test}, assembly="nodal", output_dtype=float
162
+ )
163
+ fem.normalize_dirichlet_projector(u_bd_matrix)
164
+
165
+ u_test = fem.make_test(space=self._u_space, domain=domain)
166
+ u_trial = fem.make_trial(space=self._u_space, domain=domain)
167
+
168
+ # Newton iterations (without line-search for simplicity)
169
+ for _newton_iteration in range(10):
170
+ u_matrix = fem.integrate(
171
+ distortion_hessian_form, fields={"u_cur": self._u_field, "u": u_trial, "v": u_test}, output_dtype=float
172
+ )
173
+
174
+ u_rhs = fem.integrate(
175
+ distortion_gradient_form, fields={"u_cur": self._u_field, "v": u_test}, output_dtype=wp.vec2
176
+ )
177
+
178
+ fem.project_linear_system(u_matrix, u_rhs, u_bd_matrix, normalize_projector=False)
179
+
180
+ # Solve for uv increment
181
+ du = self._du_field.dof_values
182
+ du.zero_()
183
+ fem_example_utils.bsr_cg(u_matrix, b=u_rhs, x=du, quiet=self._quiet)
184
+
185
+ # Accumulate to UV field
186
+ fem.linalg.array_axpy(x=du, y=self._u_field.dof_values, alpha=-1.0, beta=1.0)
187
+
188
+ def render(self):
189
+ # Visualization
190
+ fem.interpolate(checkerboard, fields={"u": self._u_field}, dest=self.viz_field)
191
+
192
+ self._uv_field.dof_values = wp.clone(self._u_field.dof_values)
193
+
194
+ self.renderer.add_field("pattern", self.viz_field)
195
+ self.renderer.add_field("uv", self._uv_field)
196
+
197
+
198
+ if __name__ == "__main__":
199
+ import argparse
200
+
201
+ wp.set_module_options({"enable_backward": False})
202
+
203
+ parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
204
+ parser.add_argument("--device", type=str, default=None, help="Override the default Warp device.")
205
+ parser.add_argument("--resolution", type=int, default=25, help="Grid resolution.")
206
+ parser.add_argument("--degree", type=int, default=1, help="Polynomial degree of shape functions.")
207
+ parser.add_argument("--mesh", choices=("tri", "quad", "deformed"), default="tri", help="Mesh type")
208
+ parser.add_argument(
209
+ "--headless",
210
+ action="store_true",
211
+ help="Run in headless mode, suppressing the opening of any graphical windows.",
212
+ )
213
+ parser.add_argument("--quiet", action="store_true", help="Suppresses the printing out of iteration residuals.")
214
+
215
+ args = parser.parse_known_args()[0]
216
+
217
+ with wp.ScopedDevice(args.device):
218
+ example = Example(
219
+ quiet=args.quiet,
220
+ degree=args.degree,
221
+ resolution=args.resolution,
222
+ mesh=args.mesh,
223
+ )
224
+ example.step()
225
+ example.render()
226
+
227
+ if not args.headless:
228
+ example.renderer.plot(options={"uv": {"displacement": {}}})
@@ -0,0 +1,387 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025 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
+ ###########################################################################
17
+ # Example: Shape Optimization of a 2D Elastic Cantilever Beam
18
+ #
19
+ # This example demonstrates shape optimization of a 2D elastic cantilever beam using
20
+ # finite element analysis and gradient-based optimization.
21
+ #
22
+ # Problem Setup:
23
+ # - The computational domain is a 2D beam (rectangular mesh), fixed on the left edge
24
+ # (Dirichlet boundary condition: zero displacement).
25
+ # - A constant external load is applied to the right edge of the beam, causing it to deform.
26
+ # - The beam is discretized using finite elements, and the displacement field is solved
27
+ # for the current geometry at each optimization step using a linear elasticity formulation.
28
+ #
29
+ # Shape Optimization Strategy:
30
+ # - The goal is to optimize the shape of the beam to minimize the total squared norm of the
31
+ # stress field (e.g., compliance or strain energy) over the domain.
32
+ # - The positions of the left and right boundary vertices are fixed throughout the optimization
33
+ # to maintain the beam's support and loading conditions.
34
+ # - A volume constraint is enforced to preserve the total material volume, preventing trivial
35
+ # solutions that simply shrink the structure.
36
+ # - An ad-hoc "quality" term is included in the loss function to penalize degenerate or inverted elements,
37
+ # helping to maintain mesh quality (as remeshing would be out of scope for this example).
38
+ # - The optimization is performed by computing the gradient of the objective with respect to
39
+ # the nodal positions (shape derivatives) using the adjoint method or automatic differentiation.
40
+ # - At each iteration, the nodal positions are updated in the direction of decreasing objective,
41
+ # subject to the volume constraint and boundary conditions.
42
+ ###########################################################################
43
+
44
+ import numpy as np
45
+
46
+ import warp as wp
47
+ import warp.examples.fem.utils as fem_example_utils
48
+ import warp.fem as fem
49
+ from warp.optim import Adam
50
+
51
+
52
+ @fem.integrand(kernel_options={"max_unroll": 1})
53
+ def boundary_projector_form(
54
+ s: fem.Sample,
55
+ domain: fem.Domain,
56
+ u: fem.Field,
57
+ v: fem.Field,
58
+ ):
59
+ return wp.dot(u(s), v(s))
60
+
61
+
62
+ @fem.integrand
63
+ def classify_boundary_sides(
64
+ s: fem.Sample,
65
+ domain: fem.Domain,
66
+ left: wp.array(dtype=int),
67
+ right: wp.array(dtype=int),
68
+ ):
69
+ nor = fem.normal(domain, s)
70
+
71
+ if nor[0] < -0.5:
72
+ left[s.qp_index] = 1
73
+ elif nor[0] > 0.5:
74
+ right[s.qp_index] = 1
75
+
76
+
77
+ @wp.func
78
+ def hooke_stress(strain: wp.mat22, lame: wp.vec2):
79
+ """Hookean elasticity"""
80
+ return 2.0 * lame[1] * strain + lame[0] * wp.trace(strain) * wp.identity(n=2, dtype=float)
81
+
82
+
83
+ @fem.integrand
84
+ def stress_field(s: fem.Sample, u: fem.Field, lame: wp.vec2):
85
+ return hooke_stress(fem.D(u, s), lame)
86
+
87
+
88
+ @fem.integrand
89
+ def hooke_elasticity_form(s: fem.Sample, u: fem.Field, v: fem.Field, lame: wp.vec2):
90
+ return wp.ddot(fem.D(v, s), stress_field(s, u, lame))
91
+
92
+
93
+ @fem.integrand
94
+ def applied_load_form(s: fem.Sample, domain: fem.Domain, v: fem.Field, load: wp.vec2):
95
+ return wp.dot(v(s), load)
96
+
97
+
98
+ @fem.integrand
99
+ def loss_form(
100
+ s: fem.Sample, domain: fem.Domain, u: fem.Field, lame: wp.vec2, quality_threshold: float, quality_weight: float
101
+ ):
102
+ stress = stress_field(s, u, lame)
103
+ stress_norm_sq = wp.ddot(stress, stress)
104
+
105
+ # As we're not remeshing, add a "quality" term
106
+ # to avoid degenerate and inverted elements
107
+
108
+ F = fem.deformation_gradient(domain, s)
109
+ U, S, V = wp.svd2(F)
110
+
111
+ quality = wp.min(S) / wp.max(S) / quality_threshold
112
+ quality_pen = -wp.log(wp.max(quality, 0.0001)) * wp.min(0.0, quality - 1.0) * wp.min(0.0, quality - 1.0)
113
+
114
+ return stress_norm_sq + quality_pen * quality_weight
115
+
116
+
117
+ @fem.integrand
118
+ def volume_form():
119
+ return 1.0
120
+
121
+
122
+ @wp.kernel
123
+ def add_volume_loss(
124
+ loss: wp.array(dtype=wp.float32), vol: wp.array(dtype=wp.float32), target_vol: wp.float32, weight: wp.float32
125
+ ):
126
+ loss[0] += weight * (vol[0] - target_vol) * (vol[0] - target_vol)
127
+
128
+
129
+ class Example:
130
+ def __init__(
131
+ self,
132
+ quiet=False,
133
+ degree=2,
134
+ resolution=25,
135
+ mesh="tri",
136
+ poisson_ratio=0.5,
137
+ load=(0.0, -1),
138
+ lr=1.0e-3,
139
+ ):
140
+ self._quiet = quiet
141
+
142
+ # Lame coefficients from Young modulus and Poisson ratio
143
+ self._lame = wp.vec2(1.0 / (1.0 + poisson_ratio) * np.array([poisson_ratio / (1.0 - poisson_ratio), 0.5]))
144
+ self._load = load
145
+
146
+ # procedural rectangular domain definition
147
+ bounds_lo = wp.vec2(0.0, 0.8)
148
+ bounds_hi = wp.vec2(1.0, 1.0)
149
+ self._initial_volume = (bounds_hi - bounds_lo)[0] * (bounds_hi - bounds_lo)[1]
150
+
151
+ if mesh == "tri":
152
+ # triangle mesh, optimize vertices directly
153
+ positions, tri_vidx = fem_example_utils.gen_trimesh(
154
+ res=wp.vec2i(resolution, resolution // 5), bounds_lo=bounds_lo, bounds_hi=bounds_hi
155
+ )
156
+ self._geo = fem.Trimesh2D(tri_vertex_indices=tri_vidx, positions=positions)
157
+ self._start_geo = fem.Trimesh2D(tri_vertex_indices=tri_vidx, positions=wp.clone(positions))
158
+ self._vertex_positions = positions
159
+ elif mesh == "quad":
160
+ # quad mesh, optimize vertices directly
161
+ positions, quad_vidx = fem_example_utils.gen_quadmesh(
162
+ res=wp.vec2i(resolution, resolution // 5), bounds_lo=bounds_lo, bounds_hi=bounds_hi
163
+ )
164
+ self._geo = fem.Quadmesh2D(quad_vertex_indices=quad_vidx, positions=positions)
165
+ self._start_geo = fem.Quadmesh2D(quad_vertex_indices=quad_vidx, positions=wp.clone(positions))
166
+ self._vertex_positions = positions
167
+ else:
168
+ # grid, optimize nodes of deformation field
169
+ self._start_geo = fem.Grid2D(
170
+ wp.vec2i(resolution, resolution // 5), bounds_lo=bounds_lo, bounds_hi=bounds_hi
171
+ )
172
+ vertex_displacement_space = fem.make_polynomial_space(self._start_geo, degree=1, dtype=wp.vec2)
173
+ vertex_position_field = fem.make_discrete_field(space=vertex_displacement_space)
174
+ vertex_position_field.dof_values = vertex_displacement_space.node_positions()
175
+ self._geo = vertex_position_field.make_deformed_geometry(relative=False)
176
+ self._vertex_positions = vertex_position_field.dof_values
177
+
178
+ # make sure positions are differentiable
179
+ self._vertex_positions.requires_grad = True
180
+
181
+ # Store initial node positions (for rendering)
182
+ self._u_space = fem.make_polynomial_space(self._geo, degree=degree, dtype=wp.vec2)
183
+ self._start_node_positions = self._u_space.node_positions()
184
+
185
+ # displacement field, make sure gradient is stored
186
+ self._u_field = fem.make_discrete_field(space=self._u_space)
187
+ self._u_field.dof_values.requires_grad = True
188
+
189
+ # Trial and test functions
190
+ self._u_test = fem.make_test(space=self._u_space)
191
+ self._u_trial = fem.make_trial(space=self._u_space)
192
+
193
+ # Identify left and right sides for boundary conditions
194
+ boundary = fem.BoundarySides(self._geo)
195
+
196
+ left_mask = wp.zeros(shape=boundary.element_count(), dtype=int)
197
+ right_mask = wp.zeros(shape=boundary.element_count(), dtype=int)
198
+
199
+ fem.interpolate(
200
+ classify_boundary_sides,
201
+ quadrature=fem.RegularQuadrature(boundary, order=0),
202
+ values={"left": left_mask, "right": right_mask},
203
+ )
204
+
205
+ self._left = fem.Subdomain(boundary, element_mask=left_mask)
206
+ self._right = fem.Subdomain(boundary, element_mask=right_mask)
207
+
208
+ # Build projectors for the left-side homogeneous Dirichlet condition
209
+ u_left_bd_test = fem.make_test(space=self._u_space, domain=self._left)
210
+ u_left_bd_trial = fem.make_trial(space=self._u_space, domain=self._left)
211
+ u_left_bd_matrix = fem.integrate(
212
+ boundary_projector_form,
213
+ fields={"u": u_left_bd_trial, "v": u_left_bd_test},
214
+ assembly="nodal",
215
+ output_dtype=float,
216
+ )
217
+ fem.normalize_dirichlet_projector(u_left_bd_matrix)
218
+ self._bd_projector = u_left_bd_matrix
219
+
220
+ # Fixed vertices (that the shape optimization should not move)
221
+ # Build projectors for the left and right subdomains and add them together
222
+ vertex_space = fem.make_polynomial_space(self._geo, degree=1, dtype=wp.vec2)
223
+ u_left_vertex_bd_test = fem.make_test(space=vertex_space, domain=self._left)
224
+ u_left_vertex_bd_trial = fem.make_trial(space=vertex_space, domain=self._left)
225
+ u_right_vertex_bd_test = fem.make_test(space=vertex_space, domain=self._right)
226
+ u_right_vertex_bd_trial = fem.make_trial(space=vertex_space, domain=self._right)
227
+ u_fixed_vertex_matrix = fem.integrate(
228
+ boundary_projector_form,
229
+ fields={"u": u_left_vertex_bd_trial, "v": u_left_vertex_bd_test},
230
+ assembly="nodal",
231
+ output_dtype=float,
232
+ ) + fem.integrate(
233
+ boundary_projector_form,
234
+ fields={"u": u_right_vertex_bd_trial, "v": u_right_vertex_bd_test},
235
+ assembly="nodal",
236
+ output_dtype=float,
237
+ )
238
+ fem.normalize_dirichlet_projector(u_fixed_vertex_matrix)
239
+ self._fixed_vertex_projector = u_fixed_vertex_matrix
240
+
241
+ self._u_right_test = fem.make_test(space=self._u_space, domain=self._right)
242
+
243
+ # initialize renderer
244
+ self.renderer = fem_example_utils.Plot()
245
+
246
+ # Initialize Adam optimizer
247
+ # Current implementation assumes scalar arrays, so cast our vec2 arrays to scalars
248
+ self._vertex_positions_scalar = wp.array(self._vertex_positions, dtype=wp.float32).flatten()
249
+ self._vertex_positions_scalar.grad = wp.array(self._vertex_positions.grad, dtype=wp.float32).flatten()
250
+ self.optimizer = Adam([self._vertex_positions_scalar], lr=lr)
251
+
252
+ def step(self):
253
+ # Forward step, record adjoint tape for forces
254
+ u = self._u_field.dof_values
255
+ u.zero_()
256
+
257
+ u_rhs = wp.empty(self._u_space.node_count(), dtype=wp.vec2f, requires_grad=True)
258
+
259
+ tape = wp.Tape()
260
+
261
+ with tape:
262
+ fem.integrate(
263
+ applied_load_form,
264
+ fields={"v": self._u_right_test},
265
+ values={"load": self._load},
266
+ output=u_rhs,
267
+ )
268
+ # the elastic force will be zero at the first iteration,
269
+ # but including it on the tape is necessary to compute the gradient of the force equilibrium
270
+ # using the implicit function theorem
271
+ # Note that this will be evaluated in the backward pass using the updated values for "_u_field"
272
+ fem.integrate(
273
+ hooke_elasticity_form,
274
+ fields={"u": self._u_field, "v": self._u_test},
275
+ values={"lame": -self._lame},
276
+ output=u_rhs,
277
+ add=True,
278
+ )
279
+
280
+ u_matrix = fem.integrate(
281
+ hooke_elasticity_form,
282
+ fields={"u": self._u_trial, "v": self._u_test},
283
+ values={"lame": self._lame},
284
+ output_dtype=float,
285
+ )
286
+ fem.project_linear_system(u_matrix, u_rhs, self._bd_projector, normalize_projector=False)
287
+
288
+ fem_example_utils.bsr_cg(u_matrix, b=u_rhs, x=u, quiet=self._quiet, tol=1e-6, max_iters=1000)
289
+
290
+ # Record adjoint of linear solve
291
+ # (For nonlinear elasticity, this should use the final hessian, as per implicit function theorem)
292
+ def solve_linear_system():
293
+ fem_example_utils.bsr_cg(u_matrix, b=u.grad, x=u_rhs.grad, quiet=self._quiet, tol=1e-6, max_iters=1000)
294
+ u_rhs.grad -= self._bd_projector @ u_rhs.grad
295
+ self._u_field.dof_values.grad.zero_()
296
+
297
+ tape.record_func(solve_linear_system, arrays=(u_rhs, u))
298
+
299
+ # Evaluate residual
300
+ # Integral of squared difference between simulated position and target positions
301
+ loss = wp.empty(shape=1, dtype=wp.float32, requires_grad=True)
302
+ vol = wp.empty(shape=1, dtype=wp.float32, requires_grad=True)
303
+
304
+ with tape:
305
+ fem.integrate(
306
+ loss_form,
307
+ fields={"u": self._u_field},
308
+ values={"lame": self._lame, "quality_threshold": 0.2, "quality_weight": 20.0},
309
+ domain=self._u_test.domain,
310
+ output=loss,
311
+ )
312
+ print(f"Loss: {loss}")
313
+
314
+ # Add penalization term enforcing constant volume
315
+ fem.integrate(
316
+ volume_form,
317
+ domain=self._u_test.domain,
318
+ output=vol,
319
+ )
320
+
321
+ vol_loss_weight = 100.0
322
+ wp.launch(
323
+ add_volume_loss,
324
+ dim=1,
325
+ inputs=(loss, vol, self._initial_volume, vol_loss_weight),
326
+ )
327
+
328
+ # perform backward step
329
+ tape.backward(loss=loss)
330
+
331
+ # enforce fixed vertices
332
+ self._vertex_positions.grad -= self._fixed_vertex_projector @ self._vertex_positions.grad
333
+
334
+ # update positions and reset tape
335
+ self.optimizer.step([self._vertex_positions_scalar.grad])
336
+ tape.zero()
337
+
338
+ def render(self):
339
+ # Render using fields defined on start geometry
340
+ # (renderer assumes geometry remains fixed for timesampled fields)
341
+ u_space = fem.make_polynomial_space(self._start_geo, degree=self._u_space.degree, dtype=wp.vec2)
342
+ u_field = fem.make_discrete_field(space=u_space)
343
+ rest_field = fem.make_discrete_field(space=u_space)
344
+
345
+ geo_displacement = self._u_space.node_positions() - self._start_node_positions
346
+ u_field.dof_values = self._u_field.dof_values + geo_displacement
347
+ rest_field.dof_values = geo_displacement
348
+
349
+ self.renderer.add_field("displacement", u_field)
350
+ self.renderer.add_field("rest", rest_field)
351
+
352
+
353
+ if __name__ == "__main__":
354
+ import argparse
355
+
356
+ parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
357
+ parser.add_argument("--device", type=str, default=None, help="Override the default Warp device.")
358
+ parser.add_argument("--resolution", type=int, default=10, help="Grid resolution.")
359
+ parser.add_argument("--degree", type=int, default=1, help="Polynomial degree of shape functions.")
360
+ parser.add_argument("--mesh", choices=("tri", "quad", "grid"), default="tri", help="Mesh type")
361
+ parser.add_argument(
362
+ "--headless",
363
+ action="store_true",
364
+ help="Run in headless mode, suppressing the opening of any graphical windows.",
365
+ )
366
+ parser.add_argument("--lr", type=float, default=1.0e-3, help="Learning rate.")
367
+ parser.add_argument("--num_iters", type=int, default=250, help="Number of iterations.")
368
+
369
+ args = parser.parse_known_args()[0]
370
+
371
+ with wp.ScopedDevice(args.device):
372
+ example = Example(
373
+ quiet=True,
374
+ degree=args.degree,
375
+ resolution=args.resolution,
376
+ mesh=args.mesh,
377
+ poisson_ratio=0.95,
378
+ load=wp.vec2(0.0, -0.1),
379
+ lr=args.lr,
380
+ )
381
+
382
+ for _k in range(args.num_iters):
383
+ example.step()
384
+ example.render()
385
+
386
+ if not args.headless:
387
+ example.renderer.plot(options={"displacement": {"displacement": {}}, "rest": {"displacement": {}}})