warp-lang 1.7.2rc1__py3-none-manylinux_2_34_aarch64.whl → 1.8.1__py3-none-manylinux_2_34_aarch64.whl

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

Potentially problematic release.


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

Files changed (193) hide show
  1. warp/__init__.py +3 -1
  2. warp/__init__.pyi +3489 -1
  3. warp/autograd.py +45 -122
  4. warp/bin/warp-clang.so +0 -0
  5. warp/bin/warp.so +0 -0
  6. warp/build.py +241 -252
  7. warp/build_dll.py +130 -26
  8. warp/builtins.py +1907 -384
  9. warp/codegen.py +272 -104
  10. warp/config.py +12 -1
  11. warp/constants.py +1 -1
  12. warp/context.py +770 -238
  13. warp/dlpack.py +1 -1
  14. warp/examples/benchmarks/benchmark_cloth.py +2 -2
  15. warp/examples/benchmarks/benchmark_tile_sort.py +155 -0
  16. warp/examples/core/example_sample_mesh.py +1 -1
  17. warp/examples/core/example_spin_lock.py +93 -0
  18. warp/examples/core/example_work_queue.py +118 -0
  19. warp/examples/fem/example_adaptive_grid.py +5 -5
  20. warp/examples/fem/example_apic_fluid.py +1 -1
  21. warp/examples/fem/example_burgers.py +1 -1
  22. warp/examples/fem/example_convection_diffusion.py +9 -6
  23. warp/examples/fem/example_darcy_ls_optimization.py +489 -0
  24. warp/examples/fem/example_deformed_geometry.py +1 -1
  25. warp/examples/fem/example_diffusion.py +2 -2
  26. warp/examples/fem/example_diffusion_3d.py +1 -1
  27. warp/examples/fem/example_distortion_energy.py +1 -1
  28. warp/examples/fem/example_elastic_shape_optimization.py +387 -0
  29. warp/examples/fem/example_magnetostatics.py +5 -3
  30. warp/examples/fem/example_mixed_elasticity.py +5 -3
  31. warp/examples/fem/example_navier_stokes.py +11 -9
  32. warp/examples/fem/example_nonconforming_contact.py +5 -3
  33. warp/examples/fem/example_streamlines.py +8 -3
  34. warp/examples/fem/utils.py +9 -8
  35. warp/examples/interop/example_jax_callable.py +34 -4
  36. warp/examples/interop/example_jax_ffi_callback.py +2 -2
  37. warp/examples/interop/example_jax_kernel.py +27 -1
  38. warp/examples/optim/example_drone.py +1 -1
  39. warp/examples/sim/example_cloth.py +1 -1
  40. warp/examples/sim/example_cloth_self_contact.py +48 -54
  41. warp/examples/tile/example_tile_block_cholesky.py +502 -0
  42. warp/examples/tile/example_tile_cholesky.py +2 -1
  43. warp/examples/tile/example_tile_convolution.py +1 -1
  44. warp/examples/tile/example_tile_filtering.py +1 -1
  45. warp/examples/tile/example_tile_matmul.py +1 -1
  46. warp/examples/tile/example_tile_mlp.py +2 -0
  47. warp/fabric.py +7 -7
  48. warp/fem/__init__.py +5 -0
  49. warp/fem/adaptivity.py +1 -1
  50. warp/fem/cache.py +152 -63
  51. warp/fem/dirichlet.py +2 -2
  52. warp/fem/domain.py +136 -6
  53. warp/fem/field/field.py +141 -99
  54. warp/fem/field/nodal_field.py +85 -39
  55. warp/fem/field/virtual.py +99 -52
  56. warp/fem/geometry/adaptive_nanogrid.py +91 -86
  57. warp/fem/geometry/closest_point.py +13 -0
  58. warp/fem/geometry/deformed_geometry.py +102 -40
  59. warp/fem/geometry/element.py +56 -2
  60. warp/fem/geometry/geometry.py +323 -22
  61. warp/fem/geometry/grid_2d.py +157 -62
  62. warp/fem/geometry/grid_3d.py +116 -20
  63. warp/fem/geometry/hexmesh.py +86 -20
  64. warp/fem/geometry/nanogrid.py +166 -86
  65. warp/fem/geometry/partition.py +59 -25
  66. warp/fem/geometry/quadmesh.py +86 -135
  67. warp/fem/geometry/tetmesh.py +47 -119
  68. warp/fem/geometry/trimesh.py +77 -270
  69. warp/fem/integrate.py +181 -95
  70. warp/fem/linalg.py +25 -58
  71. warp/fem/operator.py +124 -27
  72. warp/fem/quadrature/pic_quadrature.py +36 -14
  73. warp/fem/quadrature/quadrature.py +40 -16
  74. warp/fem/space/__init__.py +1 -1
  75. warp/fem/space/basis_function_space.py +66 -46
  76. warp/fem/space/basis_space.py +17 -4
  77. warp/fem/space/dof_mapper.py +1 -1
  78. warp/fem/space/function_space.py +2 -2
  79. warp/fem/space/grid_2d_function_space.py +4 -1
  80. warp/fem/space/hexmesh_function_space.py +4 -2
  81. warp/fem/space/nanogrid_function_space.py +3 -1
  82. warp/fem/space/partition.py +11 -2
  83. warp/fem/space/quadmesh_function_space.py +4 -1
  84. warp/fem/space/restriction.py +5 -2
  85. warp/fem/space/shape/__init__.py +10 -8
  86. warp/fem/space/tetmesh_function_space.py +4 -1
  87. warp/fem/space/topology.py +52 -21
  88. warp/fem/space/trimesh_function_space.py +4 -1
  89. warp/fem/utils.py +53 -8
  90. warp/jax.py +1 -2
  91. warp/jax_experimental/ffi.py +210 -67
  92. warp/jax_experimental/xla_ffi.py +37 -24
  93. warp/math.py +171 -1
  94. warp/native/array.h +103 -4
  95. warp/native/builtin.h +182 -35
  96. warp/native/coloring.cpp +6 -2
  97. warp/native/cuda_util.cpp +1 -1
  98. warp/native/exports.h +118 -63
  99. warp/native/intersect.h +5 -5
  100. warp/native/mat.h +8 -13
  101. warp/native/mathdx.cpp +11 -5
  102. warp/native/matnn.h +1 -123
  103. warp/native/mesh.h +1 -1
  104. warp/native/quat.h +34 -6
  105. warp/native/rand.h +7 -7
  106. warp/native/sparse.cpp +121 -258
  107. warp/native/sparse.cu +181 -274
  108. warp/native/spatial.h +305 -17
  109. warp/native/svd.h +23 -8
  110. warp/native/tile.h +603 -73
  111. warp/native/tile_radix_sort.h +1112 -0
  112. warp/native/tile_reduce.h +239 -13
  113. warp/native/tile_scan.h +240 -0
  114. warp/native/tuple.h +189 -0
  115. warp/native/vec.h +10 -20
  116. warp/native/warp.cpp +36 -4
  117. warp/native/warp.cu +588 -52
  118. warp/native/warp.h +47 -74
  119. warp/optim/linear.py +5 -1
  120. warp/paddle.py +7 -8
  121. warp/py.typed +0 -0
  122. warp/render/render_opengl.py +110 -80
  123. warp/render/render_usd.py +124 -62
  124. warp/sim/__init__.py +9 -0
  125. warp/sim/collide.py +253 -80
  126. warp/sim/graph_coloring.py +8 -1
  127. warp/sim/import_mjcf.py +4 -3
  128. warp/sim/import_usd.py +11 -7
  129. warp/sim/integrator.py +5 -2
  130. warp/sim/integrator_euler.py +1 -1
  131. warp/sim/integrator_featherstone.py +1 -1
  132. warp/sim/integrator_vbd.py +761 -322
  133. warp/sim/integrator_xpbd.py +1 -1
  134. warp/sim/model.py +265 -260
  135. warp/sim/utils.py +10 -7
  136. warp/sparse.py +303 -166
  137. warp/tape.py +54 -51
  138. warp/tests/cuda/test_conditional_captures.py +1046 -0
  139. warp/tests/cuda/test_streams.py +1 -1
  140. warp/tests/geometry/test_volume.py +2 -2
  141. warp/tests/interop/test_dlpack.py +9 -9
  142. warp/tests/interop/test_jax.py +0 -1
  143. warp/tests/run_coverage_serial.py +1 -1
  144. warp/tests/sim/disabled_kinematics.py +2 -2
  145. warp/tests/sim/{test_vbd.py → test_cloth.py} +378 -112
  146. warp/tests/sim/test_collision.py +159 -51
  147. warp/tests/sim/test_coloring.py +91 -2
  148. warp/tests/test_array.py +254 -2
  149. warp/tests/test_array_reduce.py +2 -2
  150. warp/tests/test_assert.py +53 -0
  151. warp/tests/test_atomic_cas.py +312 -0
  152. warp/tests/test_codegen.py +142 -19
  153. warp/tests/test_conditional.py +47 -1
  154. warp/tests/test_ctypes.py +0 -20
  155. warp/tests/test_devices.py +8 -0
  156. warp/tests/test_fabricarray.py +4 -2
  157. warp/tests/test_fem.py +58 -25
  158. warp/tests/test_func.py +42 -1
  159. warp/tests/test_grad.py +1 -1
  160. warp/tests/test_lerp.py +1 -3
  161. warp/tests/test_map.py +481 -0
  162. warp/tests/test_mat.py +23 -24
  163. warp/tests/test_quat.py +28 -15
  164. warp/tests/test_rounding.py +10 -38
  165. warp/tests/test_runlength_encode.py +7 -7
  166. warp/tests/test_smoothstep.py +1 -1
  167. warp/tests/test_sparse.py +83 -2
  168. warp/tests/test_spatial.py +507 -1
  169. warp/tests/test_static.py +48 -0
  170. warp/tests/test_struct.py +2 -2
  171. warp/tests/test_tape.py +38 -0
  172. warp/tests/test_tuple.py +265 -0
  173. warp/tests/test_types.py +2 -2
  174. warp/tests/test_utils.py +24 -18
  175. warp/tests/test_vec.py +38 -408
  176. warp/tests/test_vec_constructors.py +325 -0
  177. warp/tests/tile/test_tile.py +438 -131
  178. warp/tests/tile/test_tile_mathdx.py +518 -14
  179. warp/tests/tile/test_tile_matmul.py +179 -0
  180. warp/tests/tile/test_tile_reduce.py +307 -5
  181. warp/tests/tile/test_tile_shared_memory.py +136 -7
  182. warp/tests/tile/test_tile_sort.py +121 -0
  183. warp/tests/unittest_suites.py +14 -6
  184. warp/types.py +462 -308
  185. warp/utils.py +647 -86
  186. {warp_lang-1.7.2rc1.dist-info → warp_lang-1.8.1.dist-info}/METADATA +20 -6
  187. {warp_lang-1.7.2rc1.dist-info → warp_lang-1.8.1.dist-info}/RECORD +190 -176
  188. warp/stubs.py +0 -3381
  189. warp/tests/sim/test_xpbd.py +0 -399
  190. warp/tests/test_mlp.py +0 -282
  191. {warp_lang-1.7.2rc1.dist-info → warp_lang-1.8.1.dist-info}/WHEEL +0 -0
  192. {warp_lang-1.7.2rc1.dist-info → warp_lang-1.8.1.dist-info}/licenses/LICENSE.md +0 -0
  193. {warp_lang-1.7.2rc1.dist-info → warp_lang-1.8.1.dist-info}/top_level.txt +0 -0
@@ -13,15 +13,19 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- import contextlib
17
- import io
18
16
  import unittest
17
+ from functools import partial
18
+
19
+ import numpy as np
19
20
 
20
21
  import warp as wp
21
- import warp.optim
22
22
  import warp.sim
23
- import warp.sim.graph_coloring
23
+ import warp.sim.integrator
24
+ import warp.sim.integrator_euler
24
25
  import warp.sim.integrator_vbd
26
+ import warp.sim.integrator_xpbd
27
+ import warp.sim.particles
28
+ import warp.sim.render
25
29
  from warp.sim.model import PARTICLE_FLAG_ACTIVE
26
30
  from warp.tests.unittest_utils import *
27
31
 
@@ -295,40 +299,64 @@ CLOTH_FACES = [
295
299
  ]
296
300
 
297
301
  # fmt: on
298
- class VBDClothSim:
299
- def __init__(self, device, use_cuda_graph=False):
302
+ class ClothSim:
303
+ def __init__(self, device, solver, use_cuda_graph=False, do_rendering=False):
300
304
  self.frame_dt = 1 / 60
301
- self.num_test_frames = 100
302
- self.num_substeps = 10
303
- self.iterations = 10
304
- self.dt = self.frame_dt / self.num_substeps
305
+ self.num_test_frames = 50
306
+ self.iterations = 5
307
+ self.do_rendering = do_rendering
305
308
  self.device = device
306
309
  self.use_cuda_graph = self.device.is_cuda and use_cuda_graph
307
310
  self.builder = wp.sim.ModelBuilder()
311
+ self.solver = solver
312
+ self.renderer_scale_factor = 1.0
308
313
 
309
- def set_up_sagging_experiment(self):
310
- stiffness = 1e5
311
- kd = 1.0e-7
314
+ if solver != "semi_implicit":
315
+ self.num_substeps = 10
316
+ else:
317
+ self.num_substeps = 32
318
+ self.dt = self.frame_dt / self.num_substeps
312
319
 
320
+ def set_up_sagging_experiment(self):
313
321
  self.input_scale_factor = 1.0
314
322
  self.renderer_scale_factor = 0.01
315
323
  vertices = [wp.vec3(v) * self.input_scale_factor for v in CLOTH_POINTS]
316
324
  faces_flatten = [fv - 1 for fv in CLOTH_FACES]
317
325
 
326
+ kd = 1.0e-7
327
+
328
+ if self.solver != "semi_implicit":
329
+ stretching_stiffness = 1e4
330
+ spring_ke = 1e3
331
+ bending_ke = 10
332
+ else:
333
+ stretching_stiffness = 1e5
334
+ spring_ke = 1e2
335
+ bending_ke = 0.0
336
+
318
337
  self.builder.add_cloth_mesh(
319
- pos=wp.vec3(0.0, 200.0, 0.0),
338
+ pos=wp.vec3(0.0, 0.0, 0.0),
320
339
  rot=wp.quat_from_axis_angle(wp.vec3(1.0, 0.0, 0.0), 0.0),
321
340
  scale=1.0,
322
341
  vertices=vertices,
323
342
  indices=faces_flatten,
324
343
  vel=wp.vec3(0.0, 0.0, 0.0),
325
- density=0.02,
326
- tri_ke=stiffness,
327
- tri_ka=stiffness,
344
+ density=0.1,
345
+ tri_ke=stretching_stiffness,
346
+ tri_ka=stretching_stiffness,
328
347
  tri_kd=kd,
348
+ edge_ke=bending_ke,
349
+ add_springs=self.solver == "xpbd",
350
+ spring_ke=spring_ke,
351
+ spring_kd=0.0,
329
352
  )
353
+
330
354
  self.fixed_particles = [0, 9]
331
355
 
356
+ self.finalize(ground=False)
357
+
358
+ self.state1.particle_q.fill_(0.0)
359
+
332
360
  def set_up_bending_experiment(self):
333
361
  stretching_stiffness = 1e4
334
362
  stretching_damping = 1e-6
@@ -364,6 +392,9 @@ class VBDClothSim:
364
392
  tri_kd=stretching_damping,
365
393
  edge_ke=10,
366
394
  edge_kd=bending_damping,
395
+ add_springs=self.solver == "xpbd",
396
+ spring_ke=1.0e3,
397
+ spring_kd=0.0,
367
398
  )
368
399
 
369
400
  self.builder.add_cloth_mesh(
@@ -379,6 +410,9 @@ class VBDClothSim:
379
410
  tri_kd=stretching_damping,
380
411
  edge_ke=100,
381
412
  edge_kd=bending_damping,
413
+ add_springs=self.solver == "xpbd",
414
+ spring_ke=1.0e3,
415
+ spring_kd=0.0,
382
416
  )
383
417
 
384
418
  self.builder.add_cloth_mesh(
@@ -394,57 +428,155 @@ class VBDClothSim:
394
428
  tri_kd=stretching_damping,
395
429
  edge_ke=1000,
396
430
  edge_kd=bending_damping,
431
+ add_springs=self.solver == "xpbd",
432
+ spring_ke=1.0e3,
433
+ spring_kd=0.0,
397
434
  )
398
435
 
399
436
  self.fixed_particles = [0, 29, 36, 65, 72, 101]
400
437
 
438
+ self.finalize()
439
+
440
+ def set_self_collision_experiment(self):
441
+ elasticity_ke = 1e4
442
+ elasticity_kd = 1e-6
443
+
444
+ vs1 = [wp.vec3(v) for v in [[0, 0, 0], [1, 0, 0], [1, 0, 1], [0, 0, 1]]]
445
+ fs1 = [0, 1, 2, 0, 2, 3]
446
+
447
+ self.builder.add_cloth_mesh(
448
+ pos=wp.vec3(0.0, 0.0, 0.0),
449
+ rot=wp.quat_from_axis_angle(wp.vec3(1.0, 0.0, 0.0), 0.0),
450
+ scale=1.0,
451
+ vertices=vs1,
452
+ indices=fs1,
453
+ vel=wp.vec3(0.0, 0.0, 0.0),
454
+ density=0.02,
455
+ tri_ke=elasticity_ke,
456
+ tri_ka=elasticity_ke,
457
+ tri_kd=elasticity_kd,
458
+ add_springs=self.solver == "xpbd",
459
+ spring_ke=1.0e3,
460
+ spring_kd=0.0,
461
+ )
462
+
463
+ vs2 = [wp.vec3(v) for v in [[0.3, 0, 0.7], [0.3, 0, 0.2], [0.8, 0, 0.4]]]
464
+ fs2 = [0, 1, 2]
465
+
466
+ self.builder.add_cloth_mesh(
467
+ pos=wp.vec3(0.0, 0.5, 0.0),
468
+ rot=wp.quat_from_axis_angle(wp.vec3(1.0, 0.0, 0.0), 0.0),
469
+ scale=1.0,
470
+ vertices=vs2,
471
+ indices=fs2,
472
+ vel=wp.vec3(0.0, 0.0, 0.0),
473
+ density=0.02,
474
+ tri_ke=elasticity_ke,
475
+ tri_ka=elasticity_ke,
476
+ tri_kd=elasticity_kd,
477
+ add_springs=self.solver == "xpbd",
478
+ spring_ke=1.0e3,
479
+ spring_kd=0.0,
480
+ )
481
+
482
+ self.fixed_particles = range(0, 4)
483
+
484
+ self.finalize(handle_self_contact=True, ground=False)
485
+ self.model.soft_contact_radius = 0.1
486
+ self.model.soft_contact_margin = 0.1
487
+ self.model.soft_contact_ke = 1e4
488
+ self.model.soft_contact_kd = 1e-3
489
+ self.model.soft_contact_mu = 0.2
490
+ self.model.gravity = wp.vec3(0.0, -1000.0, 0)
491
+ self.num_test_frames = 30
492
+
493
+ def set_body_collision_experiment(self, handle_self_contact=False):
494
+ self.renderer_scale_factor = 1.0
495
+ elasticity_ke = 1e4
496
+ elasticity_kd = 1e-6
497
+
498
+ vs1 = [wp.vec3(v) for v in [[0, 0, 0], [1, 0, 0], [1, 0, 1], [0, 0, 1]]]
499
+ fs1 = [0, 1, 2, 0, 2, 3]
500
+
501
+ self.builder.add_cloth_mesh(
502
+ pos=wp.vec3(0.0, 0.0, 0.0),
503
+ rot=wp.quat_from_axis_angle(wp.vec3(1.0, 0.0, 0.0), 0.0),
504
+ scale=1.0,
505
+ vertices=vs1,
506
+ indices=fs1,
507
+ vel=wp.vec3(0.0, 0.0, 0.0),
508
+ density=0.02,
509
+ tri_ke=elasticity_ke,
510
+ tri_ka=elasticity_ke,
511
+ tri_kd=elasticity_kd,
512
+ add_springs=self.solver == "xpbd",
513
+ spring_ke=1.0e3,
514
+ spring_kd=0.0,
515
+ particle_radius=0.1,
516
+ )
517
+
518
+ self.builder.add_shape_box(-1, pos=wp.vec3(0, -3.3, 0), hx=3, hy=3, hz=3)
519
+
520
+ self.fixed_particles = []
521
+
522
+ self.finalize(handle_self_contact=handle_self_contact, ground=False)
523
+ self.model.soft_contact_radius = 0.1
524
+ self.model.soft_contact_margin = 0.1
525
+ self.model.soft_contact_ke = 1e4
526
+ self.model.soft_contact_kd = 1e-3
527
+ self.model.soft_contact_mu = 0.2
528
+ self.model.gravity = wp.vec3(0.0, -1000.0, 0)
529
+ self.num_test_frames = 30
530
+
401
531
  def set_up_non_zero_rest_angle_bending_experiment(self):
402
532
  # fmt: off
403
- vs = [
404
- [ 0. , 10. , -10. ],
405
- [ 0. , 10. , 10. ],
406
- [ 7.07107, 7.07107, -10. ],
407
- [ 7.07107, 7.07107, 10. ],
408
- [ 10. , 0. , -10. ],
409
- [ 10. , -0. , 10. ],
410
- [ 7.07107, -7.07107, -10. ],
411
- [ 7.07107, -7.07107, 10. ],
412
- [ 0. , -10. , -10. ],
413
- [ 0. , -10. , 10. ],
414
- [ -7.07107, -7.07107, -10. ],
415
- [ -7.07107, -7.07107, 10. ],
416
- [-10. , 0. , -10. ],
417
- [-10. , -0. , 10. ],
418
- [ -7.07107, 7.07107, -10. ],
419
- [ -7.07107, 7.07107, 10. ],
533
+ vs =[
534
+ [ 0. , 1. , -1. ],
535
+ [ 0. , 1. , 1. ],
536
+ [ 0.70711, 0.70711, -1. ],
537
+ [ 0.70711, 0.70711, 1. ],
538
+ [ 1. , 0. , -1. ],
539
+ [ 1. , -0. , 1. ],
540
+ [ 0.70711, -0.70711, -1. ],
541
+ [ 0.70711, -0.70711, 1. ],
542
+ [ 0. , -1. , -1. ],
543
+ [ 0. , -1. , 1. ],
544
+ [-0.70711, -0.70711, -1. ],
545
+ [-0.70711, -0.70711, 1. ],
546
+ [-1. , 0. , -1. ],
547
+ [-1. , -0. , 1. ],
548
+ [-0.70711, 0.70711, -1. ],
549
+ [-0.70711, 0.70711, 1. ],
420
550
  ]
421
551
  fs = [
422
- 1, 2, 0,
423
- 3, 4, 2,
424
- 5, 6, 4,
425
- 7, 8, 6,
426
- 9, 10, 8,
427
- 11, 12, 10,
428
- 3, 5, 4,
429
- 13, 14, 12,
430
- 15, 0, 14,
431
- 1, 3, 2,
432
- 5, 7, 6,
433
- 7, 9, 8,
434
- 9, 11, 10,
435
- 11, 13, 12,
552
+ 1, 2, 0,
553
+ 3, 4, 2,
554
+ 5, 6, 4,
555
+ 7, 8, 6,
556
+ 9, 10, 8,
557
+ 11, 12, 10,
558
+ 3, 5, 4,
559
+ 13, 14, 12,
560
+ 15, 0, 14,
561
+ 1, 3, 2,
562
+ 5, 7, 6,
563
+ 7, 9, 8,
564
+ 9, 11, 10,
565
+ 11, 13, 12,
566
+ 13, 15, 14,
567
+ 15, 1, 0,
436
568
  ]
437
569
  # fmt: on
438
570
 
439
- stretching_stiffness = 1e4
440
- stretching_damping = 1e-6
441
- edge_ke = 1000
442
- bending_damping = 1e-2
571
+ stretching_stiffness = 1e5
572
+ stretching_damping = 1e-5
573
+ edge_ke = 100
574
+ bending_damping = 1e-4
443
575
  vs = [wp.vec3(v) for v in vs]
444
576
 
445
577
  self.builder.add_cloth_mesh(
446
- pos=wp.vec3(0.0, 10.0, 0.0),
447
- rot=wp.quat_from_axis_angle(wp.vec3(1.0, 0.0, 0.0), np.pi / 2),
578
+ pos=wp.vec3(0.0, 0.0, 0.0),
579
+ rot=wp.quat_identity(),
448
580
  scale=1.0,
449
581
  vertices=vs,
450
582
  indices=fs,
@@ -455,21 +587,71 @@ class VBDClothSim:
455
587
  tri_kd=stretching_damping,
456
588
  edge_ke=edge_ke,
457
589
  edge_kd=bending_damping,
590
+ add_springs=self.solver == "xpbd",
591
+ spring_ke=1.0e3,
592
+ spring_kd=0.0,
458
593
  )
459
594
  self.fixed_particles = [0, 1]
460
595
 
461
- def finalize(self):
462
- self.builder.color()
596
+ self.finalize(handle_self_contact=False, ground=False)
597
+
598
+ def set_free_falling_experiment(self):
599
+ self.input_scale_factor = 1.0
600
+ self.renderer_scale_factor = 0.01
601
+ vertices = [wp.vec3(v) * self.input_scale_factor for v in CLOTH_POINTS]
602
+ faces_flatten = [fv - 1 for fv in CLOTH_FACES]
603
+ if self.solver != "semi_implicit":
604
+ stretching_stiffness = 1e4
605
+ spring_ke = 1e3
606
+ bending_ke = 10
607
+ else:
608
+ stretching_stiffness = 1e2
609
+ spring_ke = 1e2
610
+ bending_ke = 10
611
+
612
+ self.builder.add_cloth_mesh(
613
+ vertices=vertices,
614
+ indices=faces_flatten,
615
+ scale=0.1,
616
+ density=2,
617
+ pos=wp.vec3(0.0, 4.0, 0.0),
618
+ rot=wp.quat_identity(),
619
+ vel=wp.vec3(0.0, 0.0, 0.0),
620
+ edge_ke=bending_ke,
621
+ edge_kd=0.0,
622
+ tri_ke=stretching_stiffness,
623
+ tri_ka=stretching_stiffness,
624
+ tri_kd=0.0,
625
+ add_springs=self.solver == "xpbd",
626
+ spring_ke=spring_ke,
627
+ spring_kd=0.0,
628
+ )
629
+ self.fixed_particles = []
630
+ self.num_test_frames = 30
631
+ self.finalize(ground=False)
632
+
633
+ def finalize(self, handle_self_contact=False, ground=True):
634
+ self.builder.color(include_bending=True)
463
635
 
464
636
  self.model = self.builder.finalize(device=self.device)
465
- self.model.ground = True
637
+ self.model.ground = ground
466
638
  self.model.gravity = wp.vec3(0, -1000.0, 0)
467
639
  self.model.soft_contact_ke = 1.0e4
468
- self.model.soft_contact_kd = 1.0e2
640
+ self.model.soft_contact_kd = 1.0e-2
469
641
 
470
642
  self.set_points_fixed(self.model, self.fixed_particles)
471
643
 
472
- self.integrator = wp.sim.VBDIntegrator(self.model, self.iterations)
644
+ if self.solver == "vbd":
645
+ self.integrator = wp.sim.VBDIntegrator(self.model, self.iterations, handle_self_contact=handle_self_contact)
646
+ elif self.solver == "xpbd":
647
+ self.integrator = wp.sim.XPBDIntegrator(
648
+ self.iterations,
649
+ )
650
+ elif self.solver == "semi_implicit":
651
+ self.integrator = wp.sim.SemiImplicitIntegrator()
652
+ else:
653
+ raise ValueError("Unsupported solver type: " + self.solver)
654
+
473
655
  self.state0 = self.model.state()
474
656
  self.state1 = self.model.state()
475
657
 
@@ -477,23 +659,53 @@ class VBDClothSim:
477
659
 
478
660
  self.graph = None
479
661
  if self.use_cuda_graph:
662
+ if self.solver == "vbd":
663
+ wp.set_module_options({"block_dim": 256}, warp.sim.integrator_vbd)
664
+ wp.load_module(warp.sim.integrator_vbd, device=self.device)
665
+ elif self.solver == "xpbd":
666
+ wp.set_module_options({"block_dim": 256}, warp.sim.integrator_xpbd)
667
+ wp.load_module(warp.sim.integrator_xpbd, device=self.device)
668
+ elif self.solver == "semi_implicit":
669
+ wp.set_module_options({"block_dim": 256}, warp.sim.integrator_euler)
670
+ wp.load_module(warp.sim.integrator_euler, device=self.device)
671
+ wp.load_module(warp.sim.particles, device=self.device)
672
+ wp.load_module(warp.sim.integrator, device=self.device)
673
+ collide_module = importlib.import_module("warp.sim.collide")
674
+ wp.set_module_options({"block_dim": 256}, collide_module)
675
+ wp.load_module(collide_module, device=self.device)
480
676
  wp.load_module(device=self.device)
481
- wp.set_module_options({"block_dim": 256}, warp.sim.integrator_vbd)
482
- wp.load_module(warp.sim.integrator_vbd, device=self.device)
483
677
  with wp.ScopedCapture(device=self.device, force_module_load=False) as capture:
484
678
  self.simulate()
485
679
  self.graph = capture.graph
486
680
 
487
681
  def simulate(self):
488
- for _step in range(self.num_substeps * self.num_test_frames):
682
+ for _step in range(self.num_substeps):
683
+ self.state0.clear_forces()
684
+ wp.sim.collide(self.model, self.state0)
685
+
489
686
  self.integrator.simulate(self.model, self.state0, self.state1, self.dt, None)
490
687
  (self.state0, self.state1) = (self.state1, self.state0)
491
688
 
492
689
  def run(self):
493
- if self.graph:
494
- wp.capture_launch(self.graph)
690
+ self.sim_time = 0.0
691
+
692
+ if self.do_rendering:
693
+ self.renderer = wp.sim.render.SimRendererOpenGL(self.model, "cloth_sim", scaling=self.renderer_scale_factor)
495
694
  else:
496
- self.simulate()
695
+ self.renderer = None
696
+
697
+ for _frame in range(self.num_test_frames):
698
+ if self.graph:
699
+ wp.capture_launch(self.graph)
700
+ else:
701
+ self.simulate()
702
+
703
+ if self.renderer is not None:
704
+ self.renderer.begin_frame()
705
+ self.renderer.render(self.state0)
706
+ self.renderer.end_frame()
707
+
708
+ self.sim_time = self.sim_time + self.frame_dt
497
709
 
498
710
  def set_points_fixed(self, model, fixed_particles):
499
711
  if len(fixed_particles):
@@ -504,94 +716,148 @@ class VBDClothSim:
504
716
  model.particle_flags = wp.array(flags, device=model.device)
505
717
 
506
718
 
507
- def test_vbd_cloth(test, device):
508
- with contextlib.redirect_stdout(io.StringIO()) as f:
509
- example = VBDClothSim(device)
510
- example.set_up_bending_experiment()
511
- example.finalize()
512
- example.model.ground = False
719
+ def test_cloth_sagging(test, device, solver):
720
+ example = ClothSim(device, solver, use_cuda_graph=True)
721
+ example.set_up_sagging_experiment()
513
722
 
514
- test.assertRegex(
515
- f.getvalue(),
516
- r"Warp UserWarning: The graph is not optimizable anymore, terminated with a max/min ratio: 2.0 without reaching the target ratio: 1.1",
517
- )
723
+ initial_pos = example.state0.particle_q.numpy().copy()
518
724
 
519
725
  example.run()
520
726
 
727
+ fixed_points = np.where(np.logical_not(example.model.particle_flags.numpy()))
521
728
  # examine that the simulation does not explode
522
729
  final_pos = example.state0.particle_q.numpy()
730
+ test.assertTrue((initial_pos[fixed_points, :] == final_pos[fixed_points, :]).all())
523
731
  test.assertTrue((final_pos < 1e5).all())
524
- # examine that the simulation have moved
732
+ # examine that the simulation has moved
525
733
  test.assertTrue((example.init_pos != final_pos).any())
526
734
 
527
735
 
528
- def test_vbd_cloth_cuda_graph(test, device):
529
- with contextlib.redirect_stdout(io.StringIO()) as f:
530
- example = VBDClothSim(device, use_cuda_graph=True)
531
- example.set_up_sagging_experiment()
532
- example.finalize()
533
-
534
- test.assertRegex(
535
- f.getvalue(),
536
- r"Warp UserWarning: The graph is not optimizable anymore, terminated with a max/min ratio: 2.0 without reaching the target ratio: 1.1",
537
- )
736
+ def test_cloth_bending(test, device, solver):
737
+ example = ClothSim(device, solver, use_cuda_graph=True)
738
+ example.set_up_bending_experiment()
538
739
 
539
740
  example.run()
540
741
 
541
742
  # examine that the simulation does not explode
542
743
  final_pos = example.state0.particle_q.numpy()
543
744
  test.assertTrue((final_pos < 1e5).all())
544
- # examine that the simulation have moved
745
+ # examine that the simulation has moved
545
746
  test.assertTrue((example.init_pos != final_pos).any())
546
747
 
547
748
 
548
- def test_vbd_bending(test, device):
549
- example = VBDClothSim(device, use_cuda_graph=True)
550
- example.set_up_bending_experiment()
551
- example.finalize()
749
+ def test_cloth_bending_non_zero_rest_angle_bending(test, device, solver):
750
+ example = ClothSim(device, solver, use_cuda_graph=True)
751
+ example.set_up_non_zero_rest_angle_bending_experiment()
552
752
 
553
753
  example.run()
554
754
 
555
755
  # examine that the simulation does not explode
556
756
  final_pos = example.state0.particle_q.numpy()
557
- test.assertTrue((final_pos < 1e5).all())
558
- # examine that the simulation have moved
757
+ test.assertTrue((np.abs(final_pos) < 1e5).all())
758
+ # examine that the simulation has moved
559
759
  test.assertTrue((example.init_pos != final_pos).any())
560
760
 
561
761
 
562
- def test_vbd_bending_non_zero_rest_angle_bending(test, device):
563
- example = VBDClothSim(device, use_cuda_graph=True)
564
- example.set_up_non_zero_rest_angle_bending_experiment()
565
- example.finalize()
762
+ def test_cloth_body_collision(test, device, solver):
763
+ example = ClothSim(device, solver, use_cuda_graph=True)
764
+ example.set_body_collision_experiment(handle_self_contact=False)
765
+
766
+ example.run()
767
+
768
+ # examine that the velocity has died out
769
+ final_vel = example.state0.particle_qd.numpy()
770
+ final_pos = example.state0.particle_q.numpy()
771
+ test.assertTrue((np.linalg.norm(final_vel, axis=1) < 1.0).all())
772
+ # examine that the simulation has moved
773
+ test.assertTrue((example.init_pos[:, 1] != final_pos[:, 1]).any())
774
+
775
+ # run again with handle_self_contact=True
776
+ example = ClothSim(device, solver, use_cuda_graph=True)
777
+ example.set_body_collision_experiment(handle_self_contact=True)
778
+ example.run()
779
+ # examine that the velocity has died out
780
+ final_vel = example.state0.particle_qd.numpy()
781
+ final_pos = example.state0.particle_q.numpy()
782
+ test.assertTrue((np.linalg.norm(final_vel, axis=1) < 1.0).all())
783
+ # examine that the simulation has moved
784
+ test.assertTrue((example.init_pos[:, 1] != final_pos[:, 1]).any())
785
+
786
+
787
+ def test_cloth_self_collision(test, device, solver):
788
+ example = ClothSim(device, solver, use_cuda_graph=True)
789
+ example.set_self_collision_experiment()
790
+
791
+ example.run()
792
+
793
+ # examine that the velocity has died out
794
+ final_vel = example.state0.particle_qd.numpy()
795
+ final_pos = example.state0.particle_q.numpy()
796
+ test.assertTrue((np.linalg.norm(final_vel, axis=1) < 1.0).all())
797
+ # examine that the simulation has moved
798
+ test.assertTrue((example.init_pos != final_pos).any())
799
+
800
+
801
+ def test_cloth_free_fall(test, device, solver):
802
+ example = ClothSim(device, solver)
803
+ example.set_free_falling_experiment()
804
+
805
+ initial_pos = example.state0.particle_q.numpy().copy()
806
+
566
807
  example.run()
567
808
 
568
809
  # examine that the simulation does not explode
569
810
  final_pos = example.state0.particle_q.numpy()
570
811
  test.assertTrue((final_pos < 1e5).all())
571
- # examine that the simulation have moved
812
+ # examine that the simulation has moved
572
813
  test.assertTrue((example.init_pos != final_pos).any())
573
814
 
815
+ gravity = np.array(example.model.gravity)
816
+ diff = final_pos - initial_pos
817
+ vertical_translation_norm = diff @ gravity[..., None] / (np.linalg.norm(gravity) ** 2)
818
+ # ensure it's free-falling
819
+ test.assertTrue((np.abs(vertical_translation_norm - 0.5 * np.linalg.norm(gravity) * (example.dt**2)) < 2e-1).all())
820
+ horizontal_move = diff - (vertical_translation_norm * gravity)
821
+ # ensure its horizontal translation is minimal
822
+ test.assertTrue((np.abs(horizontal_move) < 1e-1).all())
823
+
574
824
 
575
- devices = get_test_devices()
576
- cuda_devices = get_selected_cuda_test_devices()
825
+ devices = get_test_devices(mode="basic")
577
826
 
578
827
 
579
- class TestVbd(unittest.TestCase):
828
+ class TestCloth(unittest.TestCase):
580
829
  pass
581
830
 
582
831
 
583
- add_function_test(TestVbd, "test_vbd_cloth", test_vbd_cloth, devices=devices)
584
- add_function_test(TestVbd, "test_vbd_cloth_cuda_graph", test_vbd_cloth_cuda_graph, devices=cuda_devices)
585
- add_function_test(TestVbd, "test_vbd_bending", test_vbd_bending, devices=devices, check_output=False)
586
- add_function_test(
587
- TestVbd,
588
- "test_vbd_bending_non_zero_rest_angle_bending",
589
- test_vbd_bending_non_zero_rest_angle_bending,
590
- devices=devices,
591
- check_output=False,
592
- )
832
+ tests_to_run = {
833
+ "xpbd": [
834
+ test_cloth_free_fall,
835
+ test_cloth_sagging,
836
+ test_cloth_bending,
837
+ test_cloth_bending_non_zero_rest_angle_bending,
838
+ ],
839
+ "semi_implicit": [
840
+ test_cloth_free_fall,
841
+ test_cloth_sagging,
842
+ test_cloth_bending,
843
+ ],
844
+ "vbd": [
845
+ test_cloth_free_fall,
846
+ test_cloth_sagging,
847
+ test_cloth_bending,
848
+ test_cloth_self_collision,
849
+ test_cloth_body_collision,
850
+ test_cloth_bending_non_zero_rest_angle_bending,
851
+ ],
852
+ }
853
+
854
+ for solver, tests in tests_to_run.items():
855
+ for test in tests:
856
+ add_function_test(
857
+ TestCloth, f"{test.__name__}_{solver}", partial(test, solver=solver), devices=devices, check_output=False
858
+ )
593
859
 
594
860
 
595
861
  if __name__ == "__main__":
596
862
  wp.clear_kernel_cache()
597
- unittest.main(verbosity=2)
863
+ unittest.main(verbosity=2, failfast=True)