warp-lang 1.6.2__py3-none-win_amd64.whl → 1.7.1__py3-none-win_amd64.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 (191) hide show
  1. warp/__init__.py +7 -1
  2. warp/autograd.py +12 -2
  3. warp/bin/warp-clang.dll +0 -0
  4. warp/bin/warp.dll +0 -0
  5. warp/build.py +410 -0
  6. warp/build_dll.py +6 -14
  7. warp/builtins.py +463 -372
  8. warp/codegen.py +196 -124
  9. warp/config.py +42 -6
  10. warp/context.py +496 -271
  11. warp/dlpack.py +8 -6
  12. warp/examples/assets/nonuniform.usd +0 -0
  13. warp/examples/assets/nvidia_logo.png +0 -0
  14. warp/examples/benchmarks/benchmark_cloth.py +1 -1
  15. warp/examples/benchmarks/benchmark_tile_load_store.py +103 -0
  16. warp/examples/core/example_sample_mesh.py +300 -0
  17. warp/examples/distributed/example_jacobi_mpi.py +507 -0
  18. warp/examples/fem/example_apic_fluid.py +1 -1
  19. warp/examples/fem/example_burgers.py +2 -2
  20. warp/examples/fem/example_deformed_geometry.py +1 -1
  21. warp/examples/fem/example_distortion_energy.py +1 -1
  22. warp/examples/fem/example_magnetostatics.py +6 -6
  23. warp/examples/fem/utils.py +9 -3
  24. warp/examples/interop/example_jax_callable.py +116 -0
  25. warp/examples/interop/example_jax_ffi_callback.py +132 -0
  26. warp/examples/interop/example_jax_kernel.py +205 -0
  27. warp/examples/optim/example_fluid_checkpoint.py +497 -0
  28. warp/examples/tile/example_tile_matmul.py +2 -4
  29. warp/fem/__init__.py +11 -1
  30. warp/fem/adaptivity.py +4 -4
  31. warp/fem/field/field.py +11 -1
  32. warp/fem/field/nodal_field.py +56 -88
  33. warp/fem/field/virtual.py +62 -23
  34. warp/fem/geometry/adaptive_nanogrid.py +16 -13
  35. warp/fem/geometry/closest_point.py +1 -1
  36. warp/fem/geometry/deformed_geometry.py +5 -2
  37. warp/fem/geometry/geometry.py +5 -0
  38. warp/fem/geometry/grid_2d.py +12 -12
  39. warp/fem/geometry/grid_3d.py +12 -15
  40. warp/fem/geometry/hexmesh.py +5 -7
  41. warp/fem/geometry/nanogrid.py +9 -11
  42. warp/fem/geometry/quadmesh.py +13 -13
  43. warp/fem/geometry/tetmesh.py +3 -4
  44. warp/fem/geometry/trimesh.py +7 -20
  45. warp/fem/integrate.py +262 -93
  46. warp/fem/linalg.py +5 -5
  47. warp/fem/quadrature/pic_quadrature.py +37 -22
  48. warp/fem/quadrature/quadrature.py +194 -25
  49. warp/fem/space/__init__.py +1 -1
  50. warp/fem/space/basis_function_space.py +4 -2
  51. warp/fem/space/basis_space.py +25 -18
  52. warp/fem/space/hexmesh_function_space.py +2 -2
  53. warp/fem/space/partition.py +6 -2
  54. warp/fem/space/quadmesh_function_space.py +8 -8
  55. warp/fem/space/shape/cube_shape_function.py +23 -23
  56. warp/fem/space/shape/square_shape_function.py +12 -12
  57. warp/fem/space/shape/triangle_shape_function.py +1 -1
  58. warp/fem/space/tetmesh_function_space.py +3 -3
  59. warp/fem/space/trimesh_function_space.py +2 -2
  60. warp/fem/utils.py +12 -6
  61. warp/jax.py +14 -1
  62. warp/jax_experimental/__init__.py +16 -0
  63. warp/{jax_experimental.py → jax_experimental/custom_call.py} +28 -29
  64. warp/jax_experimental/ffi.py +702 -0
  65. warp/jax_experimental/xla_ffi.py +602 -0
  66. warp/math.py +89 -0
  67. warp/native/array.h +13 -0
  68. warp/native/builtin.h +29 -3
  69. warp/native/bvh.cpp +3 -1
  70. warp/native/bvh.cu +42 -14
  71. warp/native/bvh.h +2 -1
  72. warp/native/clang/clang.cpp +30 -3
  73. warp/native/cuda_util.cpp +14 -0
  74. warp/native/cuda_util.h +2 -0
  75. warp/native/exports.h +68 -63
  76. warp/native/intersect.h +26 -26
  77. warp/native/intersect_adj.h +33 -33
  78. warp/native/marching.cu +1 -1
  79. warp/native/mat.h +513 -9
  80. warp/native/mesh.h +10 -10
  81. warp/native/quat.h +99 -11
  82. warp/native/rand.h +6 -0
  83. warp/native/sort.cpp +122 -59
  84. warp/native/sort.cu +152 -15
  85. warp/native/sort.h +8 -1
  86. warp/native/sparse.cpp +43 -22
  87. warp/native/sparse.cu +52 -17
  88. warp/native/svd.h +116 -0
  89. warp/native/tile.h +312 -116
  90. warp/native/tile_reduce.h +46 -3
  91. warp/native/vec.h +68 -7
  92. warp/native/volume.cpp +85 -113
  93. warp/native/volume_builder.cu +25 -10
  94. warp/native/volume_builder.h +6 -0
  95. warp/native/warp.cpp +5 -6
  96. warp/native/warp.cu +100 -11
  97. warp/native/warp.h +19 -10
  98. warp/optim/linear.py +10 -10
  99. warp/render/render_opengl.py +19 -17
  100. warp/render/render_usd.py +93 -3
  101. warp/sim/articulation.py +4 -4
  102. warp/sim/collide.py +32 -19
  103. warp/sim/import_mjcf.py +449 -155
  104. warp/sim/import_urdf.py +32 -12
  105. warp/sim/inertia.py +189 -156
  106. warp/sim/integrator_euler.py +8 -5
  107. warp/sim/integrator_featherstone.py +3 -10
  108. warp/sim/integrator_vbd.py +207 -2
  109. warp/sim/integrator_xpbd.py +8 -5
  110. warp/sim/model.py +71 -25
  111. warp/sim/render.py +4 -0
  112. warp/sim/utils.py +2 -2
  113. warp/sparse.py +642 -555
  114. warp/stubs.py +217 -20
  115. warp/tests/__main__.py +0 -15
  116. warp/tests/assets/torus.usda +1 -1
  117. warp/tests/cuda/__init__.py +0 -0
  118. warp/tests/{test_mempool.py → cuda/test_mempool.py} +39 -0
  119. warp/tests/{test_streams.py → cuda/test_streams.py} +71 -0
  120. warp/tests/geometry/__init__.py +0 -0
  121. warp/tests/{test_mesh_query_point.py → geometry/test_mesh_query_point.py} +66 -63
  122. warp/tests/{test_mesh_query_ray.py → geometry/test_mesh_query_ray.py} +1 -1
  123. warp/tests/{test_volume.py → geometry/test_volume.py} +41 -6
  124. warp/tests/interop/__init__.py +0 -0
  125. warp/tests/{test_dlpack.py → interop/test_dlpack.py} +28 -5
  126. warp/tests/sim/__init__.py +0 -0
  127. warp/tests/{disabled_kinematics.py → sim/disabled_kinematics.py} +9 -10
  128. warp/tests/{test_collision.py → sim/test_collision.py} +236 -205
  129. warp/tests/sim/test_inertia.py +161 -0
  130. warp/tests/{test_model.py → sim/test_model.py} +40 -0
  131. warp/tests/{flaky_test_sim_grad.py → sim/test_sim_grad.py} +4 -0
  132. warp/tests/{test_sim_kinematics.py → sim/test_sim_kinematics.py} +2 -1
  133. warp/tests/sim/test_vbd.py +597 -0
  134. warp/tests/sim/test_xpbd.py +399 -0
  135. warp/tests/test_bool.py +1 -1
  136. warp/tests/test_codegen.py +24 -3
  137. warp/tests/test_examples.py +40 -38
  138. warp/tests/test_fem.py +98 -14
  139. warp/tests/test_linear_solvers.py +0 -11
  140. warp/tests/test_mat.py +577 -156
  141. warp/tests/test_mat_scalar_ops.py +4 -4
  142. warp/tests/test_overwrite.py +0 -60
  143. warp/tests/test_quat.py +356 -151
  144. warp/tests/test_rand.py +44 -37
  145. warp/tests/test_sparse.py +47 -6
  146. warp/tests/test_spatial.py +75 -0
  147. warp/tests/test_static.py +1 -1
  148. warp/tests/test_utils.py +84 -4
  149. warp/tests/test_vec.py +336 -178
  150. warp/tests/tile/__init__.py +0 -0
  151. warp/tests/{test_tile.py → tile/test_tile.py} +136 -51
  152. warp/tests/{test_tile_load.py → tile/test_tile_load.py} +98 -1
  153. warp/tests/{test_tile_mathdx.py → tile/test_tile_mathdx.py} +9 -6
  154. warp/tests/{test_tile_mlp.py → tile/test_tile_mlp.py} +25 -14
  155. warp/tests/{test_tile_reduce.py → tile/test_tile_reduce.py} +60 -1
  156. warp/tests/{test_tile_view.py → tile/test_tile_view.py} +1 -1
  157. warp/tests/unittest_serial.py +1 -0
  158. warp/tests/unittest_suites.py +45 -62
  159. warp/tests/unittest_utils.py +2 -1
  160. warp/thirdparty/unittest_parallel.py +3 -1
  161. warp/types.py +175 -666
  162. warp/utils.py +137 -72
  163. {warp_lang-1.6.2.dist-info → warp_lang-1.7.1.dist-info}/METADATA +46 -12
  164. {warp_lang-1.6.2.dist-info → warp_lang-1.7.1.dist-info}/RECORD +184 -171
  165. {warp_lang-1.6.2.dist-info → warp_lang-1.7.1.dist-info}/WHEEL +1 -1
  166. {warp_lang-1.6.2.dist-info → warp_lang-1.7.1.dist-info/licenses}/LICENSE.md +0 -26
  167. warp/examples/optim/example_walker.py +0 -317
  168. warp/native/cutlass_gemm.cpp +0 -43
  169. warp/native/cutlass_gemm.cu +0 -382
  170. warp/tests/test_matmul.py +0 -511
  171. warp/tests/test_matmul_lite.py +0 -411
  172. warp/tests/test_vbd.py +0 -386
  173. warp/tests/unused_test_misc.py +0 -77
  174. /warp/tests/{test_async.py → cuda/test_async.py} +0 -0
  175. /warp/tests/{test_ipc.py → cuda/test_ipc.py} +0 -0
  176. /warp/tests/{test_multigpu.py → cuda/test_multigpu.py} +0 -0
  177. /warp/tests/{test_peer.py → cuda/test_peer.py} +0 -0
  178. /warp/tests/{test_pinned.py → cuda/test_pinned.py} +0 -0
  179. /warp/tests/{test_bvh.py → geometry/test_bvh.py} +0 -0
  180. /warp/tests/{test_hash_grid.py → geometry/test_hash_grid.py} +0 -0
  181. /warp/tests/{test_marching_cubes.py → geometry/test_marching_cubes.py} +0 -0
  182. /warp/tests/{test_mesh.py → geometry/test_mesh.py} +0 -0
  183. /warp/tests/{test_mesh_query_aabb.py → geometry/test_mesh_query_aabb.py} +0 -0
  184. /warp/tests/{test_volume_write.py → geometry/test_volume_write.py} +0 -0
  185. /warp/tests/{test_jax.py → interop/test_jax.py} +0 -0
  186. /warp/tests/{test_paddle.py → interop/test_paddle.py} +0 -0
  187. /warp/tests/{test_torch.py → interop/test_torch.py} +0 -0
  188. /warp/tests/{test_coloring.py → sim/test_coloring.py} +0 -0
  189. /warp/tests/{test_sim_grad_bounce_linear.py → sim/test_sim_grad_bounce_linear.py} +0 -0
  190. /warp/tests/{test_tile_shared_memory.py → tile/test_tile_shared_memory.py} +0 -0
  191. {warp_lang-1.6.2.dist-info → warp_lang-1.7.1.dist-info}/top_level.txt +0 -0
@@ -346,6 +346,172 @@ def evaluate_stvk_force_hessian(
346
346
  return f, h
347
347
 
348
348
 
349
+ @wp.func
350
+ def mat_vec_cross_from_3_basis(e1: wp.vec3, e2: wp.vec3, e3: wp.vec3, a: wp.vec3):
351
+ e1_cross_a = wp.cross(e1, a)
352
+ e2_cross_a = wp.cross(e2, a)
353
+ e3_cross_a = wp.cross(e3, a)
354
+
355
+ return wp.mat33(
356
+ e1_cross_a[0],
357
+ e2_cross_a[0],
358
+ e3_cross_a[0],
359
+ e1_cross_a[1],
360
+ e2_cross_a[1],
361
+ e3_cross_a[1],
362
+ e1_cross_a[2],
363
+ e2_cross_a[2],
364
+ e3_cross_a[2],
365
+ )
366
+
367
+
368
+ @wp.func
369
+ def mat_vec_cross(mat: wp.mat33, a: wp.vec3):
370
+ e1 = wp.vec3(mat[0, 0], mat[1, 0], mat[2, 0])
371
+ e2 = wp.vec3(mat[0, 1], mat[1, 1], mat[2, 1])
372
+ e3 = wp.vec3(mat[0, 2], mat[1, 2], mat[2, 2])
373
+
374
+ return mat_vec_cross_from_3_basis(e1, e2, e3, a)
375
+
376
+
377
+ @wp.func
378
+ def evaluate_dihedral_angle_based_bending_force_hessian(
379
+ bending_index: int,
380
+ v_order: int,
381
+ pos: wp.array(dtype=wp.vec3),
382
+ pos_prev: wp.array(dtype=wp.vec3),
383
+ edge_indices: wp.array(dtype=wp.int32, ndim=2),
384
+ edge_rest_angle: wp.array(dtype=float),
385
+ edge_rest_length: wp.array(dtype=float),
386
+ stiffness: float,
387
+ damping: float,
388
+ dt: float,
389
+ ):
390
+ if edge_indices[bending_index, 0] == -1 or edge_indices[bending_index, 1] == -1:
391
+ return wp.vec3(0.0), wp.mat33(0.0)
392
+
393
+ x1 = pos[edge_indices[bending_index, 0]]
394
+ x2 = pos[edge_indices[bending_index, 2]]
395
+ x3 = pos[edge_indices[bending_index, 3]]
396
+ x4 = pos[edge_indices[bending_index, 1]]
397
+
398
+ e1 = wp.vec3(1.0, 0.0, 0.0)
399
+ e2 = wp.vec3(0.0, 1.0, 0.0)
400
+ e3 = wp.vec3(0.0, 0.0, 1.0)
401
+
402
+ n1 = wp.cross((x2 - x1), (x3 - x1))
403
+ n2 = wp.cross((x3 - x4), (x2 - x4))
404
+ n1_norm = wp.length(n1)
405
+ n2_norm = wp.length(n2)
406
+
407
+ # degenerated bending edge
408
+ if n1_norm < 1.0e-6 or n2_norm < 1.0e-6:
409
+ return wp.vec3(0.0), wp.mat33(0.0)
410
+
411
+ n1_n = n1 / n1_norm
412
+ n2_n = n2 / n2_norm
413
+
414
+ # avoid the infinite gradient of acos at -1 or 1
415
+ cos_theta = wp.dot(n1_n, n2_n)
416
+ if wp.abs(cos_theta) > 0.9999:
417
+ cos_theta = 0.9999 * wp.sign(cos_theta)
418
+
419
+ angle_sign = wp.sign(wp.dot(wp.cross(n2, n1), x3 - x2))
420
+ theta = wp.acos(cos_theta) * angle_sign
421
+ rest_angle = edge_rest_angle[bending_index]
422
+
423
+ dE_dtheta = stiffness * (theta - rest_angle)
424
+
425
+ d_theta_d_cos_theta = angle_sign * (-1.0 / wp.sqrt(1.0 - cos_theta * cos_theta))
426
+ sin_theta = angle_sign * wp.sqrt(1.0 - cos_theta * cos_theta)
427
+ one_over_sin_theta = 1.0 / sin_theta
428
+ d_one_over_sin_theta_d_cos_theta = cos_theta / (sin_theta * sin_theta * sin_theta)
429
+
430
+ e_rest_len = edge_rest_length[bending_index]
431
+
432
+ if v_order == 0:
433
+ d_cos_theta_dx1 = 1.0 / n1_norm * (-wp.cross(x3 - x1, n2_n) + wp.cross(x2 - x1, n2_n))
434
+ d_one_over_sin_theta_dx1 = d_cos_theta_dx1 * d_one_over_sin_theta_d_cos_theta
435
+
436
+ d_theta_dx1 = d_theta_d_cos_theta * d_cos_theta_dx1
437
+ d2_theta_dx1_dx1 = -wp.outer(d_one_over_sin_theta_dx1, d_cos_theta_dx1)
438
+
439
+ dE_dx1 = e_rest_len * dE_dtheta * d_theta_d_cos_theta * d_cos_theta_dx1
440
+
441
+ d2_E_dx1_dx1 = (
442
+ e_rest_len * stiffness * (wp.outer(d_theta_dx1, d_theta_dx1) + (theta - rest_angle) * d2_theta_dx1_dx1)
443
+ )
444
+
445
+ bending_force = -dE_dx1
446
+ bending_hessian = d2_E_dx1_dx1
447
+ elif v_order == 1:
448
+ d_cos_theta_dx4 = 1.0 / n2_norm * (-wp.cross(x2 - x4, n1_n) + wp.cross(x3 - x4, n1_n))
449
+ d_one_over_sin_theta_dx4 = d_cos_theta_dx4 * d_one_over_sin_theta_d_cos_theta
450
+
451
+ d_theta_dx4 = d_theta_d_cos_theta * d_cos_theta_dx4
452
+ d2_theta_dx4_dx4 = -wp.outer(d_one_over_sin_theta_dx4, d_cos_theta_dx4)
453
+
454
+ dE_dx4 = e_rest_len * dE_dtheta * d_theta_d_cos_theta * d_cos_theta_dx4
455
+ d2_E_dx4_dx4 = (
456
+ e_rest_len * stiffness * (wp.outer(d_theta_dx4, d_theta_dx4) + (theta - rest_angle) * (d2_theta_dx4_dx4))
457
+ )
458
+
459
+ bending_force = -dE_dx4
460
+ bending_hessian = d2_E_dx4_dx4
461
+ elif v_order == 2:
462
+ d_cos_theta_dx2 = 1.0 / n1_norm * wp.cross(x3 - x1, n2_n) - 1.0 / n2_norm * wp.cross(x3 - x4, n1_n)
463
+ dn1_dx2 = mat_vec_cross_from_3_basis(e1, e2, e3, x3 - x1)
464
+ dn2_dx2 = -mat_vec_cross_from_3_basis(e1, e2, e3, x3 - x4)
465
+ d_one_over_sin_theta_dx2 = d_cos_theta_dx2 * d_one_over_sin_theta_d_cos_theta
466
+ d2_cos_theta_dx2_dx2 = -mat_vec_cross(dn2_dx2, (x3 - x1)) / (n1_norm * n2_norm) + mat_vec_cross(
467
+ dn1_dx2, x3 - x4
468
+ ) / (n1_norm * n2_norm)
469
+
470
+ d_theta_dx2 = d_theta_d_cos_theta * d_cos_theta_dx2
471
+ d2_theta_dx2_dx2 = (
472
+ -wp.outer(d_one_over_sin_theta_dx2, d_cos_theta_dx2) - one_over_sin_theta * d2_cos_theta_dx2_dx2
473
+ )
474
+
475
+ dE_dx2 = e_rest_len * dE_dtheta * d_theta_d_cos_theta * d_cos_theta_dx2
476
+ d2_E_dx2_dx2 = (
477
+ e_rest_len * stiffness * (wp.outer(d_theta_dx2, d_theta_dx2) + (theta - rest_angle) * d2_theta_dx2_dx2)
478
+ )
479
+
480
+ bending_force = -dE_dx2
481
+ bending_hessian = d2_E_dx2_dx2
482
+ else:
483
+ d_cos_theta_dx3 = -1.0 / n1_norm * wp.cross(x2 - x1, n2_n) + 1.0 / n2_norm * wp.cross(x2 - x4, n1_n)
484
+ dn1_dx3 = -mat_vec_cross_from_3_basis(e1, e2, e3, x2 - x1)
485
+ dn2_dx3 = mat_vec_cross_from_3_basis(e1, e2, e3, x2 - x4)
486
+ d_one_over_sin_theta_dx3 = d_cos_theta_dx3 * d_one_over_sin_theta_d_cos_theta
487
+ d2_cos_theta_dx3_dx3 = mat_vec_cross(dn2_dx3, (x2 - x1)) / (n1_norm * n2_norm) - mat_vec_cross(
488
+ dn1_dx3, x2 - x4
489
+ ) / (n1_norm * n2_norm)
490
+
491
+ d_theta_dx3 = d_theta_d_cos_theta * d_cos_theta_dx3
492
+ d2_theta_dx3_dx3 = (
493
+ -wp.outer(d_one_over_sin_theta_dx3, d_cos_theta_dx3) - one_over_sin_theta * d2_cos_theta_dx3_dx3
494
+ )
495
+
496
+ dE_dx3 = e_rest_len * dE_dtheta * d_theta_d_cos_theta * d_cos_theta_dx3
497
+
498
+ d2_E_dx3_dx3 = (
499
+ e_rest_len * stiffness * (wp.outer(d_theta_dx3, d_theta_dx3) + (theta - rest_angle) * d2_theta_dx3_dx3)
500
+ )
501
+
502
+ bending_force = -dE_dx3
503
+ bending_hessian = d2_E_dx3_dx3
504
+
505
+ displacement = pos_prev[edge_indices[bending_index, v_order]] - pos[edge_indices[bending_index, v_order]]
506
+ h_d = bending_hessian * (damping / dt)
507
+ f_d = h_d * displacement
508
+
509
+ bending_force = bending_force + f_d
510
+ bending_hessian = bending_hessian + h_d
511
+
512
+ return bending_force, bending_hessian
513
+
514
+
349
515
  @wp.func
350
516
  def evaluate_ground_contact_force_hessian(
351
517
  particle_pos: wp.vec3,
@@ -866,6 +1032,9 @@ def VBD_solve_trimesh_no_self_contact(
866
1032
  tri_materials: wp.array(dtype=float, ndim=2),
867
1033
  tri_areas: wp.array(dtype=float),
868
1034
  edge_indices: wp.array(dtype=wp.int32, ndim=2),
1035
+ edge_rest_angles: wp.array(dtype=float),
1036
+ edge_rest_length: wp.array(dtype=float),
1037
+ edge_bending_properties: wp.array(dtype=float, ndim=2),
869
1038
  adjacency: ForceElementAdjacencyInfo,
870
1039
  # contact info
871
1040
  # self contact
@@ -957,6 +1126,24 @@ def VBD_solve_trimesh_no_self_contact(
957
1126
  )
958
1127
  # fmt: on
959
1128
 
1129
+ for i_adj_edge in range(get_vertex_num_adjacent_edges(adjacency, particle_index)):
1130
+ nei_edge_index, vertex_order_on_edge = get_vertex_adjacent_edge_id_order(adjacency, particle_index, i_adj_edge)
1131
+ f_edge, h_edge = evaluate_dihedral_angle_based_bending_force_hessian(
1132
+ nei_edge_index,
1133
+ vertex_order_on_edge,
1134
+ pos,
1135
+ prev_pos,
1136
+ edge_indices,
1137
+ edge_rest_angles,
1138
+ edge_rest_length,
1139
+ edge_bending_properties[nei_edge_index, 0],
1140
+ edge_bending_properties[nei_edge_index, 1],
1141
+ dt,
1142
+ )
1143
+
1144
+ f = f + f_edge
1145
+ h = h + h_edge
1146
+
960
1147
  # body-particle contact
961
1148
  particle_contact_count = min(body_particle_contact_count[particle_index], body_particle_contact_buffer_pre_alloc)
962
1149
 
@@ -1072,6 +1259,9 @@ def VBD_solve_trimesh_with_self_contact_penetration_free(
1072
1259
  tri_materials: wp.array(dtype=float, ndim=2),
1073
1260
  tri_areas: wp.array(dtype=float),
1074
1261
  edge_indices: wp.array(dtype=wp.int32, ndim=2),
1262
+ edge_rest_angles: wp.array(dtype=float),
1263
+ edge_rest_length: wp.array(dtype=float),
1264
+ edge_bending_properties: wp.array(dtype=float, ndim=2),
1075
1265
  adjacency: ForceElementAdjacencyInfo,
1076
1266
  # contact info
1077
1267
  # self contact
@@ -1239,6 +1429,15 @@ def VBD_solve_trimesh_with_self_contact_penetration_free(
1239
1429
  for i_adj_edge in range(get_vertex_num_adjacent_edges(adjacency, particle_index)):
1240
1430
  nei_edge_index, vertex_order_on_edge = get_vertex_adjacent_edge_id_order(adjacency, particle_index, i_adj_edge)
1241
1431
  # vertex is on the edge; otherwise it only effects the bending energy n
1432
+ if edge_bending_properties[nei_edge_index, 0] != 0:
1433
+ f_edge, h_edge = evaluate_dihedral_angle_based_bending_force_hessian(
1434
+ nei_edge_index, vertex_order_on_edge, pos, pos_prev, edge_indices, edge_rest_angles, edge_rest_length,
1435
+ edge_bending_properties[nei_edge_index, 0], edge_bending_properties[nei_edge_index, 1], dt
1436
+ )
1437
+
1438
+ f = f + f_edge
1439
+ h = h + h_edge
1440
+
1242
1441
  if vertex_order_on_edge == 2 or vertex_order_on_edge == 3:
1243
1442
  # collisions of neighbor triangles
1244
1443
  if wp.static("contact_info" in VBD_DEBUG_PRINTING_OPTIONS):
@@ -1572,6 +1771,9 @@ class VBDIntegrator(Integrator):
1572
1771
  self.model.tri_materials,
1573
1772
  self.model.tri_areas,
1574
1773
  self.model.edge_indices,
1774
+ self.model.edge_rest_angle,
1775
+ self.model.edge_rest_length,
1776
+ self.model.edge_bending_properties,
1575
1777
  self.adjacency,
1576
1778
  self.model.soft_contact_ke,
1577
1779
  self.model.soft_contact_mu,
@@ -1659,6 +1861,9 @@ class VBDIntegrator(Integrator):
1659
1861
  self.model.tri_materials,
1660
1862
  self.model.tri_areas,
1661
1863
  self.model.edge_indices,
1864
+ self.model.edge_rest_angle,
1865
+ self.model.edge_rest_length,
1866
+ self.model.edge_bending_properties,
1662
1867
  self.adjacency,
1663
1868
  # self-contact
1664
1869
  self.trimesh_collision_detector.collision_info,
@@ -1783,7 +1988,7 @@ class VBDIntegrator(Integrator):
1783
1988
  vertex_adjacent_edges[buffer_offset_v1 + fill_count_v1 * 2 + 1] = 3
1784
1989
  vertex_adjacent_edges_fill_count[v1] = fill_count_v1 + 1
1785
1990
 
1786
- o0 = edges_array[edge_id, 2]
1991
+ o0 = edges_array[edge_id, 0]
1787
1992
  if o0 != -1:
1788
1993
  fill_count_o0 = vertex_adjacent_edges_fill_count[o0]
1789
1994
  buffer_offset_o0 = vertex_adjacent_edges_offsets[o0]
@@ -1791,7 +1996,7 @@ class VBDIntegrator(Integrator):
1791
1996
  vertex_adjacent_edges[buffer_offset_o0 + fill_count_o0 * 2 + 1] = 0
1792
1997
  vertex_adjacent_edges_fill_count[o0] = fill_count_o0 + 1
1793
1998
 
1794
- o1 = edges_array[edge_id, 3]
1999
+ o1 = edges_array[edge_id, 1]
1795
2000
  if o1 != -1:
1796
2001
  fill_count_o1 = vertex_adjacent_edges_fill_count[o1]
1797
2002
  buffer_offset_o1 = vertex_adjacent_edges_offsets[o1]
@@ -401,6 +401,9 @@ def solve_springs(
401
401
  i = spring_indices[tid * 2 + 0]
402
402
  j = spring_indices[tid * 2 + 1]
403
403
 
404
+ if i == -1 or j == -1:
405
+ return
406
+
404
407
  ke = spring_stiffness[tid]
405
408
  kd = spring_damping[tid]
406
409
  rest = spring_rest_lengths[tid]
@@ -595,7 +598,7 @@ def solve_tetrahedra(
595
598
  x20 = x2 - x0
596
599
  x30 = x3 - x0
597
600
 
598
- Ds = wp.mat33(x10, x20, x30)
601
+ Ds = wp.matrix_from_cols(x10, x20, x30)
599
602
  Dm = rest_matrix[tid]
600
603
  inv_QT = wp.transpose(Dm)
601
604
 
@@ -627,7 +630,7 @@ def solve_tetrahedra(
627
630
  elif term == 1:
628
631
  # volume conservation
629
632
  C = wp.determinant(F) - 1.0
630
- dC = wp.mat33(wp.cross(f2, f3), wp.cross(f3, f1), wp.cross(f1, f2))
633
+ dC = wp.matrix_from_cols(wp.cross(f2, f3), wp.cross(f3, f1), wp.cross(f1, f2))
631
634
  compliance = volume_compliance
632
635
 
633
636
  if C != 0.0:
@@ -691,7 +694,7 @@ def solve_tetrahedra(
691
694
  # J = wp.determinant(F)
692
695
 
693
696
  # C_vol = J - alpha
694
- # # dCdx = wp.mat33(wp.cross(f2, f3), wp.cross(f3, f1), wp.cross(f1, f2))*wp.transpose(Dm)
697
+ # # dCdx = wp.matrix_from_cols(wp.cross(f2, f3), wp.cross(f3, f1), wp.cross(f1, f2))*wp.transpose(Dm)
695
698
 
696
699
  # # grad1 = wp.vec3(dCdx[0,0], dCdx[1,0], dCdx[2,0])
697
700
  # # grad2 = wp.vec3(dCdx[0,1], dCdx[1,1], dCdx[2,1])
@@ -766,7 +769,7 @@ def solve_tetrahedra2(
766
769
  x20 = x2 - x0
767
770
  x30 = x3 - x0
768
771
 
769
- Ds = wp.mat33(x10, x20, x30)
772
+ Ds = wp.matrix_from_cols(x10, x20, x30)
770
773
  Dm = pose[tid]
771
774
 
772
775
  inv_rest_volume = wp.determinant(Dm) * 6.0
@@ -837,7 +840,7 @@ def solve_tetrahedra2(
837
840
  J = wp.determinant(F)
838
841
 
839
842
  C_vol = J - alpha
840
- # dCdx = wp.mat33(wp.cross(f2, f3), wp.cross(f3, f1), wp.cross(f1, f2))*wp.transpose(Dm)
843
+ # dCdx = wp.matrix_from_cols(wp.cross(f2, f3), wp.cross(f3, f1), wp.cross(f1, f2))*wp.transpose(Dm)
841
844
 
842
845
  # grad1 = wp.vec3(dCdx[0,0], dCdx[1,0], dCdx[2,0])
843
846
  # grad2 = wp.vec3(dCdx[0,1], dCdx[1,1], dCdx[2,1])
warp/sim/model.py CHANGED
@@ -372,9 +372,14 @@ class Control:
372
372
  should generally be created using the :func:`Model.control()` function.
373
373
  """
374
374
 
375
- def __init__(self, model: Model):
376
- self.model: Model = model
377
- """Model to use as a reference for the control inputs."""
375
+ def __init__(self, model: Model = None):
376
+ if model:
377
+ wp.utils.warn(
378
+ "Passing arguments to Control's __init__ is deprecated\n"
379
+ "and will be disallowed in a future version. Use Control() without arguments\ninstead.",
380
+ category=DeprecationWarning,
381
+ stacklevel=2,
382
+ )
378
383
 
379
384
  self.joint_act: Optional[wp.array] = None
380
385
  """Array of joint control inputs with shape ``(joint_axis_count,)`` and type ``float``."""
@@ -388,17 +393,28 @@ class Control:
388
393
  self.muscle_activations: Optional[wp.array] = None
389
394
  """Array of muscle activations with shape ``(muscle_count,)`` and type ``float``."""
390
395
 
391
- def reset(self) -> None:
392
- """Reset the control inputs to their initial state defined in :attr:`model`."""
396
+ def clear(self) -> None:
397
+ """Reset the control inputs to zero."""
393
398
 
394
399
  if self.joint_act is not None:
395
- self.joint_act.assign(self.model.joint_act)
400
+ self.joint_act.zero_()
396
401
  if self.tri_activations is not None:
397
- self.tri_activations.assign(self.model.tri_activations)
402
+ self.tri_activations.zero_()
398
403
  if self.tet_activations is not None:
399
- self.tet_activations.assign(self.model.tet_activations)
404
+ self.tet_activations.zero_()
400
405
  if self.muscle_activations is not None:
401
- self.muscle_activations.assign(self.model.muscle_activations)
406
+ self.muscle_activations.zero_()
407
+
408
+ def reset(self) -> None:
409
+ """Reset the control inputs to zero."""
410
+
411
+ wp.utils.warn(
412
+ "Control.reset() is deprecated and will be removed\nin a future version. Use Control.clear() instead.",
413
+ category=DeprecationWarning,
414
+ stacklevel=2,
415
+ )
416
+
417
+ self.clear()
402
418
 
403
419
 
404
420
  def compute_shape_mass(type, scale, src, density, is_solid, thickness):
@@ -543,6 +559,7 @@ class Model:
543
559
 
544
560
  edge_indices (array): Bending edge indices, shape [edge_count*4], int, each row is [o0, o1, v1, v2], where v1, v2 are on the edge
545
561
  edge_rest_angle (array): Bending edge rest angle, shape [edge_count], float
562
+ edge_rest_length (array): Bending edge rest length, shape [edge_count], float
546
563
  edge_bending_properties (array): Bending edge stiffness and damping parameters, shape [edge_count, 2], float
547
564
 
548
565
  tet_indices (array): Tetrahedral element indices, shape [tet_count*4], int
@@ -616,6 +633,7 @@ class Model:
616
633
  soft_contact_body_pos (array), Positional offset of soft contact point in body frame, shape [soft_contact_max], vec3
617
634
  soft_contact_body_vel (array), Linear velocity of soft contact point in body frame, shape [soft_contact_max], vec3
618
635
  soft_contact_normal (array), Contact surface normal of soft contact point in world space, shape [soft_contact_max], vec3
636
+ soft_contact_tids (array), Thread indices of the soft contact points, shape [soft_contact_max], int
619
637
 
620
638
  rigid_contact_max (int): Maximum number of potential rigid body contact points to generate ignoring the `rigid_mesh_contact_max` limit.
621
639
  rigid_contact_max_limited (int): Maximum number of potential rigid body contact points to generate respecting the `rigid_mesh_contact_max` limit.
@@ -633,6 +651,12 @@ class Model:
633
651
  rigid_contact_thickness (array): Total contact thickness, shape [rigid_contact_max], float
634
652
  rigid_contact_shape0 (array): Index of shape 0 per contact, shape [rigid_contact_max], int
635
653
  rigid_contact_shape1 (array): Index of shape 1 per contact, shape [rigid_contact_max], int
654
+ rigid_contact_tids (array): Triangle indices of the contact points, shape [rigid_contact_max], int
655
+ rigid_contact_pairwise_counter (array): Pairwise counter for contact generation, shape [rigid_contact_max], int
656
+ rigid_contact_broad_shape0 (array): Broadphase shape index of shape 0 per contact, shape [rigid_contact_max], int
657
+ rigid_contact_broad_shape1 (array): Broadphase shape index of shape 1 per contact, shape [rigid_contact_max], int
658
+ rigid_contact_point_id (array): Contact point ID, shape [rigid_contact_max], int
659
+ rigid_contact_point_limit (array): Contact point limit, shape [rigid_contact_max], int
636
660
 
637
661
  ground (bool): Whether the ground plane and ground contacts are enabled
638
662
  ground_plane (array): Ground plane 3D normal and offset, shape [4], float
@@ -716,6 +740,7 @@ class Model:
716
740
 
717
741
  self.edge_indices = None
718
742
  self.edge_rest_angle = None
743
+ self.edge_rest_length = None
719
744
  self.edge_bending_properties = None
720
745
  self.edge_constraint_lambdas = None
721
746
 
@@ -787,6 +812,7 @@ class Model:
787
812
  self.soft_contact_body_pos = None
788
813
  self.soft_contact_body_vel = None
789
814
  self.soft_contact_normal = None
815
+ self.soft_contact_tids = None
790
816
 
791
817
  self.rigid_contact_max = 0
792
818
  self.rigid_contact_max_limited = 0
@@ -804,6 +830,12 @@ class Model:
804
830
  self.rigid_contact_thickness = None
805
831
  self.rigid_contact_shape0 = None
806
832
  self.rigid_contact_shape1 = None
833
+ self.rigid_contact_tids = None
834
+ self.rigid_contact_pairwise_counter = None
835
+ self.rigid_contact_broad_shape0 = None
836
+ self.rigid_contact_broad_shape1 = None
837
+ self.rigid_contact_point_id = None
838
+ self.rigid_contact_point_limit = None
807
839
 
808
840
  # toggles ground contact for all shapes
809
841
  self.ground = True
@@ -878,7 +910,7 @@ class Model:
878
910
  Returns:
879
911
  Control: The control object
880
912
  """
881
- c = Control(self)
913
+ c = Control()
882
914
  if requires_grad is None:
883
915
  requires_grad = self.requires_grad
884
916
  if clone_variables:
@@ -1205,6 +1237,7 @@ class ModelBuilder:
1205
1237
  # edges (bending)
1206
1238
  self.edge_indices = []
1207
1239
  self.edge_rest_angle = []
1240
+ self.edge_rest_length = []
1208
1241
  self.edge_bending_properties = []
1209
1242
 
1210
1243
  # tetrahedra
@@ -1384,7 +1417,11 @@ class ModelBuilder:
1384
1417
  if builder.spring_count:
1385
1418
  self.spring_indices.extend((np.array(builder.spring_indices, dtype=np.int32) + start_particle_idx).tolist())
1386
1419
  if builder.edge_count:
1387
- self.edge_indices.extend((np.array(builder.edge_indices, dtype=np.int32) + start_particle_idx).tolist())
1420
+ # Update edge indices by adding offset, preserving -1 values
1421
+ edge_indices = np.array(builder.edge_indices, dtype=np.int32)
1422
+ mask = edge_indices != -1
1423
+ edge_indices[mask] += start_particle_idx
1424
+ self.edge_indices.extend(edge_indices.tolist())
1388
1425
  if builder.tri_count:
1389
1426
  self.tri_indices.extend((np.array(builder.tri_indices, dtype=np.int32) + start_particle_idx).tolist())
1390
1427
  if builder.tet_count:
@@ -1518,6 +1555,7 @@ class ModelBuilder:
1518
1555
  "particle_radius",
1519
1556
  "particle_flags",
1520
1557
  "edge_rest_angle",
1558
+ "edge_rest_length",
1521
1559
  "edge_bending_properties",
1522
1560
  "spring_rest_length",
1523
1561
  "spring_stiffness",
@@ -3447,8 +3485,9 @@ class ModelBuilder:
3447
3485
  self.shape_shape_collision.append(has_shape_collision)
3448
3486
 
3449
3487
  (m, c, I) = compute_shape_mass(type, scale, src, density, is_solid, thickness)
3488
+ com_body = wp.transform_point(wp.transform(pos, rot), c)
3450
3489
 
3451
- self._update_body_mass(body, m, I, pos + c, rot)
3490
+ self._update_body_mass(body, m, I, com_body, rot)
3452
3491
  return shape
3453
3492
 
3454
3493
  # particles
@@ -3757,11 +3796,11 @@ class ModelBuilder:
3757
3796
  edge_kd = edge_kd if edge_kd is not None else self.default_edge_kd
3758
3797
 
3759
3798
  # compute rest angle
3799
+ x3 = self.particle_q[k]
3800
+ x4 = self.particle_q[l]
3760
3801
  if rest is None:
3761
3802
  x1 = self.particle_q[i]
3762
3803
  x2 = self.particle_q[j]
3763
- x3 = self.particle_q[k]
3764
- x4 = self.particle_q[l]
3765
3804
 
3766
3805
  n1 = wp.normalize(wp.cross(x3 - x1, x4 - x1))
3767
3806
  n2 = wp.normalize(wp.cross(x4 - x2, x3 - x2))
@@ -3776,6 +3815,7 @@ class ModelBuilder:
3776
3815
 
3777
3816
  self.edge_indices.append((i, j, k, l))
3778
3817
  self.edge_rest_angle.append(rest)
3818
+ self.edge_rest_length.append(wp.length(x4 - x3))
3779
3819
  self.edge_bending_properties.append((edge_ke, edge_kd))
3780
3820
 
3781
3821
  def add_edges(
@@ -3807,6 +3847,8 @@ class ModelBuilder:
3807
3847
  winding: (i, k, l), (j, l, k).
3808
3848
 
3809
3849
  """
3850
+ x3 = np.array(self.particle_q)[k]
3851
+ x4 = np.array(self.particle_q)[l]
3810
3852
  if rest is None:
3811
3853
  # compute rest angle
3812
3854
  x1 = np.array(self.particle_q)[i]
@@ -3837,6 +3879,7 @@ class ModelBuilder:
3837
3879
 
3838
3880
  self.edge_indices.extend(inds.tolist())
3839
3881
  self.edge_rest_angle.extend(rest.tolist())
3882
+ self.edge_rest_length.extend(np.linalg.norm(x4 - x3, axis=1).tolist())
3840
3883
 
3841
3884
  def init_if_none(arr, defaultValue):
3842
3885
  if arr is None:
@@ -3982,15 +4025,16 @@ class ModelBuilder:
3982
4025
  ) # opposite 0, opposite 1, vertex 0, vertex 1
3983
4026
 
3984
4027
  # skip constraints open edges
3985
- if e.f0 != -1 and e.f1 != -1:
3986
- spring_indices.add((min(e.o0, e.o1), max(e.o0, e.o1)))
4028
+ spring_indices.add((min(e.v0, e.v1), max(e.v0, e.v1)))
4029
+ if e.f0 != -1:
3987
4030
  spring_indices.add((min(e.o0, e.v0), max(e.o0, e.v0)))
3988
4031
  spring_indices.add((min(e.o0, e.v1), max(e.o0, e.v1)))
3989
-
4032
+ if e.f1 != -1:
3990
4033
  spring_indices.add((min(e.o1, e.v0), max(e.o1, e.v0)))
3991
4034
  spring_indices.add((min(e.o1, e.v1), max(e.o1, e.v1)))
3992
4035
 
3993
- spring_indices.add((min(e.v0, e.v1), max(e.v0, e.v1)))
4036
+ if e.f0 != -1 and e.f1 != -1:
4037
+ spring_indices.add((min(e.o0, e.o1), max(e.o0, e.o1)))
3994
4038
 
3995
4039
  if add_springs:
3996
4040
  for i, j in spring_indices:
@@ -4101,14 +4145,15 @@ class ModelBuilder:
4101
4145
  if add_springs:
4102
4146
  spring_indices = set()
4103
4147
  for i, j, k, l in edge_indices:
4104
- spring_indices.add((min(i, j), max(i, j)))
4105
- spring_indices.add((min(i, k), max(i, k)))
4106
- spring_indices.add((min(i, l), max(i, l)))
4107
-
4108
- spring_indices.add((min(j, k), max(j, k)))
4109
- spring_indices.add((min(j, l), max(j, l)))
4110
-
4111
4148
  spring_indices.add((min(k, l), max(k, l)))
4149
+ if i != -1:
4150
+ spring_indices.add((min(i, k), max(i, k)))
4151
+ spring_indices.add((min(i, l), max(i, l)))
4152
+ if j != -1:
4153
+ spring_indices.add((min(j, k), max(j, k)))
4154
+ spring_indices.add((min(j, l), max(j, l)))
4155
+ if i != -1 and j != -1:
4156
+ spring_indices.add((min(i, j), max(i, j)))
4112
4157
 
4113
4158
  for i, j in spring_indices:
4114
4159
  self.add_spring(i, j, spring_ke, spring_kd, control=0.0)
@@ -4628,6 +4673,7 @@ class ModelBuilder:
4628
4673
 
4629
4674
  m.edge_indices = wp.array(self.edge_indices, dtype=wp.int32)
4630
4675
  m.edge_rest_angle = wp.array(self.edge_rest_angle, dtype=wp.float32, requires_grad=requires_grad)
4676
+ m.edge_rest_length = wp.array(self.edge_rest_length, dtype=wp.float32, requires_grad=requires_grad)
4631
4677
  m.edge_bending_properties = wp.array(
4632
4678
  self.edge_bending_properties, dtype=wp.float32, requires_grad=requires_grad
4633
4679
  )
warp/sim/render.py CHANGED
@@ -273,6 +273,10 @@ def CreateSimRenderer(renderer):
273
273
  continue
274
274
  tf = joint_tf[i]
275
275
  body = int(joint_parent[i])
276
+ if body >= 0 and body < len(self.body_names):
277
+ body = self.body_names[body]
278
+ else:
279
+ body = None
276
280
  # if body == -1:
277
281
  # continue
278
282
  num_linear_axes = int(joint_axis_dim[i][0])
warp/sim/utils.py CHANGED
@@ -65,7 +65,7 @@ def quat_decompose(q: wp.quat):
65
65
  Decompose a quaternion into a sequence of 3 rotations around x,y',z' respectively, i.e.: q = q_z''q_y'q_x.
66
66
  """
67
67
 
68
- R = wp.mat33(
68
+ R = wp.matrix_from_cols(
69
69
  wp.quat_rotate(q, wp.vec3(1.0, 0.0, 0.0)),
70
70
  wp.quat_rotate(q, wp.vec3(0.0, 1.0, 0.0)),
71
71
  wp.quat_rotate(q, wp.vec3(0.0, 0.0, 1.0)),
@@ -249,7 +249,7 @@ def transform_inertia(t: wp.transform, I: wp.spatial_matrix):
249
249
  r2 = wp.quat_rotate(q, wp.vec3(0.0, 1.0, 0.0))
250
250
  r3 = wp.quat_rotate(q, wp.vec3(0.0, 0.0, 1.0))
251
251
 
252
- R = wp.mat33(r1, r2, r3)
252
+ R = wp.matrix_from_cols(r1, r2, r3)
253
253
  S = wp.mul(wp.skew(p), R)
254
254
 
255
255
  T = wp.spatial_adjoint(R, S)