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.
- warp/__init__.py +334 -0
- warp/__init__.pyi +5856 -0
- warp/_src/__init__.py +14 -0
- warp/_src/autograd.py +1077 -0
- warp/_src/build.py +620 -0
- warp/_src/build_dll.py +642 -0
- warp/_src/builtins.py +10555 -0
- warp/_src/codegen.py +4361 -0
- warp/_src/config.py +178 -0
- warp/_src/constants.py +59 -0
- warp/_src/context.py +8352 -0
- warp/_src/dlpack.py +464 -0
- warp/_src/fabric.py +362 -0
- warp/_src/fem/__init__.py +14 -0
- warp/_src/fem/adaptivity.py +510 -0
- warp/_src/fem/cache.py +689 -0
- warp/_src/fem/dirichlet.py +190 -0
- warp/_src/fem/domain.py +553 -0
- warp/_src/fem/field/__init__.py +131 -0
- warp/_src/fem/field/field.py +703 -0
- warp/_src/fem/field/nodal_field.py +403 -0
- warp/_src/fem/field/restriction.py +39 -0
- warp/_src/fem/field/virtual.py +1021 -0
- warp/_src/fem/geometry/__init__.py +32 -0
- warp/_src/fem/geometry/adaptive_nanogrid.py +782 -0
- warp/_src/fem/geometry/closest_point.py +99 -0
- warp/_src/fem/geometry/deformed_geometry.py +277 -0
- warp/_src/fem/geometry/element.py +854 -0
- warp/_src/fem/geometry/geometry.py +693 -0
- warp/_src/fem/geometry/grid_2d.py +478 -0
- warp/_src/fem/geometry/grid_3d.py +539 -0
- warp/_src/fem/geometry/hexmesh.py +956 -0
- warp/_src/fem/geometry/nanogrid.py +660 -0
- warp/_src/fem/geometry/partition.py +483 -0
- warp/_src/fem/geometry/quadmesh.py +597 -0
- warp/_src/fem/geometry/tetmesh.py +762 -0
- warp/_src/fem/geometry/trimesh.py +588 -0
- warp/_src/fem/integrate.py +2507 -0
- warp/_src/fem/linalg.py +385 -0
- warp/_src/fem/operator.py +398 -0
- warp/_src/fem/polynomial.py +231 -0
- warp/_src/fem/quadrature/__init__.py +17 -0
- warp/_src/fem/quadrature/pic_quadrature.py +318 -0
- warp/_src/fem/quadrature/quadrature.py +665 -0
- warp/_src/fem/space/__init__.py +248 -0
- warp/_src/fem/space/basis_function_space.py +499 -0
- warp/_src/fem/space/basis_space.py +681 -0
- warp/_src/fem/space/dof_mapper.py +253 -0
- warp/_src/fem/space/function_space.py +312 -0
- warp/_src/fem/space/grid_2d_function_space.py +179 -0
- warp/_src/fem/space/grid_3d_function_space.py +229 -0
- warp/_src/fem/space/hexmesh_function_space.py +255 -0
- warp/_src/fem/space/nanogrid_function_space.py +199 -0
- warp/_src/fem/space/partition.py +435 -0
- warp/_src/fem/space/quadmesh_function_space.py +222 -0
- warp/_src/fem/space/restriction.py +221 -0
- warp/_src/fem/space/shape/__init__.py +152 -0
- warp/_src/fem/space/shape/cube_shape_function.py +1107 -0
- warp/_src/fem/space/shape/shape_function.py +134 -0
- warp/_src/fem/space/shape/square_shape_function.py +928 -0
- warp/_src/fem/space/shape/tet_shape_function.py +829 -0
- warp/_src/fem/space/shape/triangle_shape_function.py +674 -0
- warp/_src/fem/space/tetmesh_function_space.py +270 -0
- warp/_src/fem/space/topology.py +461 -0
- warp/_src/fem/space/trimesh_function_space.py +193 -0
- warp/_src/fem/types.py +114 -0
- warp/_src/fem/utils.py +488 -0
- warp/_src/jax.py +188 -0
- warp/_src/jax_experimental/__init__.py +14 -0
- warp/_src/jax_experimental/custom_call.py +389 -0
- warp/_src/jax_experimental/ffi.py +1286 -0
- warp/_src/jax_experimental/xla_ffi.py +658 -0
- warp/_src/marching_cubes.py +710 -0
- warp/_src/math.py +416 -0
- warp/_src/optim/__init__.py +14 -0
- warp/_src/optim/adam.py +165 -0
- warp/_src/optim/linear.py +1608 -0
- warp/_src/optim/sgd.py +114 -0
- warp/_src/paddle.py +408 -0
- warp/_src/render/__init__.py +14 -0
- warp/_src/render/imgui_manager.py +291 -0
- warp/_src/render/render_opengl.py +3638 -0
- warp/_src/render/render_usd.py +939 -0
- warp/_src/render/utils.py +162 -0
- warp/_src/sparse.py +2718 -0
- warp/_src/tape.py +1208 -0
- warp/_src/thirdparty/__init__.py +0 -0
- warp/_src/thirdparty/appdirs.py +598 -0
- warp/_src/thirdparty/dlpack.py +145 -0
- warp/_src/thirdparty/unittest_parallel.py +676 -0
- warp/_src/torch.py +393 -0
- warp/_src/types.py +5888 -0
- warp/_src/utils.py +1695 -0
- warp/autograd.py +33 -0
- warp/bin/libwarp-clang.dylib +0 -0
- warp/bin/libwarp.dylib +0 -0
- warp/build.py +29 -0
- warp/build_dll.py +24 -0
- warp/codegen.py +24 -0
- warp/constants.py +24 -0
- warp/context.py +33 -0
- warp/dlpack.py +24 -0
- warp/examples/__init__.py +24 -0
- warp/examples/assets/bear.usd +0 -0
- warp/examples/assets/bunny.usd +0 -0
- warp/examples/assets/cube.usd +0 -0
- warp/examples/assets/nonuniform.usd +0 -0
- warp/examples/assets/nvidia_logo.png +0 -0
- warp/examples/assets/pixel.jpg +0 -0
- warp/examples/assets/rocks.nvdb +0 -0
- warp/examples/assets/rocks.usd +0 -0
- warp/examples/assets/sphere.usd +0 -0
- warp/examples/assets/square_cloth.usd +0 -0
- warp/examples/benchmarks/benchmark_api.py +389 -0
- warp/examples/benchmarks/benchmark_cloth.py +296 -0
- warp/examples/benchmarks/benchmark_cloth_cupy.py +96 -0
- warp/examples/benchmarks/benchmark_cloth_jax.py +105 -0
- warp/examples/benchmarks/benchmark_cloth_numba.py +161 -0
- warp/examples/benchmarks/benchmark_cloth_numpy.py +85 -0
- warp/examples/benchmarks/benchmark_cloth_paddle.py +94 -0
- warp/examples/benchmarks/benchmark_cloth_pytorch.py +94 -0
- warp/examples/benchmarks/benchmark_cloth_taichi.py +120 -0
- warp/examples/benchmarks/benchmark_cloth_warp.py +153 -0
- warp/examples/benchmarks/benchmark_gemm.py +164 -0
- warp/examples/benchmarks/benchmark_interop_paddle.py +166 -0
- warp/examples/benchmarks/benchmark_interop_torch.py +166 -0
- warp/examples/benchmarks/benchmark_launches.py +301 -0
- warp/examples/benchmarks/benchmark_tile_load_store.py +103 -0
- warp/examples/benchmarks/benchmark_tile_sort.py +155 -0
- warp/examples/browse.py +37 -0
- warp/examples/core/example_cupy.py +86 -0
- warp/examples/core/example_dem.py +241 -0
- warp/examples/core/example_fluid.py +299 -0
- warp/examples/core/example_graph_capture.py +150 -0
- warp/examples/core/example_marching_cubes.py +195 -0
- warp/examples/core/example_mesh.py +180 -0
- warp/examples/core/example_mesh_intersect.py +211 -0
- warp/examples/core/example_nvdb.py +182 -0
- warp/examples/core/example_raycast.py +111 -0
- warp/examples/core/example_raymarch.py +205 -0
- warp/examples/core/example_render_opengl.py +290 -0
- warp/examples/core/example_sample_mesh.py +300 -0
- warp/examples/core/example_sph.py +411 -0
- warp/examples/core/example_spin_lock.py +93 -0
- warp/examples/core/example_torch.py +211 -0
- warp/examples/core/example_wave.py +269 -0
- warp/examples/core/example_work_queue.py +118 -0
- warp/examples/distributed/example_jacobi_mpi.py +506 -0
- warp/examples/fem/example_adaptive_grid.py +286 -0
- warp/examples/fem/example_apic_fluid.py +469 -0
- warp/examples/fem/example_burgers.py +261 -0
- warp/examples/fem/example_convection_diffusion.py +181 -0
- warp/examples/fem/example_convection_diffusion_dg.py +225 -0
- warp/examples/fem/example_darcy_ls_optimization.py +489 -0
- warp/examples/fem/example_deformed_geometry.py +172 -0
- warp/examples/fem/example_diffusion.py +196 -0
- warp/examples/fem/example_diffusion_3d.py +225 -0
- warp/examples/fem/example_diffusion_mgpu.py +225 -0
- warp/examples/fem/example_distortion_energy.py +228 -0
- warp/examples/fem/example_elastic_shape_optimization.py +387 -0
- warp/examples/fem/example_magnetostatics.py +242 -0
- warp/examples/fem/example_mixed_elasticity.py +293 -0
- warp/examples/fem/example_navier_stokes.py +263 -0
- warp/examples/fem/example_nonconforming_contact.py +300 -0
- warp/examples/fem/example_stokes.py +213 -0
- warp/examples/fem/example_stokes_transfer.py +262 -0
- warp/examples/fem/example_streamlines.py +357 -0
- warp/examples/fem/utils.py +1047 -0
- warp/examples/interop/example_jax_callable.py +146 -0
- warp/examples/interop/example_jax_ffi_callback.py +132 -0
- warp/examples/interop/example_jax_kernel.py +232 -0
- warp/examples/optim/example_diffray.py +561 -0
- warp/examples/optim/example_fluid_checkpoint.py +497 -0
- warp/examples/tile/example_tile_block_cholesky.py +502 -0
- warp/examples/tile/example_tile_cholesky.py +88 -0
- warp/examples/tile/example_tile_convolution.py +66 -0
- warp/examples/tile/example_tile_fft.py +55 -0
- warp/examples/tile/example_tile_filtering.py +113 -0
- warp/examples/tile/example_tile_matmul.py +85 -0
- warp/examples/tile/example_tile_mcgp.py +191 -0
- warp/examples/tile/example_tile_mlp.py +385 -0
- warp/examples/tile/example_tile_nbody.py +199 -0
- warp/fabric.py +24 -0
- warp/fem/__init__.py +173 -0
- warp/fem/adaptivity.py +26 -0
- warp/fem/cache.py +30 -0
- warp/fem/dirichlet.py +24 -0
- warp/fem/field/__init__.py +24 -0
- warp/fem/field/field.py +26 -0
- warp/fem/geometry/__init__.py +21 -0
- warp/fem/geometry/closest_point.py +31 -0
- warp/fem/linalg.py +38 -0
- warp/fem/operator.py +32 -0
- warp/fem/polynomial.py +29 -0
- warp/fem/space/__init__.py +22 -0
- warp/fem/space/basis_space.py +24 -0
- warp/fem/space/shape/__init__.py +68 -0
- warp/fem/space/topology.py +24 -0
- warp/fem/types.py +24 -0
- warp/fem/utils.py +32 -0
- warp/jax.py +29 -0
- warp/jax_experimental/__init__.py +29 -0
- warp/jax_experimental/custom_call.py +29 -0
- warp/jax_experimental/ffi.py +39 -0
- warp/jax_experimental/xla_ffi.py +24 -0
- warp/marching_cubes.py +24 -0
- warp/math.py +37 -0
- warp/native/array.h +1687 -0
- warp/native/builtin.h +2327 -0
- warp/native/bvh.cpp +562 -0
- warp/native/bvh.cu +826 -0
- warp/native/bvh.h +555 -0
- warp/native/clang/clang.cpp +541 -0
- warp/native/coloring.cpp +622 -0
- warp/native/crt.cpp +51 -0
- warp/native/crt.h +568 -0
- warp/native/cuda_crt.h +1058 -0
- warp/native/cuda_util.cpp +677 -0
- warp/native/cuda_util.h +313 -0
- warp/native/error.cpp +77 -0
- warp/native/error.h +36 -0
- warp/native/exports.h +2023 -0
- warp/native/fabric.h +246 -0
- warp/native/hashgrid.cpp +311 -0
- warp/native/hashgrid.cu +89 -0
- warp/native/hashgrid.h +240 -0
- warp/native/initializer_array.h +41 -0
- warp/native/intersect.h +1253 -0
- warp/native/intersect_adj.h +375 -0
- warp/native/intersect_tri.h +348 -0
- warp/native/mat.h +5189 -0
- warp/native/mathdx.cpp +93 -0
- warp/native/matnn.h +221 -0
- warp/native/mesh.cpp +266 -0
- warp/native/mesh.cu +406 -0
- warp/native/mesh.h +2097 -0
- warp/native/nanovdb/GridHandle.h +533 -0
- warp/native/nanovdb/HostBuffer.h +591 -0
- warp/native/nanovdb/NanoVDB.h +6246 -0
- warp/native/nanovdb/NodeManager.h +323 -0
- warp/native/nanovdb/PNanoVDB.h +3390 -0
- warp/native/noise.h +859 -0
- warp/native/quat.h +1664 -0
- warp/native/rand.h +342 -0
- warp/native/range.h +145 -0
- warp/native/reduce.cpp +174 -0
- warp/native/reduce.cu +363 -0
- warp/native/runlength_encode.cpp +79 -0
- warp/native/runlength_encode.cu +61 -0
- warp/native/scan.cpp +47 -0
- warp/native/scan.cu +55 -0
- warp/native/scan.h +23 -0
- warp/native/solid_angle.h +466 -0
- warp/native/sort.cpp +251 -0
- warp/native/sort.cu +286 -0
- warp/native/sort.h +35 -0
- warp/native/sparse.cpp +241 -0
- warp/native/sparse.cu +435 -0
- warp/native/spatial.h +1306 -0
- warp/native/svd.h +727 -0
- warp/native/temp_buffer.h +46 -0
- warp/native/tile.h +4124 -0
- warp/native/tile_radix_sort.h +1112 -0
- warp/native/tile_reduce.h +838 -0
- warp/native/tile_scan.h +240 -0
- warp/native/tuple.h +189 -0
- warp/native/vec.h +2199 -0
- warp/native/version.h +23 -0
- warp/native/volume.cpp +501 -0
- warp/native/volume.cu +68 -0
- warp/native/volume.h +970 -0
- warp/native/volume_builder.cu +483 -0
- warp/native/volume_builder.h +52 -0
- warp/native/volume_impl.h +70 -0
- warp/native/warp.cpp +1143 -0
- warp/native/warp.cu +4604 -0
- warp/native/warp.h +358 -0
- warp/optim/__init__.py +20 -0
- warp/optim/adam.py +24 -0
- warp/optim/linear.py +35 -0
- warp/optim/sgd.py +24 -0
- warp/paddle.py +24 -0
- warp/py.typed +0 -0
- warp/render/__init__.py +22 -0
- warp/render/imgui_manager.py +29 -0
- warp/render/render_opengl.py +24 -0
- warp/render/render_usd.py +24 -0
- warp/render/utils.py +24 -0
- warp/sparse.py +51 -0
- warp/tape.py +24 -0
- warp/tests/__init__.py +1 -0
- warp/tests/__main__.py +4 -0
- warp/tests/assets/curlnoise_golden.npy +0 -0
- warp/tests/assets/mlp_golden.npy +0 -0
- warp/tests/assets/pixel.npy +0 -0
- warp/tests/assets/pnoise_golden.npy +0 -0
- warp/tests/assets/spiky.usd +0 -0
- warp/tests/assets/test_grid.nvdb +0 -0
- warp/tests/assets/test_index_grid.nvdb +0 -0
- warp/tests/assets/test_int32_grid.nvdb +0 -0
- warp/tests/assets/test_vec_grid.nvdb +0 -0
- warp/tests/assets/torus.nvdb +0 -0
- warp/tests/assets/torus.usda +105 -0
- warp/tests/aux_test_class_kernel.py +34 -0
- warp/tests/aux_test_compile_consts_dummy.py +18 -0
- warp/tests/aux_test_conditional_unequal_types_kernels.py +29 -0
- warp/tests/aux_test_dependent.py +29 -0
- warp/tests/aux_test_grad_customs.py +29 -0
- warp/tests/aux_test_instancing_gc.py +26 -0
- warp/tests/aux_test_module_aot.py +7 -0
- warp/tests/aux_test_module_unload.py +23 -0
- warp/tests/aux_test_name_clash1.py +40 -0
- warp/tests/aux_test_name_clash2.py +40 -0
- warp/tests/aux_test_reference.py +9 -0
- warp/tests/aux_test_reference_reference.py +8 -0
- warp/tests/aux_test_square.py +16 -0
- warp/tests/aux_test_unresolved_func.py +22 -0
- warp/tests/aux_test_unresolved_symbol.py +22 -0
- warp/tests/cuda/__init__.py +0 -0
- warp/tests/cuda/test_async.py +676 -0
- warp/tests/cuda/test_conditional_captures.py +1147 -0
- warp/tests/cuda/test_ipc.py +124 -0
- warp/tests/cuda/test_mempool.py +233 -0
- warp/tests/cuda/test_multigpu.py +169 -0
- warp/tests/cuda/test_peer.py +139 -0
- warp/tests/cuda/test_pinned.py +84 -0
- warp/tests/cuda/test_streams.py +691 -0
- warp/tests/geometry/__init__.py +0 -0
- warp/tests/geometry/test_bvh.py +335 -0
- warp/tests/geometry/test_hash_grid.py +259 -0
- warp/tests/geometry/test_marching_cubes.py +294 -0
- warp/tests/geometry/test_mesh.py +318 -0
- warp/tests/geometry/test_mesh_query_aabb.py +392 -0
- warp/tests/geometry/test_mesh_query_point.py +935 -0
- warp/tests/geometry/test_mesh_query_ray.py +323 -0
- warp/tests/geometry/test_volume.py +1103 -0
- warp/tests/geometry/test_volume_write.py +346 -0
- warp/tests/interop/__init__.py +0 -0
- warp/tests/interop/test_dlpack.py +730 -0
- warp/tests/interop/test_jax.py +1673 -0
- warp/tests/interop/test_paddle.py +800 -0
- warp/tests/interop/test_torch.py +1001 -0
- warp/tests/run_coverage_serial.py +39 -0
- warp/tests/test_adam.py +162 -0
- warp/tests/test_arithmetic.py +1096 -0
- warp/tests/test_array.py +3756 -0
- warp/tests/test_array_reduce.py +156 -0
- warp/tests/test_assert.py +303 -0
- warp/tests/test_atomic.py +336 -0
- warp/tests/test_atomic_bitwise.py +209 -0
- warp/tests/test_atomic_cas.py +312 -0
- warp/tests/test_bool.py +220 -0
- warp/tests/test_builtins_resolution.py +732 -0
- warp/tests/test_closest_point_edge_edge.py +327 -0
- warp/tests/test_codegen.py +974 -0
- warp/tests/test_codegen_instancing.py +1495 -0
- warp/tests/test_compile_consts.py +215 -0
- warp/tests/test_conditional.py +298 -0
- warp/tests/test_context.py +35 -0
- warp/tests/test_copy.py +319 -0
- warp/tests/test_ctypes.py +618 -0
- warp/tests/test_dense.py +73 -0
- warp/tests/test_devices.py +127 -0
- warp/tests/test_enum.py +136 -0
- warp/tests/test_examples.py +424 -0
- warp/tests/test_fabricarray.py +998 -0
- warp/tests/test_fast_math.py +72 -0
- warp/tests/test_fem.py +2204 -0
- warp/tests/test_fixedarray.py +229 -0
- warp/tests/test_fp16.py +136 -0
- warp/tests/test_func.py +501 -0
- warp/tests/test_future_annotations.py +100 -0
- warp/tests/test_generics.py +656 -0
- warp/tests/test_grad.py +893 -0
- warp/tests/test_grad_customs.py +339 -0
- warp/tests/test_grad_debug.py +341 -0
- warp/tests/test_implicit_init.py +411 -0
- warp/tests/test_import.py +45 -0
- warp/tests/test_indexedarray.py +1140 -0
- warp/tests/test_intersect.py +103 -0
- warp/tests/test_iter.py +76 -0
- warp/tests/test_large.py +177 -0
- warp/tests/test_launch.py +411 -0
- warp/tests/test_lerp.py +151 -0
- warp/tests/test_linear_solvers.py +223 -0
- warp/tests/test_lvalue.py +427 -0
- warp/tests/test_map.py +526 -0
- warp/tests/test_mat.py +3515 -0
- warp/tests/test_mat_assign_copy.py +178 -0
- warp/tests/test_mat_constructors.py +573 -0
- warp/tests/test_mat_lite.py +122 -0
- warp/tests/test_mat_scalar_ops.py +2913 -0
- warp/tests/test_math.py +212 -0
- warp/tests/test_module_aot.py +287 -0
- warp/tests/test_module_hashing.py +258 -0
- warp/tests/test_modules_lite.py +70 -0
- warp/tests/test_noise.py +252 -0
- warp/tests/test_operators.py +299 -0
- warp/tests/test_options.py +129 -0
- warp/tests/test_overwrite.py +551 -0
- warp/tests/test_print.py +408 -0
- warp/tests/test_quat.py +2653 -0
- warp/tests/test_quat_assign_copy.py +145 -0
- warp/tests/test_rand.py +339 -0
- warp/tests/test_reload.py +303 -0
- warp/tests/test_rounding.py +157 -0
- warp/tests/test_runlength_encode.py +196 -0
- warp/tests/test_scalar_ops.py +133 -0
- warp/tests/test_smoothstep.py +108 -0
- warp/tests/test_snippet.py +318 -0
- warp/tests/test_sparse.py +845 -0
- warp/tests/test_spatial.py +2859 -0
- warp/tests/test_spatial_assign_copy.py +160 -0
- warp/tests/test_special_values.py +361 -0
- warp/tests/test_static.py +640 -0
- warp/tests/test_struct.py +901 -0
- warp/tests/test_tape.py +242 -0
- warp/tests/test_transient_module.py +93 -0
- warp/tests/test_triangle_closest_point.py +192 -0
- warp/tests/test_tuple.py +361 -0
- warp/tests/test_types.py +615 -0
- warp/tests/test_utils.py +594 -0
- warp/tests/test_vec.py +1408 -0
- warp/tests/test_vec_assign_copy.py +143 -0
- warp/tests/test_vec_constructors.py +325 -0
- warp/tests/test_vec_lite.py +80 -0
- warp/tests/test_vec_scalar_ops.py +2327 -0
- warp/tests/test_verify_fp.py +100 -0
- warp/tests/test_version.py +75 -0
- warp/tests/tile/__init__.py +0 -0
- warp/tests/tile/test_tile.py +1519 -0
- warp/tests/tile/test_tile_atomic_bitwise.py +403 -0
- warp/tests/tile/test_tile_cholesky.py +608 -0
- warp/tests/tile/test_tile_load.py +724 -0
- warp/tests/tile/test_tile_mathdx.py +156 -0
- warp/tests/tile/test_tile_matmul.py +179 -0
- warp/tests/tile/test_tile_mlp.py +400 -0
- warp/tests/tile/test_tile_reduce.py +950 -0
- warp/tests/tile/test_tile_shared_memory.py +376 -0
- warp/tests/tile/test_tile_sort.py +121 -0
- warp/tests/tile/test_tile_view.py +173 -0
- warp/tests/unittest_serial.py +47 -0
- warp/tests/unittest_suites.py +430 -0
- warp/tests/unittest_utils.py +469 -0
- warp/tests/walkthrough_debug.py +95 -0
- warp/torch.py +24 -0
- warp/types.py +51 -0
- warp/utils.py +31 -0
- warp_lang-1.10.0.dist-info/METADATA +459 -0
- warp_lang-1.10.0.dist-info/RECORD +468 -0
- warp_lang-1.10.0.dist-info/WHEEL +5 -0
- warp_lang-1.10.0.dist-info/licenses/LICENSE.md +176 -0
- warp_lang-1.10.0.dist-info/licenses/licenses/Gaia-LICENSE.txt +6 -0
- warp_lang-1.10.0.dist-info/licenses/licenses/appdirs-LICENSE.txt +22 -0
- warp_lang-1.10.0.dist-info/licenses/licenses/asset_pixel_jpg-LICENSE.txt +3 -0
- warp_lang-1.10.0.dist-info/licenses/licenses/cuda-LICENSE.txt +1582 -0
- warp_lang-1.10.0.dist-info/licenses/licenses/dlpack-LICENSE.txt +201 -0
- warp_lang-1.10.0.dist-info/licenses/licenses/fp16-LICENSE.txt +28 -0
- warp_lang-1.10.0.dist-info/licenses/licenses/libmathdx-LICENSE.txt +220 -0
- warp_lang-1.10.0.dist-info/licenses/licenses/llvm-LICENSE.txt +279 -0
- warp_lang-1.10.0.dist-info/licenses/licenses/moller-LICENSE.txt +16 -0
- warp_lang-1.10.0.dist-info/licenses/licenses/nanovdb-LICENSE.txt +2 -0
- warp_lang-1.10.0.dist-info/licenses/licenses/nvrtc-LICENSE.txt +1592 -0
- warp_lang-1.10.0.dist-info/licenses/licenses/svd-LICENSE.txt +23 -0
- warp_lang-1.10.0.dist-info/licenses/licenses/unittest_parallel-LICENSE.txt +21 -0
- warp_lang-1.10.0.dist-info/licenses/licenses/usd-LICENSE.txt +213 -0
- warp_lang-1.10.0.dist-info/licenses/licenses/windingnumber-LICENSE.txt +21 -0
- 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": {}}})
|