warp-lang 1.7.2__py3-none-manylinux_2_34_aarch64.whl → 1.8.0__py3-none-manylinux_2_34_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of warp-lang might be problematic. Click here for more details.
- warp/__init__.py +3 -1
- warp/__init__.pyi +3489 -1
- warp/autograd.py +45 -122
- warp/bin/warp.so +0 -0
- warp/build.py +241 -252
- warp/build_dll.py +125 -26
- warp/builtins.py +1907 -384
- warp/codegen.py +257 -101
- warp/config.py +12 -1
- warp/constants.py +1 -1
- warp/context.py +657 -223
- warp/dlpack.py +1 -1
- warp/examples/benchmarks/benchmark_cloth.py +2 -2
- warp/examples/benchmarks/benchmark_tile_sort.py +155 -0
- warp/examples/core/example_sample_mesh.py +1 -1
- warp/examples/core/example_spin_lock.py +93 -0
- warp/examples/core/example_work_queue.py +118 -0
- warp/examples/fem/example_adaptive_grid.py +5 -5
- warp/examples/fem/example_apic_fluid.py +1 -1
- warp/examples/fem/example_burgers.py +1 -1
- warp/examples/fem/example_convection_diffusion.py +9 -6
- warp/examples/fem/example_darcy_ls_optimization.py +489 -0
- warp/examples/fem/example_deformed_geometry.py +1 -1
- warp/examples/fem/example_diffusion.py +2 -2
- warp/examples/fem/example_diffusion_3d.py +1 -1
- warp/examples/fem/example_distortion_energy.py +1 -1
- warp/examples/fem/example_elastic_shape_optimization.py +387 -0
- warp/examples/fem/example_magnetostatics.py +5 -3
- warp/examples/fem/example_mixed_elasticity.py +5 -3
- warp/examples/fem/example_navier_stokes.py +11 -9
- warp/examples/fem/example_nonconforming_contact.py +5 -3
- warp/examples/fem/example_streamlines.py +8 -3
- warp/examples/fem/utils.py +9 -8
- warp/examples/interop/example_jax_ffi_callback.py +2 -2
- warp/examples/optim/example_drone.py +1 -1
- warp/examples/sim/example_cloth.py +1 -1
- warp/examples/sim/example_cloth_self_contact.py +48 -54
- warp/examples/tile/example_tile_block_cholesky.py +502 -0
- warp/examples/tile/example_tile_cholesky.py +2 -1
- warp/examples/tile/example_tile_convolution.py +1 -1
- warp/examples/tile/example_tile_filtering.py +1 -1
- warp/examples/tile/example_tile_matmul.py +1 -1
- warp/examples/tile/example_tile_mlp.py +2 -0
- warp/fabric.py +7 -7
- warp/fem/__init__.py +5 -0
- warp/fem/adaptivity.py +1 -1
- warp/fem/cache.py +152 -63
- warp/fem/dirichlet.py +2 -2
- warp/fem/domain.py +136 -6
- warp/fem/field/field.py +141 -99
- warp/fem/field/nodal_field.py +85 -39
- warp/fem/field/virtual.py +97 -52
- warp/fem/geometry/adaptive_nanogrid.py +91 -86
- warp/fem/geometry/closest_point.py +13 -0
- warp/fem/geometry/deformed_geometry.py +102 -40
- warp/fem/geometry/element.py +56 -2
- warp/fem/geometry/geometry.py +323 -22
- warp/fem/geometry/grid_2d.py +157 -62
- warp/fem/geometry/grid_3d.py +116 -20
- warp/fem/geometry/hexmesh.py +86 -20
- warp/fem/geometry/nanogrid.py +166 -86
- warp/fem/geometry/partition.py +59 -25
- warp/fem/geometry/quadmesh.py +86 -135
- warp/fem/geometry/tetmesh.py +47 -119
- warp/fem/geometry/trimesh.py +77 -270
- warp/fem/integrate.py +107 -52
- warp/fem/linalg.py +25 -58
- warp/fem/operator.py +124 -27
- warp/fem/quadrature/pic_quadrature.py +36 -14
- warp/fem/quadrature/quadrature.py +40 -16
- warp/fem/space/__init__.py +1 -1
- warp/fem/space/basis_function_space.py +66 -46
- warp/fem/space/basis_space.py +17 -4
- warp/fem/space/dof_mapper.py +1 -1
- warp/fem/space/function_space.py +2 -2
- warp/fem/space/grid_2d_function_space.py +4 -1
- warp/fem/space/hexmesh_function_space.py +4 -2
- warp/fem/space/nanogrid_function_space.py +3 -1
- warp/fem/space/partition.py +11 -2
- warp/fem/space/quadmesh_function_space.py +4 -1
- warp/fem/space/restriction.py +5 -2
- warp/fem/space/shape/__init__.py +10 -8
- warp/fem/space/tetmesh_function_space.py +4 -1
- warp/fem/space/topology.py +52 -21
- warp/fem/space/trimesh_function_space.py +4 -1
- warp/fem/utils.py +53 -8
- warp/jax.py +1 -2
- warp/jax_experimental/ffi.py +12 -17
- warp/jax_experimental/xla_ffi.py +37 -24
- warp/math.py +171 -1
- warp/native/array.h +99 -0
- warp/native/builtin.h +174 -31
- warp/native/coloring.cpp +1 -1
- warp/native/exports.h +118 -63
- warp/native/intersect.h +3 -3
- warp/native/mat.h +5 -10
- warp/native/mathdx.cpp +11 -5
- warp/native/matnn.h +1 -123
- warp/native/quat.h +28 -4
- warp/native/sparse.cpp +121 -258
- warp/native/sparse.cu +181 -274
- warp/native/spatial.h +305 -17
- warp/native/tile.h +583 -72
- warp/native/tile_radix_sort.h +1108 -0
- warp/native/tile_reduce.h +237 -2
- warp/native/tile_scan.h +240 -0
- warp/native/tuple.h +189 -0
- warp/native/vec.h +6 -16
- warp/native/warp.cpp +36 -4
- warp/native/warp.cu +574 -51
- warp/native/warp.h +47 -74
- warp/optim/linear.py +5 -1
- warp/paddle.py +7 -8
- warp/py.typed +0 -0
- warp/render/render_opengl.py +58 -29
- warp/render/render_usd.py +124 -61
- warp/sim/__init__.py +9 -0
- warp/sim/collide.py +252 -78
- warp/sim/graph_coloring.py +8 -1
- warp/sim/import_mjcf.py +4 -3
- warp/sim/import_usd.py +11 -7
- warp/sim/integrator.py +5 -2
- warp/sim/integrator_euler.py +1 -1
- warp/sim/integrator_featherstone.py +1 -1
- warp/sim/integrator_vbd.py +751 -320
- warp/sim/integrator_xpbd.py +1 -1
- warp/sim/model.py +265 -260
- warp/sim/utils.py +10 -7
- warp/sparse.py +303 -166
- warp/tape.py +52 -51
- warp/tests/cuda/test_conditional_captures.py +1046 -0
- warp/tests/cuda/test_streams.py +1 -1
- warp/tests/geometry/test_volume.py +2 -2
- warp/tests/interop/test_dlpack.py +9 -9
- warp/tests/interop/test_jax.py +0 -1
- warp/tests/run_coverage_serial.py +1 -1
- warp/tests/sim/disabled_kinematics.py +2 -2
- warp/tests/sim/{test_vbd.py → test_cloth.py} +296 -113
- warp/tests/sim/test_collision.py +159 -51
- warp/tests/sim/test_coloring.py +15 -1
- warp/tests/test_array.py +254 -2
- warp/tests/test_array_reduce.py +2 -2
- warp/tests/test_atomic_cas.py +299 -0
- warp/tests/test_codegen.py +142 -19
- warp/tests/test_conditional.py +47 -1
- warp/tests/test_ctypes.py +0 -20
- warp/tests/test_devices.py +8 -0
- warp/tests/test_fabricarray.py +4 -2
- warp/tests/test_fem.py +58 -25
- warp/tests/test_func.py +42 -1
- warp/tests/test_grad.py +1 -1
- warp/tests/test_lerp.py +1 -3
- warp/tests/test_map.py +481 -0
- warp/tests/test_mat.py +1 -24
- warp/tests/test_quat.py +6 -15
- warp/tests/test_rounding.py +10 -38
- warp/tests/test_runlength_encode.py +7 -7
- warp/tests/test_smoothstep.py +1 -1
- warp/tests/test_sparse.py +51 -2
- warp/tests/test_spatial.py +507 -1
- warp/tests/test_struct.py +2 -2
- warp/tests/test_tuple.py +265 -0
- warp/tests/test_types.py +2 -2
- warp/tests/test_utils.py +24 -18
- warp/tests/tile/test_tile.py +420 -1
- warp/tests/tile/test_tile_mathdx.py +518 -14
- warp/tests/tile/test_tile_reduce.py +213 -0
- warp/tests/tile/test_tile_shared_memory.py +130 -1
- warp/tests/tile/test_tile_sort.py +117 -0
- warp/tests/unittest_suites.py +4 -6
- warp/types.py +462 -308
- warp/utils.py +647 -86
- {warp_lang-1.7.2.dist-info → warp_lang-1.8.0.dist-info}/METADATA +20 -6
- {warp_lang-1.7.2.dist-info → warp_lang-1.8.0.dist-info}/RECORD +177 -165
- warp/stubs.py +0 -3381
- warp/tests/sim/test_xpbd.py +0 -399
- warp/tests/test_mlp.py +0 -282
- {warp_lang-1.7.2.dist-info → warp_lang-1.8.0.dist-info}/WHEEL +0 -0
- {warp_lang-1.7.2.dist-info → warp_lang-1.8.0.dist-info}/licenses/LICENSE.md +0 -0
- {warp_lang-1.7.2.dist-info → warp_lang-1.8.0.dist-info}/top_level.txt +0 -0
warp/tests/cuda/test_streams.py
CHANGED
|
@@ -492,7 +492,7 @@ class TestStreams(unittest.TestCase):
|
|
|
492
492
|
|
|
493
493
|
# Can't get the stream on a CPU device
|
|
494
494
|
with self.assertRaises(RuntimeError):
|
|
495
|
-
cpu_stream = cpu_device.stream
|
|
495
|
+
cpu_stream = cpu_device.stream
|
|
496
496
|
|
|
497
497
|
@unittest.skipUnless(len(wp.get_cuda_devices()) > 1, "Requires at least two CUDA devices")
|
|
498
498
|
@unittest.skipUnless(check_p2p(), "Peer-to-Peer transfers not supported")
|
|
@@ -893,7 +893,7 @@ def test_volume_from_numpy_3d(test, device):
|
|
|
893
893
|
nums = np.ceil((maxs - mins) / (voxel_size)).astype(dtype=int)
|
|
894
894
|
centers = np.array([[-1.0, -1.0, -1.0], [0.0, 0.0, 0.0], [1.0, 1.0, 1.0]])
|
|
895
895
|
rad = 2.5
|
|
896
|
-
sphere_sdf_np = np.zeros(tuple(nums)
|
|
896
|
+
sphere_sdf_np = np.zeros((*tuple(nums), 3))
|
|
897
897
|
for x in range(nums[0]):
|
|
898
898
|
for y in range(nums[1]):
|
|
899
899
|
for z in range(nums[2]):
|
|
@@ -935,7 +935,7 @@ def test_volume_aniso_transform(test, device):
|
|
|
935
935
|
def test_volume_write(test, device):
|
|
936
936
|
codecs = ["none", "zip", "blosc"]
|
|
937
937
|
try:
|
|
938
|
-
import blosc # noqa: F401
|
|
938
|
+
import blosc # noqa: F401
|
|
939
939
|
except ImportError:
|
|
940
940
|
codecs.pop()
|
|
941
941
|
|
|
@@ -412,8 +412,8 @@ def test_dlpack_warp_to_jax(test, device):
|
|
|
412
412
|
|
|
413
413
|
test.assertEqual(a.ptr, j1.unsafe_buffer_pointer())
|
|
414
414
|
test.assertEqual(a.ptr, j2.unsafe_buffer_pointer())
|
|
415
|
-
test.assertEqual(a.device, wp.device_from_jax(
|
|
416
|
-
test.assertEqual(a.device, wp.device_from_jax(
|
|
415
|
+
test.assertEqual(a.device, wp.device_from_jax(next(iter(j1.devices()))))
|
|
416
|
+
test.assertEqual(a.device, wp.device_from_jax(next(iter(j2.devices()))))
|
|
417
417
|
test.assertEqual(a.shape, j1.shape)
|
|
418
418
|
test.assertEqual(a.shape, j2.shape)
|
|
419
419
|
|
|
@@ -460,8 +460,8 @@ def test_dlpack_warp_to_jax_v2(test, device):
|
|
|
460
460
|
|
|
461
461
|
test.assertEqual(a.ptr, j1.unsafe_buffer_pointer())
|
|
462
462
|
test.assertEqual(a.ptr, j2.unsafe_buffer_pointer())
|
|
463
|
-
test.assertEqual(a.device, wp.device_from_jax(
|
|
464
|
-
test.assertEqual(a.device, wp.device_from_jax(
|
|
463
|
+
test.assertEqual(a.device, wp.device_from_jax(next(iter(j1.devices()))))
|
|
464
|
+
test.assertEqual(a.device, wp.device_from_jax(next(iter(j2.devices()))))
|
|
465
465
|
test.assertEqual(a.shape, j1.shape)
|
|
466
466
|
test.assertEqual(a.shape, j2.shape)
|
|
467
467
|
|
|
@@ -543,15 +543,15 @@ def test_dlpack_jax_to_warp(test, device):
|
|
|
543
543
|
j = jax.numpy.arange(N, dtype=jax.numpy.float32)
|
|
544
544
|
|
|
545
545
|
# use generic dlpack conversion
|
|
546
|
-
a1 = wp.from_dlpack(
|
|
546
|
+
a1 = wp.from_dlpack(j)
|
|
547
547
|
|
|
548
548
|
# use jax wrapper
|
|
549
549
|
a2 = wp.from_jax(j)
|
|
550
550
|
|
|
551
551
|
test.assertEqual(a1.ptr, j.unsafe_buffer_pointer())
|
|
552
552
|
test.assertEqual(a2.ptr, j.unsafe_buffer_pointer())
|
|
553
|
-
test.assertEqual(a1.device, wp.device_from_jax(
|
|
554
|
-
test.assertEqual(a2.device, wp.device_from_jax(
|
|
553
|
+
test.assertEqual(a1.device, wp.device_from_jax(next(iter(j.devices()))))
|
|
554
|
+
test.assertEqual(a2.device, wp.device_from_jax(next(iter(j.devices()))))
|
|
555
555
|
test.assertEqual(a1.shape, j.shape)
|
|
556
556
|
test.assertEqual(a2.shape, j.shape)
|
|
557
557
|
|
|
@@ -586,8 +586,8 @@ def test_dlpack_jax_to_warp_v2(test, device):
|
|
|
586
586
|
|
|
587
587
|
test.assertEqual(a1.ptr, j.unsafe_buffer_pointer())
|
|
588
588
|
test.assertEqual(a2.ptr, j.unsafe_buffer_pointer())
|
|
589
|
-
test.assertEqual(a1.device, wp.device_from_jax(
|
|
590
|
-
test.assertEqual(a2.device, wp.device_from_jax(
|
|
589
|
+
test.assertEqual(a1.device, wp.device_from_jax(next(iter(j.devices()))))
|
|
590
|
+
test.assertEqual(a2.device, wp.device_from_jax(next(iter(j.devices()))))
|
|
591
591
|
test.assertEqual(a1.shape, j.shape)
|
|
592
592
|
test.assertEqual(a2.shape, j.shape)
|
|
593
593
|
|
warp/tests/interop/test_jax.py
CHANGED
|
@@ -123,7 +123,7 @@ def build_complex_joint_mechanism(chain_length):
|
|
|
123
123
|
parent_xform=tf1,
|
|
124
124
|
child_xform=tf2,
|
|
125
125
|
)
|
|
126
|
-
builder.joint_q[-7:] = [0.5, -0.9, 1.4
|
|
126
|
+
builder.joint_q[-7:] = [0.5, -0.9, 1.4, *wp.quat_rpy(0.3, -0.5, 0.7)]
|
|
127
127
|
builder.joint_qd[-6:] = [1.0, -1.0, 0.5, 0.8, -0.3, 0.1]
|
|
128
128
|
|
|
129
129
|
b8 = builder.add_body(com=com2)
|
|
@@ -133,7 +133,7 @@ def build_complex_joint_mechanism(chain_length):
|
|
|
133
133
|
parent_xform=tf1,
|
|
134
134
|
child_xform=tf2,
|
|
135
135
|
)
|
|
136
|
-
builder.joint_q[-7:] = [-0.3, -0.7, 0.2
|
|
136
|
+
builder.joint_q[-7:] = [-0.3, -0.7, 0.2, *wp.quat_rpy(0.1, 0.1, 0.4)]
|
|
137
137
|
builder.joint_qd[-6:] = [-0.34, 0.5, -0.6, -0.4, 0.2, 0.1]
|
|
138
138
|
|
|
139
139
|
# D6 joint that behaves like a fixed joint
|
|
@@ -13,15 +13,18 @@
|
|
|
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.
|
|
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
|
|
25
28
|
from warp.sim.model import PARTICLE_FLAG_ACTIVE
|
|
26
29
|
from warp.tests.unittest_utils import *
|
|
27
30
|
|
|
@@ -295,40 +298,62 @@ CLOTH_FACES = [
|
|
|
295
298
|
]
|
|
296
299
|
|
|
297
300
|
# fmt: on
|
|
298
|
-
class
|
|
299
|
-
def __init__(self, device, use_cuda_graph=False):
|
|
301
|
+
class ClothSim:
|
|
302
|
+
def __init__(self, device, solver, use_cuda_graph=False):
|
|
300
303
|
self.frame_dt = 1 / 60
|
|
301
|
-
self.num_test_frames =
|
|
302
|
-
self.
|
|
303
|
-
self.iterations = 10
|
|
304
|
-
self.dt = self.frame_dt / self.num_substeps
|
|
304
|
+
self.num_test_frames = 50
|
|
305
|
+
self.iterations = 5
|
|
305
306
|
self.device = device
|
|
306
307
|
self.use_cuda_graph = self.device.is_cuda and use_cuda_graph
|
|
307
308
|
self.builder = wp.sim.ModelBuilder()
|
|
309
|
+
self.solver = solver
|
|
308
310
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
311
|
+
if solver != "semi_implicit":
|
|
312
|
+
self.num_substeps = 10
|
|
313
|
+
else:
|
|
314
|
+
self.num_substeps = 32
|
|
315
|
+
self.dt = self.frame_dt / self.num_substeps
|
|
312
316
|
|
|
317
|
+
def set_up_sagging_experiment(self):
|
|
313
318
|
self.input_scale_factor = 1.0
|
|
314
319
|
self.renderer_scale_factor = 0.01
|
|
315
320
|
vertices = [wp.vec3(v) * self.input_scale_factor for v in CLOTH_POINTS]
|
|
316
321
|
faces_flatten = [fv - 1 for fv in CLOTH_FACES]
|
|
317
322
|
|
|
323
|
+
kd = 1.0e-7
|
|
324
|
+
|
|
325
|
+
if self.solver != "semi_implicit":
|
|
326
|
+
stretching_stiffness = 1e4
|
|
327
|
+
spring_ke = 1e3
|
|
328
|
+
bending_ke = 10
|
|
329
|
+
else:
|
|
330
|
+
stretching_stiffness = 1e5
|
|
331
|
+
spring_ke = 1e2
|
|
332
|
+
bending_ke = 0.0
|
|
333
|
+
|
|
318
334
|
self.builder.add_cloth_mesh(
|
|
319
|
-
pos=wp.vec3(0.0,
|
|
335
|
+
pos=wp.vec3(0.0, 0.0, 0.0),
|
|
320
336
|
rot=wp.quat_from_axis_angle(wp.vec3(1.0, 0.0, 0.0), 0.0),
|
|
321
337
|
scale=1.0,
|
|
322
338
|
vertices=vertices,
|
|
323
339
|
indices=faces_flatten,
|
|
324
340
|
vel=wp.vec3(0.0, 0.0, 0.0),
|
|
325
|
-
density=0.
|
|
326
|
-
tri_ke=
|
|
327
|
-
tri_ka=
|
|
341
|
+
density=0.1,
|
|
342
|
+
tri_ke=stretching_stiffness,
|
|
343
|
+
tri_ka=stretching_stiffness,
|
|
328
344
|
tri_kd=kd,
|
|
345
|
+
edge_ke=bending_ke,
|
|
346
|
+
add_springs=self.solver == "xpbd",
|
|
347
|
+
spring_ke=spring_ke,
|
|
348
|
+
spring_kd=0.0,
|
|
329
349
|
)
|
|
350
|
+
|
|
330
351
|
self.fixed_particles = [0, 9]
|
|
331
352
|
|
|
353
|
+
self.finalize(ground=False)
|
|
354
|
+
|
|
355
|
+
self.state1.particle_q.fill_(0.0)
|
|
356
|
+
|
|
332
357
|
def set_up_bending_experiment(self):
|
|
333
358
|
stretching_stiffness = 1e4
|
|
334
359
|
stretching_damping = 1e-6
|
|
@@ -364,6 +389,9 @@ class VBDClothSim:
|
|
|
364
389
|
tri_kd=stretching_damping,
|
|
365
390
|
edge_ke=10,
|
|
366
391
|
edge_kd=bending_damping,
|
|
392
|
+
add_springs=self.solver == "xpbd",
|
|
393
|
+
spring_ke=1.0e3,
|
|
394
|
+
spring_kd=0.0,
|
|
367
395
|
)
|
|
368
396
|
|
|
369
397
|
self.builder.add_cloth_mesh(
|
|
@@ -379,6 +407,9 @@ class VBDClothSim:
|
|
|
379
407
|
tri_kd=stretching_damping,
|
|
380
408
|
edge_ke=100,
|
|
381
409
|
edge_kd=bending_damping,
|
|
410
|
+
add_springs=self.solver == "xpbd",
|
|
411
|
+
spring_ke=1.0e3,
|
|
412
|
+
spring_kd=0.0,
|
|
382
413
|
)
|
|
383
414
|
|
|
384
415
|
self.builder.add_cloth_mesh(
|
|
@@ -394,57 +425,117 @@ class VBDClothSim:
|
|
|
394
425
|
tri_kd=stretching_damping,
|
|
395
426
|
edge_ke=1000,
|
|
396
427
|
edge_kd=bending_damping,
|
|
428
|
+
add_springs=self.solver == "xpbd",
|
|
429
|
+
spring_ke=1.0e3,
|
|
430
|
+
spring_kd=0.0,
|
|
397
431
|
)
|
|
398
432
|
|
|
399
433
|
self.fixed_particles = [0, 29, 36, 65, 72, 101]
|
|
400
434
|
|
|
435
|
+
self.finalize()
|
|
436
|
+
|
|
437
|
+
def set_collision_experiment(self):
|
|
438
|
+
elasticity_ke = 1e4
|
|
439
|
+
elasticity_kd = 1e-6
|
|
440
|
+
|
|
441
|
+
vs1 = [wp.vec3(v) for v in [[0, 0, 0], [1, 0, 0], [1, 0, 1], [0, 0, 1]]]
|
|
442
|
+
fs1 = [0, 1, 2, 0, 2, 3]
|
|
443
|
+
|
|
444
|
+
self.builder.add_cloth_mesh(
|
|
445
|
+
pos=wp.vec3(0.0, 0.0, 0.0),
|
|
446
|
+
rot=wp.quat_from_axis_angle(wp.vec3(1.0, 0.0, 0.0), 0.0),
|
|
447
|
+
scale=1.0,
|
|
448
|
+
vertices=vs1,
|
|
449
|
+
indices=fs1,
|
|
450
|
+
vel=wp.vec3(0.0, 0.0, 0.0),
|
|
451
|
+
density=0.02,
|
|
452
|
+
tri_ke=elasticity_ke,
|
|
453
|
+
tri_ka=elasticity_ke,
|
|
454
|
+
tri_kd=elasticity_kd,
|
|
455
|
+
add_springs=self.solver == "xpbd",
|
|
456
|
+
spring_ke=1.0e3,
|
|
457
|
+
spring_kd=0.0,
|
|
458
|
+
)
|
|
459
|
+
|
|
460
|
+
vs2 = [wp.vec3(v) for v in [[0.3, 0, 0.7], [0.3, 0, 0.2], [0.8, 0, 0.4]]]
|
|
461
|
+
fs2 = [0, 1, 2]
|
|
462
|
+
|
|
463
|
+
self.builder.add_cloth_mesh(
|
|
464
|
+
pos=wp.vec3(0.0, 0.5, 0.0),
|
|
465
|
+
rot=wp.quat_from_axis_angle(wp.vec3(1.0, 0.0, 0.0), 0.0),
|
|
466
|
+
scale=1.0,
|
|
467
|
+
vertices=vs2,
|
|
468
|
+
indices=fs2,
|
|
469
|
+
vel=wp.vec3(0.0, 0.0, 0.0),
|
|
470
|
+
density=0.02,
|
|
471
|
+
tri_ke=elasticity_ke,
|
|
472
|
+
tri_ka=elasticity_ke,
|
|
473
|
+
tri_kd=elasticity_kd,
|
|
474
|
+
add_springs=self.solver == "xpbd",
|
|
475
|
+
spring_ke=1.0e3,
|
|
476
|
+
spring_kd=0.0,
|
|
477
|
+
)
|
|
478
|
+
|
|
479
|
+
self.fixed_particles = range(0, 4)
|
|
480
|
+
|
|
481
|
+
self.finalize(handle_self_contact=True, ground=False)
|
|
482
|
+
self.model.soft_contact_radius = 0.1
|
|
483
|
+
self.model.soft_contact_margin = 0.1
|
|
484
|
+
self.model.soft_contact_ke = 1e4
|
|
485
|
+
self.model.soft_contact_kd = 1e-3
|
|
486
|
+
self.model.soft_contact_mu = 0.2
|
|
487
|
+
self.model.gravity = wp.vec3(0.0, -1000.0, 0)
|
|
488
|
+
self.num_test_frames = 30
|
|
489
|
+
|
|
401
490
|
def set_up_non_zero_rest_angle_bending_experiment(self):
|
|
402
491
|
# fmt: off
|
|
403
|
-
vs =
|
|
404
|
-
[
|
|
405
|
-
[
|
|
406
|
-
[
|
|
407
|
-
[
|
|
408
|
-
[
|
|
409
|
-
[
|
|
410
|
-
[
|
|
411
|
-
[
|
|
412
|
-
[
|
|
413
|
-
[
|
|
414
|
-
[
|
|
415
|
-
[
|
|
416
|
-
[-
|
|
417
|
-
[-
|
|
418
|
-
[
|
|
419
|
-
[
|
|
492
|
+
vs =[
|
|
493
|
+
[ 0. , 1. , -1. ],
|
|
494
|
+
[ 0. , 1. , 1. ],
|
|
495
|
+
[ 0.70711, 0.70711, -1. ],
|
|
496
|
+
[ 0.70711, 0.70711, 1. ],
|
|
497
|
+
[ 1. , 0. , -1. ],
|
|
498
|
+
[ 1. , -0. , 1. ],
|
|
499
|
+
[ 0.70711, -0.70711, -1. ],
|
|
500
|
+
[ 0.70711, -0.70711, 1. ],
|
|
501
|
+
[ 0. , -1. , -1. ],
|
|
502
|
+
[ 0. , -1. , 1. ],
|
|
503
|
+
[-0.70711, -0.70711, -1. ],
|
|
504
|
+
[-0.70711, -0.70711, 1. ],
|
|
505
|
+
[-1. , 0. , -1. ],
|
|
506
|
+
[-1. , -0. , 1. ],
|
|
507
|
+
[-0.70711, 0.70711, -1. ],
|
|
508
|
+
[-0.70711, 0.70711, 1. ],
|
|
420
509
|
]
|
|
421
510
|
fs = [
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
511
|
+
1, 2, 0,
|
|
512
|
+
3, 4, 2,
|
|
513
|
+
5, 6, 4,
|
|
514
|
+
7, 8, 6,
|
|
515
|
+
9, 10, 8,
|
|
516
|
+
11, 12, 10,
|
|
517
|
+
3, 5, 4,
|
|
518
|
+
13, 14, 12,
|
|
519
|
+
15, 0, 14,
|
|
520
|
+
1, 3, 2,
|
|
521
|
+
5, 7, 6,
|
|
522
|
+
7, 9, 8,
|
|
523
|
+
9, 11, 10,
|
|
524
|
+
11, 13, 12,
|
|
525
|
+
13, 15, 14,
|
|
526
|
+
15, 1, 0,
|
|
436
527
|
]
|
|
437
528
|
# fmt: on
|
|
438
529
|
|
|
439
|
-
stretching_stiffness =
|
|
440
|
-
stretching_damping = 1e-
|
|
441
|
-
edge_ke =
|
|
442
|
-
bending_damping = 1e-
|
|
530
|
+
stretching_stiffness = 1e5
|
|
531
|
+
stretching_damping = 1e-5
|
|
532
|
+
edge_ke = 100
|
|
533
|
+
bending_damping = 1e-4
|
|
443
534
|
vs = [wp.vec3(v) for v in vs]
|
|
444
535
|
|
|
445
536
|
self.builder.add_cloth_mesh(
|
|
446
|
-
pos=wp.vec3(0.0,
|
|
447
|
-
rot=wp.
|
|
537
|
+
pos=wp.vec3(0.0, 0.0, 0.0),
|
|
538
|
+
rot=wp.quat_identity(),
|
|
448
539
|
scale=1.0,
|
|
449
540
|
vertices=vs,
|
|
450
541
|
indices=fs,
|
|
@@ -455,21 +546,71 @@ class VBDClothSim:
|
|
|
455
546
|
tri_kd=stretching_damping,
|
|
456
547
|
edge_ke=edge_ke,
|
|
457
548
|
edge_kd=bending_damping,
|
|
549
|
+
add_springs=self.solver == "xpbd",
|
|
550
|
+
spring_ke=1.0e3,
|
|
551
|
+
spring_kd=0.0,
|
|
458
552
|
)
|
|
459
553
|
self.fixed_particles = [0, 1]
|
|
460
554
|
|
|
461
|
-
|
|
462
|
-
|
|
555
|
+
self.finalize(handle_self_contact=False, ground=False)
|
|
556
|
+
|
|
557
|
+
def set_free_falling_experiment(self):
|
|
558
|
+
self.input_scale_factor = 1.0
|
|
559
|
+
self.renderer_scale_factor = 0.01
|
|
560
|
+
vertices = [wp.vec3(v) * self.input_scale_factor for v in CLOTH_POINTS]
|
|
561
|
+
faces_flatten = [fv - 1 for fv in CLOTH_FACES]
|
|
562
|
+
if self.solver != "semi_implicit":
|
|
563
|
+
stretching_stiffness = 1e4
|
|
564
|
+
spring_ke = 1e3
|
|
565
|
+
bending_ke = 10
|
|
566
|
+
else:
|
|
567
|
+
stretching_stiffness = 1e2
|
|
568
|
+
spring_ke = 1e2
|
|
569
|
+
bending_ke = 10
|
|
570
|
+
|
|
571
|
+
self.builder.add_cloth_mesh(
|
|
572
|
+
vertices=vertices,
|
|
573
|
+
indices=faces_flatten,
|
|
574
|
+
scale=0.1,
|
|
575
|
+
density=2,
|
|
576
|
+
pos=wp.vec3(0.0, 4.0, 0.0),
|
|
577
|
+
rot=wp.quat_identity(),
|
|
578
|
+
vel=wp.vec3(0.0, 0.0, 0.0),
|
|
579
|
+
edge_ke=bending_ke,
|
|
580
|
+
edge_kd=0.0,
|
|
581
|
+
tri_ke=stretching_stiffness,
|
|
582
|
+
tri_ka=stretching_stiffness,
|
|
583
|
+
tri_kd=0.0,
|
|
584
|
+
add_springs=self.solver == "xpbd",
|
|
585
|
+
spring_ke=spring_ke,
|
|
586
|
+
spring_kd=0.0,
|
|
587
|
+
)
|
|
588
|
+
self.fixed_particles = []
|
|
589
|
+
self.num_test_frames = 30
|
|
590
|
+
self.finalize(ground=False)
|
|
591
|
+
|
|
592
|
+
def finalize(self, handle_self_contact=False, ground=True):
|
|
593
|
+
self.builder.color(include_bending=True)
|
|
463
594
|
|
|
464
595
|
self.model = self.builder.finalize(device=self.device)
|
|
465
|
-
self.model.ground =
|
|
596
|
+
self.model.ground = ground
|
|
466
597
|
self.model.gravity = wp.vec3(0, -1000.0, 0)
|
|
467
598
|
self.model.soft_contact_ke = 1.0e4
|
|
468
|
-
self.model.soft_contact_kd = 1.
|
|
599
|
+
self.model.soft_contact_kd = 1.0e-2
|
|
469
600
|
|
|
470
601
|
self.set_points_fixed(self.model, self.fixed_particles)
|
|
471
602
|
|
|
472
|
-
self.
|
|
603
|
+
if self.solver == "vbd":
|
|
604
|
+
self.integrator = wp.sim.VBDIntegrator(self.model, self.iterations, handle_self_contact=handle_self_contact)
|
|
605
|
+
elif self.solver == "xpbd":
|
|
606
|
+
self.integrator = wp.sim.XPBDIntegrator(
|
|
607
|
+
self.iterations,
|
|
608
|
+
)
|
|
609
|
+
elif self.solver == "semi_implicit":
|
|
610
|
+
self.integrator = wp.sim.SemiImplicitIntegrator()
|
|
611
|
+
else:
|
|
612
|
+
raise ValueError("Unsupported solver type: " + self.solver)
|
|
613
|
+
|
|
473
614
|
self.state0 = self.model.state()
|
|
474
615
|
self.state1 = self.model.state()
|
|
475
616
|
|
|
@@ -477,23 +618,37 @@ class VBDClothSim:
|
|
|
477
618
|
|
|
478
619
|
self.graph = None
|
|
479
620
|
if self.use_cuda_graph:
|
|
621
|
+
if self.solver == "vbd":
|
|
622
|
+
wp.set_module_options({"block_dim": 256}, warp.sim.integrator_vbd)
|
|
623
|
+
wp.load_module(warp.sim.integrator_vbd, device=self.device)
|
|
624
|
+
elif self.solver == "xpbd":
|
|
625
|
+
wp.set_module_options({"block_dim": 256}, warp.sim.integrator_xpbd)
|
|
626
|
+
wp.load_module(warp.sim.integrator_xpbd, device=self.device)
|
|
627
|
+
elif self.solver == "semi_implicit":
|
|
628
|
+
wp.set_module_options({"block_dim": 256}, warp.sim.integrator_euler)
|
|
629
|
+
wp.load_module(warp.sim.integrator_euler, device=self.device)
|
|
630
|
+
wp.load_module(warp.sim.particles, device=self.device)
|
|
631
|
+
wp.load_module(warp.sim.integrator, device=self.device)
|
|
480
632
|
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
633
|
with wp.ScopedCapture(device=self.device, force_module_load=False) as capture:
|
|
484
634
|
self.simulate()
|
|
485
635
|
self.graph = capture.graph
|
|
486
636
|
|
|
487
637
|
def simulate(self):
|
|
488
|
-
for _step in range(self.num_substeps
|
|
638
|
+
for _step in range(self.num_substeps):
|
|
639
|
+
self.state0.clear_forces()
|
|
640
|
+
|
|
489
641
|
self.integrator.simulate(self.model, self.state0, self.state1, self.dt, None)
|
|
490
642
|
(self.state0, self.state1) = (self.state1, self.state0)
|
|
491
643
|
|
|
492
644
|
def run(self):
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
645
|
+
self.sim_time = 0.0
|
|
646
|
+
for _frame in range(self.num_test_frames):
|
|
647
|
+
if self.graph:
|
|
648
|
+
wp.capture_launch(self.graph)
|
|
649
|
+
else:
|
|
650
|
+
self.simulate()
|
|
651
|
+
self.sim_time = self.sim_time + self.frame_dt
|
|
497
652
|
|
|
498
653
|
def set_points_fixed(self, model, fixed_particles):
|
|
499
654
|
if len(fixed_particles):
|
|
@@ -504,94 +659,122 @@ class VBDClothSim:
|
|
|
504
659
|
model.particle_flags = wp.array(flags, device=model.device)
|
|
505
660
|
|
|
506
661
|
|
|
507
|
-
def
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
example.set_up_bending_experiment()
|
|
511
|
-
example.finalize()
|
|
512
|
-
example.model.ground = False
|
|
662
|
+
def test_cloth_sagging(test, device, solver):
|
|
663
|
+
example = ClothSim(device, solver, use_cuda_graph=True)
|
|
664
|
+
example.set_up_sagging_experiment()
|
|
513
665
|
|
|
514
|
-
|
|
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
|
-
)
|
|
666
|
+
initial_pos = example.state0.particle_q.numpy().copy()
|
|
518
667
|
|
|
519
668
|
example.run()
|
|
520
669
|
|
|
670
|
+
fixed_points = np.where(np.logical_not(example.model.particle_flags.numpy()))
|
|
521
671
|
# examine that the simulation does not explode
|
|
522
672
|
final_pos = example.state0.particle_q.numpy()
|
|
673
|
+
test.assertTrue((initial_pos[fixed_points, :] == final_pos[fixed_points, :]).all())
|
|
523
674
|
test.assertTrue((final_pos < 1e5).all())
|
|
524
|
-
# examine that the simulation
|
|
675
|
+
# examine that the simulation has moved
|
|
525
676
|
test.assertTrue((example.init_pos != final_pos).any())
|
|
526
677
|
|
|
527
678
|
|
|
528
|
-
def
|
|
529
|
-
|
|
530
|
-
|
|
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
|
-
)
|
|
679
|
+
def test_cloth_bending(test, device, solver):
|
|
680
|
+
example = ClothSim(device, solver, use_cuda_graph=True)
|
|
681
|
+
example.set_up_bending_experiment()
|
|
538
682
|
|
|
539
683
|
example.run()
|
|
540
684
|
|
|
541
685
|
# examine that the simulation does not explode
|
|
542
686
|
final_pos = example.state0.particle_q.numpy()
|
|
543
687
|
test.assertTrue((final_pos < 1e5).all())
|
|
544
|
-
# examine that the simulation
|
|
688
|
+
# examine that the simulation has moved
|
|
545
689
|
test.assertTrue((example.init_pos != final_pos).any())
|
|
546
690
|
|
|
547
691
|
|
|
548
|
-
def
|
|
549
|
-
example =
|
|
550
|
-
example.
|
|
551
|
-
example.finalize()
|
|
692
|
+
def test_cloth_bending_non_zero_rest_angle_bending(test, device, solver):
|
|
693
|
+
example = ClothSim(device, solver, use_cuda_graph=True)
|
|
694
|
+
example.set_up_non_zero_rest_angle_bending_experiment()
|
|
552
695
|
|
|
553
696
|
example.run()
|
|
554
697
|
|
|
555
698
|
# examine that the simulation does not explode
|
|
556
699
|
final_pos = example.state0.particle_q.numpy()
|
|
557
|
-
test.assertTrue((final_pos < 1e5).all())
|
|
558
|
-
# examine that the simulation
|
|
700
|
+
test.assertTrue((np.abs(final_pos) < 1e5).all())
|
|
701
|
+
# examine that the simulation has moved
|
|
559
702
|
test.assertTrue((example.init_pos != final_pos).any())
|
|
560
703
|
|
|
561
704
|
|
|
562
|
-
def
|
|
563
|
-
example =
|
|
564
|
-
example.
|
|
565
|
-
|
|
705
|
+
def test_cloth_collision(test, device, solver):
|
|
706
|
+
example = ClothSim(device, solver, use_cuda_graph=True)
|
|
707
|
+
example.set_collision_experiment()
|
|
708
|
+
|
|
709
|
+
example.run()
|
|
710
|
+
|
|
711
|
+
# examine that the velocity has died out
|
|
712
|
+
final_vel = example.state0.particle_qd.numpy()
|
|
713
|
+
final_pos = example.state0.particle_q.numpy()
|
|
714
|
+
test.assertTrue((np.linalg.norm(final_vel, axis=0) < 1.0).all())
|
|
715
|
+
# examine that the simulation has moved
|
|
716
|
+
test.assertTrue((example.init_pos != final_pos).any())
|
|
717
|
+
|
|
718
|
+
|
|
719
|
+
def test_cloth_free_fall(test, device, solver):
|
|
720
|
+
example = ClothSim(device, solver)
|
|
721
|
+
example.set_free_falling_experiment()
|
|
722
|
+
|
|
723
|
+
initial_pos = example.state0.particle_q.numpy().copy()
|
|
724
|
+
|
|
566
725
|
example.run()
|
|
567
726
|
|
|
568
727
|
# examine that the simulation does not explode
|
|
569
728
|
final_pos = example.state0.particle_q.numpy()
|
|
570
729
|
test.assertTrue((final_pos < 1e5).all())
|
|
571
|
-
# examine that the simulation
|
|
730
|
+
# examine that the simulation has moved
|
|
572
731
|
test.assertTrue((example.init_pos != final_pos).any())
|
|
573
732
|
|
|
733
|
+
gravity = np.array(example.model.gravity)
|
|
734
|
+
diff = final_pos - initial_pos
|
|
735
|
+
vertical_translation_norm = diff @ gravity[..., None] / (np.linalg.norm(gravity) ** 2)
|
|
736
|
+
# ensure it's free-falling
|
|
737
|
+
test.assertTrue((np.abs(vertical_translation_norm - 0.5 * np.linalg.norm(gravity) * (example.dt**2)) < 2e-1).all())
|
|
738
|
+
horizontal_move = diff - (vertical_translation_norm * gravity)
|
|
739
|
+
# ensure its horizontal translation is minimal
|
|
740
|
+
test.assertTrue((np.abs(horizontal_move) < 1e-1).all())
|
|
574
741
|
|
|
575
|
-
devices = get_test_devices()
|
|
576
|
-
cuda_devices = get_selected_cuda_test_devices()
|
|
577
742
|
|
|
743
|
+
devices = get_test_devices(mode="basic")
|
|
578
744
|
|
|
579
|
-
|
|
745
|
+
|
|
746
|
+
class TestCloth(unittest.TestCase):
|
|
580
747
|
pass
|
|
581
748
|
|
|
582
749
|
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
750
|
+
tests_to_run = {
|
|
751
|
+
"xpbd": [
|
|
752
|
+
test_cloth_free_fall,
|
|
753
|
+
test_cloth_sagging,
|
|
754
|
+
test_cloth_bending,
|
|
755
|
+
test_cloth_bending_non_zero_rest_angle_bending,
|
|
756
|
+
],
|
|
757
|
+
"semi_implicit": [
|
|
758
|
+
test_cloth_free_fall,
|
|
759
|
+
test_cloth_sagging,
|
|
760
|
+
test_cloth_bending,
|
|
761
|
+
],
|
|
762
|
+
"vbd": [
|
|
763
|
+
test_cloth_free_fall,
|
|
764
|
+
test_cloth_sagging,
|
|
765
|
+
test_cloth_bending,
|
|
766
|
+
test_cloth_collision,
|
|
767
|
+
test_cloth_bending_non_zero_rest_angle_bending,
|
|
768
|
+
],
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
for solver, tests in tests_to_run.items():
|
|
772
|
+
for test in tests:
|
|
773
|
+
add_function_test(
|
|
774
|
+
TestCloth, f"{test.__name__}_{solver}", partial(test, solver=solver), devices=devices, check_output=False
|
|
775
|
+
)
|
|
593
776
|
|
|
594
777
|
|
|
595
778
|
if __name__ == "__main__":
|
|
596
779
|
wp.clear_kernel_cache()
|
|
597
|
-
unittest.main(verbosity=2)
|
|
780
|
+
unittest.main(verbosity=2, failfast=True)
|