warp-lang 1.5.0__py3-none-macosx_10_13_universal2.whl → 1.6.0__py3-none-macosx_10_13_universal2.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 +5 -0
- warp/autograd.py +414 -191
- warp/bin/libwarp-clang.dylib +0 -0
- warp/bin/libwarp.dylib +0 -0
- warp/build.py +40 -12
- warp/build_dll.py +13 -6
- warp/builtins.py +1124 -497
- warp/codegen.py +261 -136
- warp/config.py +1 -1
- warp/context.py +357 -119
- warp/examples/assets/square_cloth.usd +0 -0
- warp/examples/benchmarks/benchmark_gemm.py +27 -18
- warp/examples/benchmarks/benchmark_interop_paddle.py +3 -3
- warp/examples/benchmarks/benchmark_interop_torch.py +3 -3
- warp/examples/core/example_torch.py +18 -34
- warp/examples/fem/example_apic_fluid.py +1 -0
- warp/examples/fem/example_mixed_elasticity.py +1 -1
- warp/examples/optim/example_bounce.py +1 -1
- warp/examples/optim/example_cloth_throw.py +1 -1
- warp/examples/optim/example_diffray.py +4 -15
- warp/examples/optim/example_drone.py +1 -1
- warp/examples/optim/example_softbody_properties.py +392 -0
- warp/examples/optim/example_trajectory.py +1 -3
- warp/examples/optim/example_walker.py +5 -0
- warp/examples/sim/example_cartpole.py +0 -2
- warp/examples/sim/example_cloth.py +3 -1
- warp/examples/sim/example_cloth_self_contact.py +260 -0
- warp/examples/sim/example_granular_collision_sdf.py +4 -5
- warp/examples/sim/example_jacobian_ik.py +0 -2
- warp/examples/sim/example_quadruped.py +5 -2
- warp/examples/tile/example_tile_cholesky.py +79 -0
- warp/examples/tile/example_tile_convolution.py +2 -2
- warp/examples/tile/example_tile_fft.py +2 -2
- warp/examples/tile/example_tile_filtering.py +3 -3
- warp/examples/tile/example_tile_matmul.py +4 -4
- warp/examples/tile/example_tile_mlp.py +12 -12
- warp/examples/tile/example_tile_nbody.py +180 -0
- warp/examples/tile/example_tile_walker.py +319 -0
- warp/fem/geometry/geometry.py +0 -2
- warp/math.py +147 -0
- warp/native/array.h +12 -0
- warp/native/builtin.h +0 -1
- warp/native/bvh.cpp +149 -70
- warp/native/bvh.cu +287 -68
- warp/native/bvh.h +195 -85
- warp/native/clang/clang.cpp +5 -1
- warp/native/coloring.cpp +5 -1
- warp/native/cuda_util.cpp +91 -53
- warp/native/cuda_util.h +5 -0
- warp/native/exports.h +40 -40
- warp/native/intersect.h +17 -0
- warp/native/mat.h +41 -0
- warp/native/mathdx.cpp +19 -0
- warp/native/mesh.cpp +25 -8
- warp/native/mesh.cu +153 -101
- warp/native/mesh.h +482 -403
- warp/native/quat.h +40 -0
- warp/native/solid_angle.h +7 -0
- warp/native/sort.cpp +85 -0
- warp/native/sort.cu +34 -0
- warp/native/sort.h +3 -1
- warp/native/spatial.h +11 -0
- warp/native/tile.h +1187 -669
- warp/native/tile_reduce.h +8 -6
- warp/native/vec.h +41 -0
- warp/native/warp.cpp +8 -1
- warp/native/warp.cu +263 -40
- warp/native/warp.h +19 -5
- warp/optim/linear.py +22 -4
- warp/render/render_opengl.py +130 -64
- warp/sim/__init__.py +6 -1
- warp/sim/collide.py +270 -26
- warp/sim/import_urdf.py +8 -8
- warp/sim/integrator_euler.py +25 -7
- warp/sim/integrator_featherstone.py +154 -35
- warp/sim/integrator_vbd.py +842 -40
- warp/sim/model.py +134 -72
- warp/sparse.py +1 -1
- warp/stubs.py +265 -132
- warp/tape.py +28 -30
- warp/tests/aux_test_module_unload.py +15 -0
- warp/tests/{test_sim_grad.py → flaky_test_sim_grad.py} +104 -63
- warp/tests/test_array.py +74 -0
- warp/tests/test_assert.py +242 -0
- warp/tests/test_codegen.py +14 -61
- warp/tests/test_collision.py +2 -2
- warp/tests/test_coloring.py +12 -2
- warp/tests/test_examples.py +12 -1
- warp/tests/test_func.py +21 -4
- warp/tests/test_grad_debug.py +87 -2
- warp/tests/test_hash_grid.py +1 -1
- warp/tests/test_ipc.py +116 -0
- warp/tests/test_lerp.py +13 -87
- warp/tests/test_mat.py +138 -167
- warp/tests/test_math.py +47 -1
- warp/tests/test_matmul.py +17 -16
- warp/tests/test_matmul_lite.py +10 -15
- warp/tests/test_mesh.py +84 -60
- warp/tests/test_mesh_query_aabb.py +165 -0
- warp/tests/test_mesh_query_point.py +328 -286
- warp/tests/test_mesh_query_ray.py +134 -121
- warp/tests/test_mlp.py +2 -2
- warp/tests/test_operators.py +43 -0
- warp/tests/test_overwrite.py +47 -2
- warp/tests/test_quat.py +77 -0
- warp/tests/test_reload.py +29 -0
- warp/tests/test_sim_grad_bounce_linear.py +204 -0
- warp/tests/test_smoothstep.py +17 -83
- warp/tests/test_static.py +19 -3
- warp/tests/test_tape.py +25 -0
- warp/tests/test_tile.py +178 -191
- warp/tests/test_tile_load.py +356 -0
- warp/tests/test_tile_mathdx.py +61 -8
- warp/tests/test_tile_mlp.py +17 -17
- warp/tests/test_tile_reduce.py +24 -18
- warp/tests/test_tile_shared_memory.py +66 -17
- warp/tests/test_tile_view.py +165 -0
- warp/tests/test_torch.py +35 -0
- warp/tests/test_utils.py +36 -24
- warp/tests/test_vec.py +110 -0
- warp/tests/unittest_suites.py +29 -4
- warp/tests/unittest_utils.py +30 -13
- warp/thirdparty/unittest_parallel.py +2 -2
- warp/types.py +411 -101
- warp/utils.py +10 -7
- {warp_lang-1.5.0.dist-info → warp_lang-1.6.0.dist-info}/METADATA +92 -69
- {warp_lang-1.5.0.dist-info → warp_lang-1.6.0.dist-info}/RECORD +130 -119
- {warp_lang-1.5.0.dist-info → warp_lang-1.6.0.dist-info}/WHEEL +1 -1
- warp/examples/benchmarks/benchmark_tile.py +0 -179
- warp/native/tile_gemm.h +0 -341
- {warp_lang-1.5.0.dist-info → warp_lang-1.6.0.dist-info}/LICENSE.md +0 -0
- {warp_lang-1.5.0.dist-info → warp_lang-1.6.0.dist-info}/top_level.txt +0 -0
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
# Note: requires a CUDA-capable device
|
|
16
16
|
###########################################################################
|
|
17
17
|
|
|
18
|
-
import math
|
|
19
18
|
import os
|
|
20
19
|
|
|
21
20
|
import numpy as np
|
|
@@ -66,8 +65,8 @@ class Example:
|
|
|
66
65
|
sdf=rock_sdf,
|
|
67
66
|
body=-1,
|
|
68
67
|
pos=wp.vec3(0.0, 0.0, 0.0),
|
|
69
|
-
rot=wp.
|
|
70
|
-
scale=wp.vec3(0
|
|
68
|
+
rot=wp.quat(0.0, 0.0, 0.0, 1.0),
|
|
69
|
+
scale=wp.vec3(1.0, 1.0, 1.0),
|
|
71
70
|
)
|
|
72
71
|
|
|
73
72
|
mins = np.array([-3.0, -3.0, -3.0])
|
|
@@ -149,13 +148,13 @@ class Example:
|
|
|
149
148
|
with wp.ScopedTimer("render"):
|
|
150
149
|
self.renderer.begin_frame(self.sim_time)
|
|
151
150
|
|
|
152
|
-
# Note the extra wp.quat_from_axis_angle(wp.vec3(1.0, 0.0, 0.0), math.pi) is because .usd is oriented differently from .nvdb
|
|
153
151
|
self.renderer.render_ref(
|
|
154
152
|
name="collision",
|
|
155
153
|
path=os.path.join(warp.examples.get_asset_directory(), "rocks.usd"),
|
|
156
154
|
pos=wp.vec3(0.0, 0.0, 0.0),
|
|
157
155
|
rot=wp.quat(0.0, 0.0, 0.0, 1.0),
|
|
158
|
-
scale=wp.vec3(0
|
|
156
|
+
scale=wp.vec3(1.0, 1.0, 1.0),
|
|
157
|
+
color=(0.35, 0.55, 0.9),
|
|
159
158
|
)
|
|
160
159
|
|
|
161
160
|
self.renderer.render_sphere(
|
|
@@ -93,7 +93,7 @@ class Example:
|
|
|
93
93
|
fps = 100
|
|
94
94
|
self.frame_dt = 1.0 / fps
|
|
95
95
|
|
|
96
|
-
self.sim_substeps =
|
|
96
|
+
self.sim_substeps = 10
|
|
97
97
|
self.sim_dt = self.frame_dt / self.sim_substeps
|
|
98
98
|
|
|
99
99
|
self.num_envs = num_envs
|
|
@@ -116,10 +116,13 @@ class Example:
|
|
|
116
116
|
self.model.joint_attach_ke = 16000.0
|
|
117
117
|
self.model.joint_attach_kd = 200.0
|
|
118
118
|
self.use_tile_gemm = False
|
|
119
|
+
self.fuse_cholesky = False
|
|
119
120
|
|
|
120
121
|
# self.integrator = wp.sim.XPBDIntegrator()
|
|
121
122
|
# self.integrator = wp.sim.SemiImplicitIntegrator()
|
|
122
|
-
self.integrator = wp.sim.FeatherstoneIntegrator(
|
|
123
|
+
self.integrator = wp.sim.FeatherstoneIntegrator(
|
|
124
|
+
self.model, use_tile_gemm=self.use_tile_gemm, fuse_cholesky=self.fuse_cholesky
|
|
125
|
+
)
|
|
123
126
|
|
|
124
127
|
if stage_path:
|
|
125
128
|
self.renderer = wp.sim.render.SimRenderer(self.model, stage_path)
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# Copyright (c) 2025 NVIDIA CORPORATION. All rights reserved.
|
|
2
|
+
# NVIDIA CORPORATION and its licensors retain all intellectual property
|
|
3
|
+
# and proprietary rights in and to this software, related documentation
|
|
4
|
+
# and any modifications thereto. Any use, reproduction, disclosure or
|
|
5
|
+
# distribution of this software and related documentation without an express
|
|
6
|
+
# license agreement from NVIDIA CORPORATION is strictly prohibited.
|
|
7
|
+
|
|
8
|
+
###########################################################################
|
|
9
|
+
# Example Tile Cholesky
|
|
10
|
+
#
|
|
11
|
+
# Shows how to write a simple kernel computing a Cholesky factorize and
|
|
12
|
+
# triangular solve using Warp Cholesky Tile APIs.
|
|
13
|
+
#
|
|
14
|
+
###########################################################################
|
|
15
|
+
|
|
16
|
+
import numpy as np
|
|
17
|
+
|
|
18
|
+
import warp as wp
|
|
19
|
+
|
|
20
|
+
wp.init()
|
|
21
|
+
wp.set_module_options({"enable_backward": False})
|
|
22
|
+
|
|
23
|
+
BLOCK_DIM = 128
|
|
24
|
+
TILE = 32
|
|
25
|
+
|
|
26
|
+
# Both should work
|
|
27
|
+
np_type, wp_type = np.float64, wp.float64
|
|
28
|
+
# np_type, wp_type = np.float32, wp.float32
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@wp.kernel
|
|
32
|
+
def cholesky(
|
|
33
|
+
A: wp.array2d(dtype=wp_type),
|
|
34
|
+
L: wp.array2d(dtype=wp_type),
|
|
35
|
+
X: wp.array1d(dtype=wp_type),
|
|
36
|
+
Y: wp.array1d(dtype=wp_type),
|
|
37
|
+
):
|
|
38
|
+
i, j, _ = wp.tid()
|
|
39
|
+
|
|
40
|
+
a = wp.tile_load(A, shape=(TILE, TILE))
|
|
41
|
+
l = wp.tile_cholesky(a)
|
|
42
|
+
wp.tile_store(L, l)
|
|
43
|
+
|
|
44
|
+
x = wp.tile_load(X, shape=TILE)
|
|
45
|
+
y = wp.tile_cholesky_solve(l, x)
|
|
46
|
+
wp.tile_store(Y, y)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
if __name__ == "__main__":
|
|
50
|
+
wp.set_device("cuda:0")
|
|
51
|
+
|
|
52
|
+
A_h = np.ones((TILE, TILE), dtype=np_type) + 5 * np.diag(np.ones(TILE), 0)
|
|
53
|
+
L_h = np.zeros_like(A_h)
|
|
54
|
+
|
|
55
|
+
A_wp = wp.array2d(A_h, dtype=wp_type)
|
|
56
|
+
L_wp = wp.array2d(L_h, dtype=wp_type)
|
|
57
|
+
|
|
58
|
+
X_h = np.arange(TILE, dtype=np_type)
|
|
59
|
+
Y_h = np.zeros_like(X_h)
|
|
60
|
+
|
|
61
|
+
X_wp = wp.array1d(X_h, dtype=wp_type)
|
|
62
|
+
Y_wp = wp.array1d(Y_h, dtype=wp_type)
|
|
63
|
+
|
|
64
|
+
wp.launch_tiled(cholesky, dim=[1, 1], inputs=[A_wp, L_wp, X_wp, Y_wp], block_dim=BLOCK_DIM)
|
|
65
|
+
|
|
66
|
+
L_np = np.linalg.cholesky(A_h)
|
|
67
|
+
Y_np = np.linalg.solve(A_h, X_h)
|
|
68
|
+
|
|
69
|
+
print("A:\n", A_h)
|
|
70
|
+
print("L (Warp):\n", L_wp)
|
|
71
|
+
print("L (Numpy):\n", L_np)
|
|
72
|
+
|
|
73
|
+
print("x:\n", X_h)
|
|
74
|
+
print("A\\n (Warp):\n", Y_wp.numpy())
|
|
75
|
+
print("A\\x (Numpy):\n", Y_np)
|
|
76
|
+
|
|
77
|
+
assert np.allclose(Y_wp.numpy(), Y_np) and np.allclose(L_wp.numpy(), L_np)
|
|
78
|
+
|
|
79
|
+
print("Example Tile Cholesky passed")
|
|
@@ -34,11 +34,11 @@ def filter(x: wp.vec2d):
|
|
|
34
34
|
@wp.kernel
|
|
35
35
|
def conv_tiled(x: wp.array2d(dtype=wp.vec2d), y: wp.array2d(dtype=wp.vec2d)):
|
|
36
36
|
i, j, _ = wp.tid()
|
|
37
|
-
a = wp.tile_load(x,
|
|
37
|
+
a = wp.tile_load(x, shape=(TILE_M, TILE_N))
|
|
38
38
|
wp.tile_fft(a)
|
|
39
39
|
b = wp.tile_map(filter, a)
|
|
40
40
|
wp.tile_ifft(b)
|
|
41
|
-
wp.tile_store(y,
|
|
41
|
+
wp.tile_store(y, b)
|
|
42
42
|
|
|
43
43
|
|
|
44
44
|
if __name__ == "__main__":
|
|
@@ -26,10 +26,10 @@ TILE_N = 32
|
|
|
26
26
|
@wp.kernel
|
|
27
27
|
def fft_tiled(x: wp.array2d(dtype=wp.vec2d), y: wp.array2d(dtype=wp.vec2d)):
|
|
28
28
|
i, j, _ = wp.tid()
|
|
29
|
-
a = wp.tile_load(x,
|
|
29
|
+
a = wp.tile_load(x, shape=(TILE_M, TILE_N))
|
|
30
30
|
wp.tile_fft(a)
|
|
31
31
|
wp.tile_ifft(a)
|
|
32
|
-
wp.tile_store(y,
|
|
32
|
+
wp.tile_store(y, a)
|
|
33
33
|
|
|
34
34
|
|
|
35
35
|
if __name__ == "__main__":
|
|
@@ -38,12 +38,12 @@ def cplx_prod(x: wp.vec2d, y: wp.vec2d):
|
|
|
38
38
|
@wp.kernel
|
|
39
39
|
def conv_tiled(x: wp.array2d(dtype=wp.vec2d), y: wp.array2d(dtype=wp.vec2d), z: wp.array2d(dtype=wp.vec2d)):
|
|
40
40
|
i, j, _ = wp.tid()
|
|
41
|
-
a = wp.tile_load(x,
|
|
42
|
-
b = wp.tile_load(y,
|
|
41
|
+
a = wp.tile_load(x, shape=(TILE_M, TILE_N))
|
|
42
|
+
b = wp.tile_load(y, shape=(TILE_M, TILE_N))
|
|
43
43
|
wp.tile_fft(a)
|
|
44
44
|
c = wp.tile_map(cplx_prod, a, b)
|
|
45
45
|
wp.tile_ifft(c)
|
|
46
|
-
wp.tile_store(z,
|
|
46
|
+
wp.tile_store(z, c)
|
|
47
47
|
|
|
48
48
|
|
|
49
49
|
if __name__ == "__main__":
|
|
@@ -30,7 +30,7 @@ def tile_gemm(A: wp.array2d(dtype=wp.float32), B: wp.array2d(dtype=wp.float16),
|
|
|
30
30
|
# output tile index
|
|
31
31
|
i, j = wp.tid()
|
|
32
32
|
|
|
33
|
-
sum = wp.tile_zeros(
|
|
33
|
+
sum = wp.tile_zeros(shape=(TILE_M, TILE_N), dtype=wp.float64)
|
|
34
34
|
|
|
35
35
|
_M = A.shape[0]
|
|
36
36
|
_N = B.shape[1]
|
|
@@ -39,13 +39,13 @@ def tile_gemm(A: wp.array2d(dtype=wp.float32), B: wp.array2d(dtype=wp.float16),
|
|
|
39
39
|
count = int(K / TILE_K)
|
|
40
40
|
|
|
41
41
|
for k in range(0, count):
|
|
42
|
-
a = wp.tile_load(A,
|
|
43
|
-
b = wp.tile_load(B,
|
|
42
|
+
a = wp.tile_load(A, shape=(TILE_M, TILE_K), offset=(i * TILE_M, k * TILE_K))
|
|
43
|
+
b = wp.tile_load(B, shape=(TILE_K, TILE_N), offset=(k * TILE_K, j * TILE_N))
|
|
44
44
|
|
|
45
45
|
# sum += a*b
|
|
46
46
|
wp.tile_matmul(a, b, sum)
|
|
47
47
|
|
|
48
|
-
wp.tile_store(C, i, j
|
|
48
|
+
wp.tile_store(C, sum, offset=(i * TILE_M, j * TILE_N))
|
|
49
49
|
|
|
50
50
|
|
|
51
51
|
if __name__ == "__main__":
|
|
@@ -117,23 +117,23 @@ def compute(
|
|
|
117
117
|
f = wp.tile(local)
|
|
118
118
|
|
|
119
119
|
# input layer
|
|
120
|
-
w0 = wp.tile_load(weights_0,
|
|
121
|
-
b0 = wp.tile_load(bias_0,
|
|
122
|
-
z = wp.tile_map(relu, wp.tile_matmul(w0, f) + wp.tile_broadcast(b0,
|
|
120
|
+
w0 = wp.tile_load(weights_0, shape=(DIM_HID, DIM_IN))
|
|
121
|
+
b0 = wp.tile_load(bias_0, shape=(DIM_HID, 1))
|
|
122
|
+
z = wp.tile_map(relu, wp.tile_matmul(w0, f) + wp.tile_broadcast(b0, shape=(DIM_HID, NUM_THREADS)))
|
|
123
123
|
|
|
124
124
|
# hidden layer
|
|
125
|
-
w1 = wp.tile_load(weights_1,
|
|
126
|
-
b1 = wp.tile_load(bias_1,
|
|
127
|
-
z = wp.tile_map(relu, wp.tile_matmul(w1, z) + wp.tile_broadcast(b1,
|
|
125
|
+
w1 = wp.tile_load(weights_1, shape=(DIM_HID, DIM_HID))
|
|
126
|
+
b1 = wp.tile_load(bias_1, shape=(DIM_HID, 1))
|
|
127
|
+
z = wp.tile_map(relu, wp.tile_matmul(w1, z) + wp.tile_broadcast(b1, shape=(DIM_HID, NUM_THREADS)))
|
|
128
128
|
|
|
129
|
-
w2 = wp.tile_load(weights_2,
|
|
130
|
-
b2 = wp.tile_load(bias_2,
|
|
131
|
-
z = wp.tile_map(relu, wp.tile_matmul(w2, z) + wp.tile_broadcast(b2,
|
|
129
|
+
w2 = wp.tile_load(weights_2, shape=(DIM_HID, DIM_HID))
|
|
130
|
+
b2 = wp.tile_load(bias_2, shape=(DIM_HID, 1))
|
|
131
|
+
z = wp.tile_map(relu, wp.tile_matmul(w2, z) + wp.tile_broadcast(b2, shape=(DIM_HID, NUM_THREADS)))
|
|
132
132
|
|
|
133
133
|
# output layer
|
|
134
|
-
w3 = wp.tile_load(weights_3,
|
|
135
|
-
b3 = wp.tile_load(bias_3,
|
|
136
|
-
o = wp.tile_map(relu, wp.tile_matmul(w3, z) + wp.tile_broadcast(b3,
|
|
134
|
+
w3 = wp.tile_load(weights_3, shape=(DIM_OUT, DIM_HID))
|
|
135
|
+
b3 = wp.tile_load(bias_3, shape=(DIM_OUT, 1))
|
|
136
|
+
o = wp.tile_map(relu, wp.tile_matmul(w3, z) + wp.tile_broadcast(b3, shape=(DIM_OUT, NUM_THREADS)))
|
|
137
137
|
|
|
138
138
|
# untile back to SIMT
|
|
139
139
|
output = wp.untile(o)
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# Copyright (c) 2025 NVIDIA CORPORATION. All rights reserved.
|
|
2
|
+
# NVIDIA CORPORATION and its licensors retain all intellectual property
|
|
3
|
+
# and proprietary rights in and to this software, related documentation
|
|
4
|
+
# and any modifications thereto. Any use, reproduction, disclosure or
|
|
5
|
+
# distribution of this software and related documentation without an express
|
|
6
|
+
# license agreement from NVIDIA CORPORATION is strictly prohibited.
|
|
7
|
+
|
|
8
|
+
###########################################################################
|
|
9
|
+
# Example N-Body
|
|
10
|
+
#
|
|
11
|
+
# Shows how to simulate an N-Body gravitational problem using an all-pairs
|
|
12
|
+
# approach with Warp tile primitives.
|
|
13
|
+
#
|
|
14
|
+
# References:
|
|
15
|
+
# L. Nyland, M. Harris, and J. Prins. "Fast N-Body Simulation with
|
|
16
|
+
# CUDA" in GPU Gems 3. H. Nguyen, Addison-Wesley Professional, 2007.
|
|
17
|
+
# https://developer.nvidia.com/gpugems/gpugems3/part-v-physics-simulation/chapter-31-fast-n-body-simulation-cuda
|
|
18
|
+
#
|
|
19
|
+
###########################################################################
|
|
20
|
+
|
|
21
|
+
import argparse
|
|
22
|
+
|
|
23
|
+
import numpy as np
|
|
24
|
+
|
|
25
|
+
import warp as wp
|
|
26
|
+
|
|
27
|
+
wp.init()
|
|
28
|
+
|
|
29
|
+
DT = wp.constant(0.01)
|
|
30
|
+
SOFTENING_SQ = wp.constant(0.1**2) # Softening factor for numerical stability
|
|
31
|
+
TILE_SIZE = wp.constant(64)
|
|
32
|
+
PARTICLE_MASS = wp.constant(1.0)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@wp.func
|
|
36
|
+
def body_body_interaction(p0: wp.vec3, pi: wp.vec3):
|
|
37
|
+
"""Return the acceleration of the particle at position `p0` due to the
|
|
38
|
+
particle at position `pi`."""
|
|
39
|
+
r = pi - p0
|
|
40
|
+
|
|
41
|
+
dist_sq = wp.length_sq(r) + SOFTENING_SQ
|
|
42
|
+
|
|
43
|
+
inv_dist = 1.0 / wp.sqrt(dist_sq)
|
|
44
|
+
inv_dist_cubed = inv_dist * inv_dist * inv_dist
|
|
45
|
+
|
|
46
|
+
acc = PARTICLE_MASS * inv_dist_cubed * r
|
|
47
|
+
|
|
48
|
+
return acc
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@wp.kernel
|
|
52
|
+
def integrate_bodies_tiled(
|
|
53
|
+
old_position: wp.array(dtype=wp.vec3),
|
|
54
|
+
velocity: wp.array(dtype=wp.vec3),
|
|
55
|
+
new_position: wp.array(dtype=wp.vec3),
|
|
56
|
+
num_bodies: int,
|
|
57
|
+
):
|
|
58
|
+
i = wp.tid()
|
|
59
|
+
|
|
60
|
+
p0 = old_position[i]
|
|
61
|
+
|
|
62
|
+
accel = wp.vec3(0.0, 0.0, 0.0)
|
|
63
|
+
|
|
64
|
+
for k in range(num_bodies / TILE_SIZE):
|
|
65
|
+
k_tile = wp.tile_load(old_position, shape=TILE_SIZE, offset=k * TILE_SIZE)
|
|
66
|
+
for idx in range(TILE_SIZE):
|
|
67
|
+
pi = k_tile[idx]
|
|
68
|
+
accel += body_body_interaction(p0, pi)
|
|
69
|
+
|
|
70
|
+
# Advance the velocity one timestep (in-place)
|
|
71
|
+
velocity[i] = velocity[i] + accel * DT
|
|
72
|
+
|
|
73
|
+
# Advance the positions (using a second array)
|
|
74
|
+
new_position[i] = old_position[i] + DT * velocity[i]
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class Example:
|
|
78
|
+
def __init__(self, headless=False, num_bodies=1024):
|
|
79
|
+
self.num_bodies = num_bodies
|
|
80
|
+
|
|
81
|
+
rng = np.random.default_rng(42)
|
|
82
|
+
|
|
83
|
+
# Sample the surface of a sphere
|
|
84
|
+
r = 10.0 * (num_bodies / 1024) ** (1 / 2) # Scale factor to maintain a constant density
|
|
85
|
+
phi = np.arccos(1.0 - 2.0 * rng.uniform(size=self.num_bodies))
|
|
86
|
+
theta = rng.uniform(low=0.0, high=2.0 * np.pi, size=self.num_bodies)
|
|
87
|
+
x = r * np.cos(theta) * np.sin(phi)
|
|
88
|
+
y = r * np.sin(theta) * np.sin(phi)
|
|
89
|
+
z = r * np.cos(phi)
|
|
90
|
+
|
|
91
|
+
self.scale = r
|
|
92
|
+
init_pos_np = np.stack((x, y, z), axis=1)
|
|
93
|
+
|
|
94
|
+
self.pos_array_0 = wp.array(init_pos_np, dtype=wp.vec3)
|
|
95
|
+
self.pos_array_1 = wp.empty_like(self.pos_array_0)
|
|
96
|
+
self.vel_array = wp.zeros(self.num_bodies, dtype=wp.vec3)
|
|
97
|
+
|
|
98
|
+
if headless:
|
|
99
|
+
self.scatter_plot = None
|
|
100
|
+
else:
|
|
101
|
+
self.scatter_plot = self.create_plot()
|
|
102
|
+
|
|
103
|
+
def create_plot(self):
|
|
104
|
+
import matplotlib.pyplot as plt
|
|
105
|
+
|
|
106
|
+
# Create a figure and a 3D axis for the plot
|
|
107
|
+
self.fig = plt.figure()
|
|
108
|
+
ax = self.fig.add_subplot(111, projection="3d")
|
|
109
|
+
|
|
110
|
+
# Scatter plot of initial positions
|
|
111
|
+
init_pos_np = self.pos_array_0.numpy()
|
|
112
|
+
scatter_plot = ax.scatter(init_pos_np[:, 0], init_pos_np[:, 1], init_pos_np[:, 2], c="#76b900", alpha=0.5)
|
|
113
|
+
|
|
114
|
+
# Set axis limits
|
|
115
|
+
ax.set_xlim(-self.scale, self.scale)
|
|
116
|
+
ax.set_ylim(-self.scale, self.scale)
|
|
117
|
+
ax.set_zlim(-self.scale, self.scale)
|
|
118
|
+
|
|
119
|
+
return scatter_plot
|
|
120
|
+
|
|
121
|
+
def step(self):
|
|
122
|
+
wp.launch(
|
|
123
|
+
integrate_bodies_tiled,
|
|
124
|
+
dim=self.num_bodies,
|
|
125
|
+
inputs=[self.pos_array_0, self.vel_array, self.pos_array_1, self.num_bodies],
|
|
126
|
+
block_dim=TILE_SIZE,
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
# Swap arrays
|
|
130
|
+
(self.pos_array_0, self.pos_array_1) = (self.pos_array_1, self.pos_array_0)
|
|
131
|
+
|
|
132
|
+
def render(self):
|
|
133
|
+
positions_cpu = self.pos_array_0.numpy()
|
|
134
|
+
|
|
135
|
+
# Update scatter plot positions
|
|
136
|
+
self.scatter_plot._offsets3d = (
|
|
137
|
+
positions_cpu[:, 0],
|
|
138
|
+
positions_cpu[:, 1],
|
|
139
|
+
positions_cpu[:, 2],
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
# Function to update the scatter plot
|
|
143
|
+
def step_and_render(self, frame):
|
|
144
|
+
self.step()
|
|
145
|
+
self.render()
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
if __name__ == "__main__":
|
|
149
|
+
parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter)
|
|
150
|
+
parser.add_argument("--device", type=str, default=None, help="Override the default Warp device.")
|
|
151
|
+
parser.add_argument("--num_frames", type=int, default=1000, help="Total number of frames.")
|
|
152
|
+
parser.add_argument("-N", help="Number of bodies. Should be a multiple of 64.", type=int, default=1024)
|
|
153
|
+
parser.add_argument(
|
|
154
|
+
"--headless",
|
|
155
|
+
action="store_true",
|
|
156
|
+
help="Run in headless mode, suppressing the opening of any graphical windows.",
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
args = parser.parse_known_args()[0]
|
|
160
|
+
|
|
161
|
+
if args.device == "cpu":
|
|
162
|
+
print("This example only runs on CUDA devices.")
|
|
163
|
+
exit()
|
|
164
|
+
|
|
165
|
+
with wp.ScopedDevice(args.device):
|
|
166
|
+
example = Example(headless=args.headless, num_bodies=args.N)
|
|
167
|
+
|
|
168
|
+
if not args.headless:
|
|
169
|
+
import matplotlib.pyplot as plt
|
|
170
|
+
from matplotlib.animation import FuncAnimation
|
|
171
|
+
|
|
172
|
+
# Create the animation
|
|
173
|
+
ani = FuncAnimation(example.fig, example.step_and_render, frames=args.num_frames, interval=50, repeat=False)
|
|
174
|
+
|
|
175
|
+
# Display the animation
|
|
176
|
+
plt.show()
|
|
177
|
+
|
|
178
|
+
else:
|
|
179
|
+
for _ in range(args.num_frames):
|
|
180
|
+
example.step()
|