warp-lang 1.0.0b5__py3-none-manylinux2014_aarch64.whl → 1.0.0b6__py3-none-manylinux2014_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/config.py CHANGED
@@ -5,7 +5,7 @@
5
5
  # distribution of this software and related documentation without an express
6
6
  # license agreement from NVIDIA CORPORATION is strictly prohibited.
7
7
 
8
- version = "1.0.0-beta.5"
8
+ version = "1.0.0-beta.6"
9
9
 
10
10
  cuda_path = (
11
11
  None # path to local CUDA toolchain, if None at init time warp will attempt to find the SDK using CUDA_PATH env var
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: warp-lang
3
- Version: 1.0.0b5
3
+ Version: 1.0.0b6
4
4
  Summary: A Python framework for high-performance simulation and graphics programming
5
5
  Author-email: NVIDIA <mmacklin@nvidia.com>
6
6
  License: NVSCL
@@ -1,13 +1,5 @@
1
1
  docs/conf.py,sha256=FHItR6eNAj6TeuWRo--2UjFrfM_dFTZmeZkMJ12e3L8,4763
2
2
  examples/benchmark_api.py,sha256=3W6ETJyumNs3jfzWecDdCcHfiGmFatcG66-EkHwTeiI,3894
3
- examples/benchmark_cloth.py,sha256=fGP0VkJJU5F5nLhP8sGHyva3P5Wra_tDNmrwnCKCkQg,9223
4
- examples/benchmark_cloth_cupy.py,sha256=74vm-LUW-4sg8mzhAxuiHJgVwO_IxAmddo6d5YJ37m8,2574
5
- examples/benchmark_cloth_jax.py,sha256=v5u1Bq-GHIJBymOvw-jdNBsoJ6lTkuKuCUsGYlRfndE,2794
6
- examples/benchmark_cloth_numba.py,sha256=YHLgFjHXx6PRC47R2lSOmwGB090QhKbUGZLWqdP-PsA,4290
7
- examples/benchmark_cloth_numpy.py,sha256=zFPvrTz_5_f9Pq5-KwMYiB8_d1xK-XdbyBVCHZ13Zd0,2106
8
- examples/benchmark_cloth_pytorch.py,sha256=6CExU-Da0aqCFudwpwvXfelS4Kb2H1ujzFLzvDJ5up0,2803
9
- examples/benchmark_cloth_taichi.py,sha256=PIV3lADe6_bKE1H3WhJBeXRlpOdq-wkH_amjqGlS1Z0,3674
10
- examples/benchmark_cloth_warp.py,sha256=gZQVsJd0qLtqiCCPLUmW44t1YGzZMT15BhyOavQMW48,4187
11
3
  examples/benchmark_launches.py,sha256=dlsGCZDeqp9K3p5DDjLK8_d6qv54jgs1aI9_AKDTrVg,6190
12
4
  examples/example_dem.py,sha256=dTNH2sl3XBTK6BQMH9W-vvOP7_Vhv5bePqBTyjJ2coI,7941
13
5
  examples/example_diffray.py,sha256=eqWg2OPTARDIsCwfy1YlIEVTE4dklOae3o54HaavFx0,17681
@@ -72,7 +64,7 @@ warp/build.py,sha256=P5i_8fqiwd8CImhfDbDeZ3I0CnWU9gCtQXwNnloAh9U,4294
72
64
  warp/build_dll.py,sha256=ifOzGKrVYStIe8VLQLQS8tjKzTMmgy8gfm_9HFaRD0M,16844
73
65
  warp/builtins.py,sha256=Eb3qSVbAx1LwA67kM7w_gRhpCNTR3PXZRJYumDcIBz4,116613
74
66
  warp/codegen.py,sha256=5ws31bglnS-3DgjtUGyobJr2qw8_mZ8oh29rLmKJWkM,97863
75
- warp/config.py,sha256=Y4BB52qBoOmLkTexXw4F-sk_fWm24Y25ArM8mSsxLus,1751
67
+ warp/config.py,sha256=IZa37rx9TLcTqRkXv3mC6T4a5iQlmKy4Ht3FkZBiJr4,1751
76
68
  warp/constants.py,sha256=7kcIJLSp1byeDxqKPHqOSLml_U6DzWe9qTLFMtIIp_E,1138
77
69
  warp/context.py,sha256=KSQC55ZWZBCc1eUGcxE7o2IxAY3Kzk-zupEP8sKuRO0,167393
78
70
  warp/dlpack.py,sha256=axWuv7Pch-LZeoDrtabhwwq0WRMjNAZZdvjxt_wkjUg,13724
@@ -410,8 +402,8 @@ warp/thirdparty/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
410
402
  warp/thirdparty/appdirs.py,sha256=6msNAwCSJ0eRTVmRVF98Uvd3trshrw5RRsVUM_hPPLE,24852
411
403
  warp/thirdparty/dlpack.py,sha256=Upx_8E-DR7TQTHUN0bNbfrilzFubRjxWvafV10ZXvqQ,4416
412
404
  warp/thirdparty/unittest_parallel.py,sha256=9CmhJlIiDVjWv5CfXuxm0K_CwezSE_YiCRvk9Fa24J0,22676
413
- warp_lang-1.0.0b5.dist-info/LICENSE.md,sha256=-oj_azPLVWrkvvTDXjtMSiATqx18KpDmmwXsGmpPSEQ,4110
414
- warp_lang-1.0.0b5.dist-info/METADATA,sha256=GSRLOjdlR_xbhg0loubZafeU-aARVqvlg6_465ECOXY,12412
415
- warp_lang-1.0.0b5.dist-info/WHEEL,sha256=Vh4XtMfOVuhxoeaWoNYYOVdIKGVLrtk_M0IR9wFFsf4,111
416
- warp_lang-1.0.0b5.dist-info/top_level.txt,sha256=mO4N6yg9gzmMV87isVqdT7nNNojfOrWjxuH3mIa1gwc,49
417
- warp_lang-1.0.0b5.dist-info/RECORD,,
405
+ warp_lang-1.0.0b6.dist-info/LICENSE.md,sha256=-oj_azPLVWrkvvTDXjtMSiATqx18KpDmmwXsGmpPSEQ,4110
406
+ warp_lang-1.0.0b6.dist-info/METADATA,sha256=RzZ024mEMol3oZ0v0-GunXydWuTPJV5e-FUqJyiToaU,12412
407
+ warp_lang-1.0.0b6.dist-info/WHEEL,sha256=Vh4XtMfOVuhxoeaWoNYYOVdIKGVLrtk_M0IR9wFFsf4,111
408
+ warp_lang-1.0.0b6.dist-info/top_level.txt,sha256=pGqQ4zb6p2PGWj4LRHmD9iUQdiR7ZJCpvHTYlsIp7BI,44
409
+ warp_lang-1.0.0b6.dist-info/RECORD,,
@@ -1,4 +1,3 @@
1
- deps
2
1
  dist
3
2
  docs
4
3
  examples
@@ -1,279 +0,0 @@
1
- # Copyright (c) 2022 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
- # include parent path
9
- import os
10
- import sys, getopt
11
- import numpy as np
12
- import math
13
- import ctypes
14
-
15
- sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
16
-
17
- from pxr import Usd, UsdGeom, Gf, Sdf
18
-
19
- import warp as wp
20
-
21
-
22
- class Cloth:
23
- def __init__(
24
- self, lower, dx, dy, radius, stretch_stiffness, bend_stiffness, shear_stiffness, mass, fix_corners=True
25
- ):
26
- self.triangles = []
27
-
28
- self.positions = []
29
- self.velocities = []
30
- self.inv_masses = []
31
-
32
- self.spring_indices = []
33
- self.spring_lengths = []
34
- self.spring_stiffness = []
35
- self.spring_damping = []
36
-
37
- def grid(x, y, stride):
38
- return y * stride + x
39
-
40
- def create_spring(i, j, stiffness, damp=10.0):
41
- length = np.linalg.norm(np.array(self.positions[i]) - np.array(self.positions[j]))
42
-
43
- self.spring_indices.append(i)
44
- self.spring_indices.append(j)
45
- self.spring_lengths.append(length)
46
- self.spring_stiffness.append(stiffness)
47
- self.spring_damping.append(damp)
48
-
49
- for y in range(dy):
50
- for x in range(dx):
51
- p = np.array(lower) + radius * np.array((float(x), float(0.0), float(y)))
52
-
53
- self.positions.append(p)
54
- self.velocities.append(np.zeros(3))
55
-
56
- if x > 0 and y > 0:
57
- self.triangles.append(grid(x - 1, y - 1, dx))
58
- self.triangles.append(grid(x, y - 1, dx))
59
- self.triangles.append(grid(x, y, dx))
60
-
61
- self.triangles.append(grid(x - 1, y - 1, dx))
62
- self.triangles.append(grid(x, y, dx))
63
- self.triangles.append(grid(x - 1, y, dx))
64
-
65
- if fix_corners and y == 0 and (x == 0 or x == dx - 1):
66
- w = 0.0
67
- else:
68
- w = 1.0 / mass
69
-
70
- self.inv_masses.append(w)
71
-
72
- # horizontal springs
73
- for y in range(dy):
74
- for x in range(dx):
75
- index0 = y * dx + x
76
-
77
- if x > 0:
78
- index1 = y * dx + x - 1
79
- create_spring(index0, index1, stretch_stiffness)
80
-
81
- if x > 1 and bend_stiffness > 0.0:
82
- index2 = y * dx + x - 2
83
- create_spring(index0, index2, bend_stiffness)
84
-
85
- if y > 0 and x < dx - 1 and shear_stiffness > 0.0:
86
- indexDiag = (y - 1) * dx + x + 1
87
- create_spring(index0, indexDiag, shear_stiffness)
88
-
89
- if y > 0 and x > 0 and shear_stiffness > 0.0:
90
- indexDiag = (y - 1) * dx + x - 1
91
- create_spring(index0, indexDiag, shear_stiffness)
92
-
93
- # vertical
94
- for x in range(dx):
95
- for y in range(dy):
96
- index0 = y * dx + x
97
-
98
- if y > 0:
99
- index1 = (y - 1) * dx + x
100
- create_spring(index0, index1, stretch_stiffness)
101
-
102
- if y > 1 and bend_stiffness > 0.0:
103
- index2 = (y - 2) * dx + x
104
- create_spring(index0, index2, bend_stiffness)
105
-
106
- # harden to np arrays
107
- self.positions = np.array(self.positions, dtype=np.float32)
108
- self.velocities = np.array(self.velocities, dtype=np.float32)
109
- self.inv_masses = np.array(self.inv_masses, dtype=np.float32)
110
- self.spring_lengths = np.array(self.spring_lengths, dtype=np.float32)
111
- self.spring_indices = np.array(self.spring_indices, dtype=np.int32)
112
- self.spring_stiffness = np.array(self.spring_stiffness, dtype=np.float32)
113
- self.spring_damping = np.array(self.spring_damping, dtype=np.float32)
114
-
115
- self.num_particles = len(self.positions)
116
- self.num_springs = len(self.spring_lengths)
117
- self.num_tris = int(len(self.triangles) / 3)
118
-
119
-
120
- def run_benchmark(mode, dim, timers, render=False):
121
- # params
122
- sim_width = dim
123
- sim_height = dim
124
-
125
- sim_fps = 60.0
126
- sim_substeps = 16
127
- sim_duration = 1.0
128
- sim_frames = int(sim_duration * sim_fps)
129
- sim_dt = 1.0 / sim_fps
130
- sim_time = 0.0
131
-
132
- # wave constants
133
- k_stretch = 1000.0
134
- k_shear = 1000.0
135
- k_bend = 1000.0
136
- k_damp = 0.0
137
-
138
- cloth = Cloth(
139
- lower=(0.0, 0.0, 0.0),
140
- dx=sim_width,
141
- dy=sim_height,
142
- radius=0.1,
143
- stretch_stiffness=k_stretch,
144
- bend_stiffness=k_bend,
145
- shear_stiffness=k_shear,
146
- mass=0.1,
147
- fix_corners=True,
148
- )
149
-
150
- if render:
151
- # set up grid for visualization
152
- stage = Usd.Stage.CreateNew(os.path.join(os.path.dirname(__file__), "outputs/benchmark.usd"))
153
- stage.SetStartTimeCode(0.0)
154
- stage.SetEndTimeCode(sim_duration * sim_fps)
155
- stage.SetTimeCodesPerSecond(sim_fps)
156
-
157
- grid = UsdGeom.Mesh.Define(stage, "/root")
158
- grid.GetPointsAttr().Set(cloth.positions, 0.0)
159
- grid.GetFaceVertexIndicesAttr().Set(cloth.triangles, 0.0)
160
- grid.GetFaceVertexCountsAttr().Set([3] * cloth.num_tris, 0.0)
161
-
162
- with wp.ScopedTimer("Initialization", dict=timers):
163
- if mode == "warp_cpu":
164
- import examples.benchmark_cloth_warp
165
-
166
- integrator = examples.benchmark_cloth_warp.WpIntegrator(cloth, "cpu")
167
-
168
- elif mode == "warp_gpu":
169
- import examples.benchmark_cloth_warp
170
-
171
- integrator = examples.benchmark_cloth_warp.WpIntegrator(cloth, "cuda")
172
-
173
- elif mode == "taichi_cpu":
174
- import examples.benchmark_cloth_taichi
175
-
176
- integrator = examples.benchmark_cloth_taichi.TiIntegrator(cloth, "cpu")
177
-
178
- elif mode == "taichi_gpu":
179
- import examples.benchmark_cloth_taichi
180
-
181
- integrator = examples.benchmark_cloth_taichi.TiIntegrator(cloth, "cuda")
182
-
183
- elif mode == "numpy":
184
- import examples.benchmark_cloth_numpy
185
-
186
- integrator = examples.benchmark_cloth_numpy.NpIntegrator(cloth)
187
-
188
- elif mode == "cupy":
189
- import examples.benchmark_cloth_cupy
190
-
191
- integrator = examples.benchmark_cloth_cupy.CpIntegrator(cloth)
192
-
193
- elif mode == "numba":
194
- import examples.benchmark_cloth_numba
195
-
196
- integrator = examples.benchmark_cloth_numba.NbIntegrator(cloth)
197
-
198
- elif mode == "torch_cpu":
199
- import examples.benchmark_cloth_pytorch
200
-
201
- integrator = examples.benchmark_cloth_pytorch.TrIntegrator(cloth, "cpu")
202
-
203
- elif mode == "torch_gpu":
204
- import examples.benchmark_cloth_pytorch
205
-
206
- integrator = examples.benchmark_cloth_pytorch.TrIntegrator(cloth, "cuda")
207
-
208
- elif mode == "jax_cpu":
209
- os.environ["JAX_PLATFORM_NAME"] = "cpu"
210
-
211
- import examples.benchmark_cloth_jax
212
-
213
- integrator = examples.benchmark_cloth_jax.JxIntegrator(cloth)
214
-
215
- elif mode == "jax_gpu":
216
- os.environ["JAX_PLATFORM_NAME"] = "gpu"
217
-
218
- import examples.benchmark_cloth_jax
219
-
220
- integrator = examples.benchmark_cloth_jax.JxIntegrator(cloth)
221
-
222
- else:
223
- raise RuntimeError("Unknown simulation backend")
224
-
225
- # run one warm-up iteration to accurately measure initialization time (some engines do lazy init)
226
- positions = integrator.simulate(sim_dt, sim_substeps)
227
-
228
- label = "Dim ({}^2)".format(dim)
229
-
230
- # run simulation
231
- for i in range(sim_frames):
232
- # simulate
233
- with wp.ScopedTimer(label, dict=timers):
234
- positions = integrator.simulate(sim_dt, sim_substeps)
235
-
236
- if render:
237
- grid.GetPointsAttr().Set(positions, sim_time * sim_fps)
238
-
239
- sim_time += sim_dt
240
-
241
- if render:
242
- stage.Save()
243
-
244
-
245
- # record profiling information
246
- timers = {}
247
-
248
- if len(sys.argv) > 1:
249
- mode = sys.argv[1]
250
- else:
251
- mode = "warp_gpu"
252
-
253
- run_benchmark(mode, 32, timers, render=False)
254
- run_benchmark(mode, 64, timers, render=False)
255
- run_benchmark(mode, 128, timers, render=False)
256
-
257
- # write results
258
- import csv
259
-
260
- for k, v in timers.items():
261
- print("{:16} min: {:8.2f} max: {:8.2f} avg: {:8.2f}".format(k, np.min(v), np.max(v), np.mean(v)))
262
-
263
- report = open(os.path.join(os.path.dirname(__file__), "outputs/benchmark.csv"), "a")
264
- writer = csv.writer(report, delimiter=",")
265
-
266
- if report.tell() == 0:
267
- writer.writerow(["Name", "Init", "Dim (32^2)", "Dim (64^2)", "Dim (128^2)"])
268
-
269
- writer.writerow(
270
- [
271
- mode,
272
- np.max(timers["Initialization"]),
273
- np.mean(timers["Dim (32^2)"]),
274
- np.mean(timers["Dim (64^2)"]),
275
- np.mean(timers["Dim (128^2)"]),
276
- ]
277
- )
278
-
279
- report.close()
@@ -1,88 +0,0 @@
1
- # Copyright (c) 2022 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
- import cupy as cp
9
- import cupyx as cpx
10
-
11
-
12
- def eval_springs(x, v, indices, rest, ke, kd, f):
13
- i = indices[:, 0]
14
- j = indices[:, 1]
15
-
16
- xi = x[i]
17
- xj = x[j]
18
-
19
- vi = v[i]
20
- vj = v[j]
21
-
22
- xij = xi - xj
23
- vij = vi - vj
24
-
25
- l = cp.linalg.norm(xij, axis=1)
26
- l_inv = 1.0 / l
27
-
28
- # normalized spring direction
29
- dir = (xij.T * l_inv).T
30
-
31
- c = l - rest
32
- dcdt = cp.sum(dir * vij, axis=1)
33
-
34
- # damping based on relative velocity.
35
- fs = dir.T * (ke * c + kd * dcdt)
36
-
37
- cpx.scatter_add(f, i, -fs.T)
38
- cpx.scatter_add(f, j, fs.T)
39
-
40
-
41
- def integrate_particles(x, v, f, w, dt):
42
- g = cp.array((0.0, 0.0 - 9.8, 0.0))
43
- s = w > 0.0
44
-
45
- a_ext = g * s[:, None]
46
-
47
- # simple semi-implicit Euler. v1 = v0 + a dt, x1 = x0 + v1 dt
48
- v += ((f.T * w).T + a_ext) * dt
49
- x += v * dt
50
-
51
- # clear forces
52
- f *= 0.0
53
-
54
-
55
- class CpIntegrator:
56
- def __init__(self, cloth):
57
- self.cloth = cloth
58
-
59
- self.positions = cp.array(self.cloth.positions)
60
- self.velocities = cp.array(self.cloth.velocities)
61
- self.inv_mass = cp.array(self.cloth.inv_masses)
62
-
63
- self.spring_indices = cp.array(self.cloth.spring_indices)
64
- self.spring_lengths = cp.array(self.cloth.spring_lengths)
65
- self.spring_stiffness = cp.array(self.cloth.spring_stiffness)
66
- self.spring_damping = cp.array(self.cloth.spring_damping)
67
-
68
- self.forces = cp.zeros((self.cloth.num_particles, 3), dtype=cp.float32)
69
-
70
- def simulate(self, dt, substeps):
71
- sim_dt = dt / substeps
72
-
73
- for s in range(substeps):
74
- eval_springs(
75
- self.positions,
76
- self.velocities,
77
- self.spring_indices.reshape((self.cloth.num_springs, 2)),
78
- self.spring_lengths,
79
- self.spring_stiffness,
80
- self.spring_damping,
81
- self.forces,
82
- )
83
-
84
- # integrate
85
- integrate_particles(self.positions, self.velocities, self.forces, self.inv_mass, sim_dt)
86
-
87
- # return np.array(self.positions)
88
- return self.positions.get()
@@ -1,100 +0,0 @@
1
- # Copyright (c) 2022 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
- import numpy as np
9
-
10
- import jax.lax
11
- import jax.numpy as jnp
12
-
13
- import os
14
-
15
-
16
- @jax.jit
17
- def eval_springs(x, v, indices, rest, ke, kd):
18
- i = indices[:, 0]
19
- j = indices[:, 1]
20
-
21
- xi = x[i]
22
- xj = x[j]
23
-
24
- vi = v[i]
25
- vj = v[j]
26
-
27
- xij = xi - xj
28
- vij = vi - vj
29
-
30
- l = jnp.linalg.norm(xij, axis=1)
31
- l_inv = 1.0 / l
32
-
33
- # normalized spring direction
34
- dir = (xij.T * l_inv).T
35
-
36
- c = l - rest
37
- dcdt = jnp.sum(dir * vij, axis=1)
38
-
39
- # damping based on relative velocity.
40
- fs = dir.T * (ke * c + kd * dcdt)
41
-
42
- f = jnp.zeros_like(v)
43
-
44
- # f = jax.ops.index_add(f, i, -fs.T, indices_are_sorted=False, unique_indices=False)
45
- # f = jax.ops.index_add(f, j, fs.T, indices_are_sorted=False, unique_indices=False)
46
-
47
- f.at[i].add(-fs.T)
48
- f.at[j].add(fs.T)
49
-
50
- return f
51
-
52
-
53
- @jax.jit
54
- def integrate_particles(x, v, f, w, dt):
55
- g = jnp.array((0.0, 0.0 - 9.8, 0.0))
56
- s = w > 0.0
57
-
58
- a_ext = g * s[:, None]
59
-
60
- # simple semi-implicit Euler. v1 = v0 + a dt, x1 = x0 + v1 dt
61
- v += ((f.T * w).T + a_ext) * dt
62
- x += v * dt
63
-
64
- return (x, v)
65
-
66
-
67
- class JxIntegrator:
68
- def __init__(self, cloth):
69
- self.cloth = cloth
70
-
71
- self.positions = jnp.array(self.cloth.positions)
72
- self.velocities = jnp.array(self.cloth.velocities)
73
- self.inv_mass = jnp.array(self.cloth.inv_masses)
74
-
75
- print(self.positions.device_buffer.device())
76
-
77
- self.spring_indices = jnp.array(self.cloth.spring_indices)
78
- self.spring_lengths = jnp.array(self.cloth.spring_lengths)
79
- self.spring_stiffness = jnp.array(self.cloth.spring_stiffness)
80
- self.spring_damping = jnp.array(self.cloth.spring_damping)
81
-
82
- def simulate(self, dt, substeps):
83
- sim_dt = dt / substeps
84
-
85
- for s in range(substeps):
86
- f = eval_springs(
87
- self.positions,
88
- self.velocities,
89
- self.spring_indices.reshape((self.cloth.num_springs, 2)),
90
- self.spring_lengths,
91
- self.spring_stiffness,
92
- self.spring_damping,
93
- )
94
-
95
- # integrate
96
- (self.positions, self.velocities) = integrate_particles(
97
- self.positions, self.velocities, f, self.inv_mass, sim_dt
98
- )
99
-
100
- return np.array(self.positions)
@@ -1,142 +0,0 @@
1
- from numba import cuda, float32
2
- import numpy as np
3
- import cupy as cp
4
-
5
- import math
6
-
7
- # Notes:
8
- #
9
- # Current implementation requires some familarity of writing custom cuda kernels
10
- # May be improved with cuda ufuncs and/or writing custom numba type extensions.
11
-
12
-
13
- @cuda.jit(device=True)
14
- def norm(x):
15
- s = float32(0.0)
16
- for i in range(3):
17
- s += x[i] * x[i]
18
- return math.sqrt(s)
19
-
20
-
21
- @cuda.jit(device=True)
22
- def dot(x, y):
23
- s = float32(0.0)
24
- for i in range(3):
25
- s += x[i] * y[i]
26
- return s
27
-
28
-
29
- @cuda.jit
30
- def eval_springs_cuda(
31
- num_springs, # (1,)
32
- xs, # position (N, 3)
33
- vs, # velocities (N, 3)
34
- indices, # spring indices (S, 2)
35
- rests, # spring rest length (S,)
36
- kes, # stiffness (S,)
37
- kds, # damping (S,)
38
- fs,
39
- ): # forces (N, 3)
40
- tidx = cuda.grid(1)
41
-
42
- if tidx < num_springs:
43
- i, j = indices[tidx][0], indices[tidx][1]
44
- xi, xj = xs[i], xs[j]
45
- vi, vj = vs[i], vs[j]
46
- rest, ke, kd = rests[tidx], kes[tidx], kds[tidx]
47
-
48
- xij = cuda.local.array(3, dtype=cp.float32)
49
- vij = cuda.local.array(3, dtype=cp.float32)
50
- for k in range(3):
51
- xij[k] = xi[k] - xj[k]
52
- for k in range(3):
53
- vij[k] = vi[k] - vj[k]
54
-
55
- l = norm(xij)
56
-
57
- l_inv = float32(1.0) / l
58
-
59
- # normalized spring direction
60
- xij_unit = cuda.local.array(3, dtype=cp.float32)
61
- for k in range(3):
62
- xij_unit[k] = xij[k] * l_inv
63
- c = l - rest
64
- dcdt = dot(xij_unit, vij)
65
-
66
- # mass-spring-damper model
67
- fac = ke * c + kd * dcdt
68
- df = cuda.local.array(3, dtype=cp.float32)
69
- for k in range(3):
70
- df[k] = xij_unit[k] * fac
71
-
72
- for k in range(3):
73
- cuda.atomic.add(fs[i], k, -df[k])
74
- cuda.atomic.add(fs[j], k, df[k])
75
-
76
-
77
- # Support const array with cp array?
78
- g = np.array([0.0, 0.0 - 9.8, 0.0], dtype=np.float32)
79
- z = np.array([0.0, 0.0, 0.0], dtype=np.float32)
80
-
81
-
82
- @cuda.jit
83
- def integrate_particles_cuda(
84
- xs, vs, fs, ws, dt # position (N, 3) # velocity (N, 3) # force (N, 3) # inverse of mass (N,)
85
- ): # dt (1,)
86
- i = cuda.grid(1)
87
-
88
- if i < xs.shape[0]:
89
- w = ws[i]
90
- a = cuda.const.array_like(g) if w > 0.0 else cuda.const.array_like(z)
91
-
92
- for j in range(3):
93
- # vs[i] += ((f * w) + a) * dt (ideally)
94
- vs[i][j] = vs[i][j] + ((fs[i][j] * w) + a[j]) * dt
95
- xs[i][j] = xs[i][j] + vs[i][j] * dt
96
-
97
- fs[i] = 0.0
98
-
99
-
100
- class NbIntegrator:
101
- def __init__(self, cloth):
102
- self.cloth = cloth
103
-
104
- self.positions = cp.array(self.cloth.positions)
105
- self.velocities = cp.array(self.cloth.velocities)
106
- self.inv_mass = cp.array(self.cloth.inv_masses)
107
-
108
- self.spring_indices = cp.array(self.cloth.spring_indices)
109
- self.spring_lengths = cp.array(self.cloth.spring_lengths)
110
- self.spring_stiffness = cp.array(self.cloth.spring_stiffness)
111
- self.spring_damping = cp.array(self.cloth.spring_damping)
112
-
113
- self.forces = cp.zeros((self.cloth.num_particles, 3), dtype=cp.float32)
114
-
115
- self.num_particles = self.positions.shape[0]
116
- self.integrate_tpb = 4
117
- self.integrate_nb = self.num_particles // self.integrate_tpb + 1
118
-
119
- self.spring_tpb = 4
120
- self.spring_nb = self.cloth.num_springs // self.spring_tpb + 1
121
-
122
- def simulate(self, dt, substeps):
123
- sim_dt = dt / substeps
124
-
125
- for s in range(substeps):
126
- eval_springs_cuda[self.spring_nb, self.spring_tpb](
127
- self.cloth.num_springs,
128
- self.positions,
129
- self.velocities,
130
- self.spring_indices.reshape((self.cloth.num_springs, 2)),
131
- self.spring_lengths,
132
- self.spring_stiffness,
133
- self.spring_damping,
134
- self.forces,
135
- )
136
-
137
- # integrate
138
- integrate_particles_cuda[self.integrate_nb, self.integrate_tpb](
139
- self.positions, self.velocities, self.forces, self.inv_mass, sim_dt
140
- )
141
-
142
- return self.positions.get()
@@ -1,77 +0,0 @@
1
- # Copyright (c) 2022 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
- import numpy as np
9
-
10
-
11
- def eval_springs(x, v, indices, rest, ke, kd, f):
12
- i = indices[:, 0]
13
- j = indices[:, 1]
14
-
15
- xi = x[i]
16
- xj = x[j]
17
-
18
- vi = v[i]
19
- vj = v[j]
20
-
21
- xij = xi - xj
22
- vij = vi - vj
23
-
24
- l = np.linalg.norm(xij, axis=1)
25
- l_inv = 1.0 / l
26
-
27
- # normalized spring direction
28
- dir = (xij.T * l_inv).T
29
-
30
- c = l - rest
31
- dcdt = np.sum(dir * vij, axis=1)
32
-
33
- # damping based on relative velocity.
34
- fs = dir.T * (ke * c + kd * dcdt)
35
-
36
- np.add.at(f, i, -fs.T)
37
- np.add.at(f, j, fs.T)
38
-
39
-
40
- def integrate_particles(x, v, f, w, dt):
41
- g = np.array((0.0, 0.0 - 9.8, 0.0))
42
- s = w > 0.0
43
-
44
- a_ext = g * s[:, None]
45
-
46
- # simple semi-implicit Euler. v1 = v0 + a dt, x1 = x0 + v1 dt
47
- v += ((f.T * w).T + a_ext) * dt
48
- x += v * dt
49
-
50
- # clear forces
51
- f *= 0.0
52
-
53
-
54
- class NpIntegrator:
55
- def __init__(self, cloth):
56
- self.cloth = cloth
57
-
58
- self.forces = np.zeros((self.cloth.num_particles, 3), dtype=np.float32)
59
-
60
- def simulate(self, dt, substeps):
61
- sim_dt = dt / substeps
62
-
63
- for s in range(substeps):
64
- eval_springs(
65
- self.cloth.positions,
66
- self.cloth.velocities,
67
- self.cloth.spring_indices.reshape((self.cloth.num_springs, 2)),
68
- self.cloth.spring_lengths,
69
- self.cloth.spring_stiffness,
70
- self.cloth.spring_damping,
71
- self.forces,
72
- )
73
-
74
- # integrate
75
- integrate_particles(self.cloth.positions, self.cloth.velocities, self.forces, self.cloth.inv_masses, sim_dt)
76
-
77
- return self.cloth.positions
@@ -1,86 +0,0 @@
1
- # Copyright (c) 2022 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
- import torch
9
-
10
-
11
- def eval_springs(x, v, indices, rest, ke, kd, f):
12
- i = indices[:, 0]
13
- j = indices[:, 1]
14
-
15
- xi = x[i]
16
- xj = x[j]
17
-
18
- vi = v[i]
19
- vj = v[j]
20
-
21
- xij = xi - xj
22
- vij = vi - vj
23
-
24
- l = torch.linalg.norm(xij, axis=1)
25
- l_inv = 1.0 / l
26
-
27
- # normalized spring direction
28
- dir = (xij.T * l_inv).T
29
-
30
- c = l - rest
31
- dcdt = torch.sum(dir * vij, axis=1)
32
-
33
- # damping based on relative velocity.
34
- fs = dir.T * (ke * c + kd * dcdt)
35
-
36
- f.index_add_(dim=0, index=i, source=-fs.T)
37
- f.index_add_(dim=0, index=j, source=fs.T)
38
-
39
-
40
- def integrate_particles(x, v, f, g, w, dt):
41
- s = w > 0.0
42
-
43
- a_ext = g * s[:, None]
44
-
45
- # simple semi-implicit Euler. v1 = v0 + a dt, x1 = x0 + v1 dt
46
- v += ((f.T * w).T + a_ext) * dt
47
- x += v * dt
48
-
49
- # clear forces
50
- f *= 0.0
51
-
52
-
53
- class TrIntegrator:
54
- def __init__(self, cloth, device):
55
- self.cloth = cloth
56
-
57
- self.positions = torch.tensor(self.cloth.positions, device=device)
58
- self.velocities = torch.tensor(self.cloth.velocities, device=device)
59
- self.inv_mass = torch.tensor(self.cloth.inv_masses, device=device)
60
-
61
- self.spring_indices = torch.tensor(self.cloth.spring_indices, device=device, dtype=torch.long)
62
- self.spring_lengths = torch.tensor(self.cloth.spring_lengths, device=device)
63
- self.spring_stiffness = torch.tensor(self.cloth.spring_stiffness, device=device)
64
- self.spring_damping = torch.tensor(self.cloth.spring_damping, device=device)
65
-
66
- self.forces = torch.zeros((self.cloth.num_particles, 3), dtype=torch.float32, device=device)
67
- self.gravity = g = torch.tensor((0.0, 0.0 - 9.8, 0.0), dtype=torch.float32, device=device)
68
-
69
- def simulate(self, dt, substeps):
70
- sim_dt = dt / substeps
71
-
72
- for s in range(substeps):
73
- eval_springs(
74
- self.positions,
75
- self.velocities,
76
- self.spring_indices.reshape((self.cloth.num_springs, 2)),
77
- self.spring_lengths,
78
- self.spring_stiffness,
79
- self.spring_damping,
80
- self.forces,
81
- )
82
-
83
- # integrate
84
- integrate_particles(self.positions, self.velocities, self.forces, self.gravity, self.inv_mass, sim_dt)
85
-
86
- return self.positions.cpu().numpy()
@@ -1,112 +0,0 @@
1
- # Copyright (c) 2022 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
- import taichi as ti
9
- import numpy as np
10
-
11
-
12
- @ti.func
13
- def step(x):
14
- ret = 0.0
15
- if x < 0:
16
- ret = 1
17
- return ret
18
-
19
-
20
- @ti.data_oriented
21
- class TiIntegrator:
22
- @ti.kernel
23
- def eval_springs(self):
24
- for tid in range(self.cloth.num_springs):
25
- i = self.spring_indices[2 * tid]
26
- j = self.spring_indices[2 * tid + 1]
27
-
28
- ke = self.spring_stiffness[tid]
29
- kd = self.spring_damping[tid]
30
- rest = self.spring_lengths[tid]
31
-
32
- xi = self.positions[i]
33
- xj = self.positions[j]
34
-
35
- vi = self.velocities[i]
36
- vj = self.velocities[j]
37
-
38
- xij = xi - xj
39
- vij = vi - vj
40
-
41
- l = xij.norm()
42
- dir = xij.normalized()
43
-
44
- c = l - rest
45
- dcdt = dir.dot(vij)
46
-
47
- fs = dir * (ke * c + kd * dcdt)
48
-
49
- self.forces[i] -= fs
50
- self.forces[j] += fs
51
-
52
- @ti.kernel
53
- def integrate_particles(self, dt: ti.f32):
54
- for tid in range(self.cloth.num_particles):
55
- x0 = self.positions[tid]
56
- v0 = self.velocities[tid]
57
- f0 = self.forces[tid]
58
- w = self.inv_mass[tid]
59
-
60
- g = ti.Vector([0.0, 0.0, 0.0])
61
-
62
- if w > 0.0:
63
- g = ti.Vector([0.0, -9.81, 0.0])
64
-
65
- v1 = v0 + (f0 * w + g) * dt
66
- x1 = x0 + v1 * dt
67
-
68
- self.positions[tid] = x1
69
- self.velocities[tid] = v1
70
- self.forces[tid] = ti.Vector([0.0, 0.0, 0.0])
71
-
72
- def __init__(self, cloth, device):
73
- if device == "cpu":
74
- ti.init(arch=ti.cpu)
75
- elif device == "cuda":
76
- ti.init(arch=ti.gpu)
77
- else:
78
- raise RuntimeError("Unsupported Taichi device")
79
-
80
- self.cloth = cloth
81
-
82
- self.positions = ti.Vector.field(3, dtype=ti.f32, shape=self.cloth.num_particles)
83
- self.velocities = ti.Vector.field(3, dtype=ti.f32, shape=self.cloth.num_particles)
84
- self.inv_mass = ti.field(ti.f32, shape=self.cloth.num_particles)
85
-
86
- self.spring_indices = ti.field(ti.i32, shape=self.cloth.num_springs * 2)
87
- self.spring_lengths = ti.field(ti.f32, shape=self.cloth.num_springs)
88
- self.spring_stiffness = ti.field(ti.f32, shape=self.cloth.num_springs)
89
- self.spring_damping = ti.field(ti.f32, shape=self.cloth.num_springs)
90
-
91
- self.forces = ti.Vector.field(3, dtype=ti.f32, shape=self.cloth.num_particles)
92
-
93
- # upload data
94
- self.positions.from_numpy(cloth.positions)
95
- self.velocities.from_numpy(cloth.velocities)
96
- self.inv_mass.from_numpy(cloth.inv_masses)
97
- self.forces.from_numpy(np.zeros_like(self.cloth.velocities))
98
-
99
- self.spring_indices.from_numpy(cloth.spring_indices)
100
- self.spring_lengths.from_numpy(cloth.spring_lengths)
101
- self.spring_stiffness.from_numpy(cloth.spring_stiffness)
102
- self.spring_damping.from_numpy(cloth.spring_damping)
103
-
104
- def simulate(self, dt, substeps):
105
- sim_dt = dt / substeps
106
-
107
- for s in range(substeps):
108
- self.eval_springs()
109
-
110
- self.integrate_particles(sim_dt)
111
-
112
- return self.positions.to_numpy()
@@ -1,146 +0,0 @@
1
- # Copyright (c) 2022 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
- import warp as wp
9
-
10
- wp.init()
11
- wp.build.clear_kernel_cache()
12
-
13
-
14
- @wp.kernel
15
- def eval_springs(
16
- x: wp.array(dtype=wp.vec3),
17
- v: wp.array(dtype=wp.vec3),
18
- spring_indices: wp.array(dtype=int),
19
- spring_rest_lengths: wp.array(dtype=float),
20
- spring_stiffness: wp.array(dtype=float),
21
- spring_damping: wp.array(dtype=float),
22
- f: wp.array(dtype=wp.vec3),
23
- ):
24
- tid = wp.tid()
25
-
26
- i = spring_indices[tid * 2 + 0]
27
- j = spring_indices[tid * 2 + 1]
28
-
29
- ke = spring_stiffness[tid]
30
- kd = spring_damping[tid]
31
- rest = spring_rest_lengths[tid]
32
-
33
- xi = x[i]
34
- xj = x[j]
35
-
36
- vi = v[i]
37
- vj = v[j]
38
-
39
- xij = xi - xj
40
- vij = vi - vj
41
-
42
- l = wp.length(xij)
43
- l_inv = 1.0 / l
44
-
45
- # normalized spring direction
46
- dir = xij * l_inv
47
-
48
- c = l - rest
49
- dcdt = wp.dot(dir, vij)
50
-
51
- # damping based on relative velocity.
52
- fs = dir * (ke * c + kd * dcdt)
53
-
54
- wp.atomic_sub(f, i, fs)
55
- wp.atomic_add(f, j, fs)
56
-
57
-
58
- @wp.kernel
59
- def integrate_particles(
60
- x: wp.array(dtype=wp.vec3),
61
- v: wp.array(dtype=wp.vec3),
62
- f: wp.array(dtype=wp.vec3),
63
- w: wp.array(dtype=float),
64
- dt: float,
65
- ):
66
- tid = wp.tid()
67
-
68
- x0 = x[tid]
69
- v0 = v[tid]
70
- f0 = f[tid]
71
- inv_mass = w[tid]
72
-
73
- g = wp.vec3()
74
-
75
- # treat particles with inv_mass == 0 as kinematic
76
- if inv_mass > 0.0:
77
- g = wp.vec3(0.0, 0.0 - 9.81, 0.0)
78
-
79
- # simple semi-implicit Euler. v1 = v0 + a dt, x1 = x0 + v1 dt
80
- v1 = v0 + (f0 * inv_mass + g) * dt
81
- x1 = x0 + v1 * dt
82
-
83
- x[tid] = x1
84
- v[tid] = v1
85
-
86
- # clear forces
87
- f[tid] = wp.vec3()
88
-
89
-
90
- class WpIntegrator:
91
- def __init__(self, cloth, device):
92
- self.device = wp.get_device(device)
93
-
94
- with wp.ScopedDevice(self.device):
95
- self.positions = wp.from_numpy(cloth.positions, dtype=wp.vec3)
96
- self.positions_host = wp.from_numpy(cloth.positions, dtype=wp.vec3, device="cpu")
97
- self.invmass = wp.from_numpy(cloth.inv_masses, dtype=float)
98
-
99
- self.velocities = wp.zeros(cloth.num_particles, dtype=wp.vec3)
100
- self.forces = wp.zeros(cloth.num_particles, dtype=wp.vec3)
101
-
102
- self.spring_indices = wp.from_numpy(cloth.spring_indices, dtype=int)
103
- self.spring_lengths = wp.from_numpy(cloth.spring_lengths, dtype=float)
104
- self.spring_stiffness = wp.from_numpy(cloth.spring_stiffness, dtype=float)
105
- self.spring_damping = wp.from_numpy(cloth.spring_damping, dtype=float)
106
-
107
- self.cloth = cloth
108
-
109
- def simulate(self, dt, substeps):
110
- sim_dt = dt / substeps
111
-
112
- for s in range(substeps):
113
- wp.launch(
114
- kernel=eval_springs,
115
- dim=self.cloth.num_springs,
116
- inputs=[
117
- self.positions,
118
- self.velocities,
119
- self.spring_indices,
120
- self.spring_lengths,
121
- self.spring_stiffness,
122
- self.spring_damping,
123
- self.forces,
124
- ],
125
- outputs=[],
126
- device=self.device,
127
- )
128
-
129
- # integrate
130
- wp.launch(
131
- kernel=integrate_particles,
132
- dim=self.cloth.num_particles,
133
- inputs=[self.positions, self.velocities, self.forces, self.invmass, sim_dt],
134
- outputs=[],
135
- device=self.device,
136
- )
137
-
138
- # copy data back to host
139
- if self.device.is_cuda:
140
- wp.copy(self.positions_host, self.positions)
141
- wp.synchronize()
142
-
143
- return self.positions_host.numpy()
144
-
145
- else:
146
- return self.positions.numpy()