warp-lang 1.7.0__py3-none-manylinux_2_34_aarch64.whl → 1.7.2rc1__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 (60) hide show
  1. warp/autograd.py +12 -2
  2. warp/bin/warp-clang.so +0 -0
  3. warp/bin/warp.so +0 -0
  4. warp/build.py +1 -1
  5. warp/builtins.py +103 -66
  6. warp/codegen.py +48 -27
  7. warp/config.py +1 -1
  8. warp/context.py +112 -49
  9. warp/examples/benchmarks/benchmark_cloth.py +1 -1
  10. warp/examples/distributed/example_jacobi_mpi.py +507 -0
  11. warp/fem/cache.py +1 -1
  12. warp/fem/field/field.py +11 -1
  13. warp/fem/field/nodal_field.py +36 -22
  14. warp/fem/geometry/adaptive_nanogrid.py +7 -3
  15. warp/fem/geometry/trimesh.py +4 -12
  16. warp/jax_experimental/custom_call.py +14 -2
  17. warp/jax_experimental/ffi.py +100 -67
  18. warp/native/builtin.h +91 -65
  19. warp/native/svd.h +59 -49
  20. warp/native/tile.h +55 -26
  21. warp/native/volume.cpp +2 -2
  22. warp/native/volume_builder.cu +33 -22
  23. warp/native/warp.cu +1 -1
  24. warp/render/render_opengl.py +41 -34
  25. warp/render/render_usd.py +96 -6
  26. warp/sim/collide.py +11 -9
  27. warp/sim/inertia.py +189 -156
  28. warp/sim/integrator_euler.py +3 -0
  29. warp/sim/integrator_xpbd.py +3 -0
  30. warp/sim/model.py +56 -31
  31. warp/sim/render.py +4 -0
  32. warp/sparse.py +1 -1
  33. warp/stubs.py +73 -25
  34. warp/tests/assets/torus.usda +1 -1
  35. warp/tests/cuda/test_streams.py +1 -1
  36. warp/tests/sim/test_collision.py +237 -206
  37. warp/tests/sim/test_inertia.py +161 -0
  38. warp/tests/sim/test_model.py +5 -3
  39. warp/tests/sim/{flaky_test_sim_grad.py → test_sim_grad.py} +1 -4
  40. warp/tests/sim/test_xpbd.py +399 -0
  41. warp/tests/test_array.py +8 -7
  42. warp/tests/test_atomic.py +181 -2
  43. warp/tests/test_builtins_resolution.py +38 -38
  44. warp/tests/test_codegen.py +24 -3
  45. warp/tests/test_examples.py +16 -6
  46. warp/tests/test_fem.py +93 -14
  47. warp/tests/test_func.py +1 -1
  48. warp/tests/test_mat.py +416 -119
  49. warp/tests/test_quat.py +321 -137
  50. warp/tests/test_struct.py +116 -0
  51. warp/tests/test_vec.py +320 -174
  52. warp/tests/tile/test_tile.py +27 -0
  53. warp/tests/tile/test_tile_load.py +124 -0
  54. warp/tests/unittest_suites.py +2 -5
  55. warp/types.py +107 -9
  56. {warp_lang-1.7.0.dist-info → warp_lang-1.7.2rc1.dist-info}/METADATA +41 -19
  57. {warp_lang-1.7.0.dist-info → warp_lang-1.7.2rc1.dist-info}/RECORD +60 -57
  58. {warp_lang-1.7.0.dist-info → warp_lang-1.7.2rc1.dist-info}/WHEEL +1 -1
  59. {warp_lang-1.7.0.dist-info → warp_lang-1.7.2rc1.dist-info}/licenses/LICENSE.md +0 -26
  60. {warp_lang-1.7.0.dist-info → warp_lang-1.7.2rc1.dist-info}/top_level.txt +0 -0
@@ -184,6 +184,122 @@ def test_tile_load_unaligned(test, device):
184
184
  assert_np_equal(input.grad.numpy(), expected_grad)
185
185
 
186
186
 
187
+ @wp.kernel
188
+ def tile_load_aligned_small_kernel(
189
+ input: wp.array2d(dtype=float),
190
+ output: wp.array2d(dtype=float),
191
+ ):
192
+ t = wp.tile_load(input, shape=(3, 3), offset=(0, 0), storage="shared")
193
+ wp.tile_store(output, t, offset=(0, 0))
194
+
195
+
196
+ # regression test for tiles that are smaller than sizeof(float4) in that last
197
+ # dimension but are aligned to float4. Did trigger the fast float4 path by accident.
198
+ def test_tile_load_aligned_small(test, device):
199
+ rng = np.random.default_rng(42)
200
+
201
+ shape = [TILE_M, TILE_N]
202
+
203
+ input = wp.array(rng.random(shape), dtype=float, requires_grad=True, device=device)
204
+ output = wp.zeros(shape, dtype=float, device=device)
205
+
206
+ wp.launch_tiled(
207
+ tile_load_aligned_small_kernel,
208
+ dim=[1],
209
+ inputs=[input, output],
210
+ block_dim=TILE_DIM,
211
+ device=device,
212
+ )
213
+
214
+ # zeros except for the 3x3 tile at 0, 0
215
+ assert_np_equal(output.numpy()[3:, :], np.zeros((TILE_M - 3, TILE_N)))
216
+ assert_np_equal(output.numpy()[:, 3:], np.zeros((TILE_M, TILE_N - 3)))
217
+
218
+ # check output elements
219
+ assert_np_equal(output.numpy()[:3, :3], input.numpy()[:3, :3])
220
+
221
+
222
+ TILE_WIDTH = 5
223
+ TILE_OFFSET_X = 0
224
+ TILE_OFFSET_Y = 8
225
+
226
+
227
+ @wp.kernel
228
+ def test_tile_load_aligned_offset_unaligned_size_kernel(
229
+ input: wp.array2d(dtype=float),
230
+ output: wp.array2d(dtype=float),
231
+ ):
232
+ # Load a 5x5 tile from the input array starting at offset (0,8)
233
+ # and store it in shared memory
234
+ tile = wp.tile_load(input, shape=(TILE_WIDTH, TILE_WIDTH), offset=(TILE_OFFSET_X, TILE_OFFSET_Y), storage="shared")
235
+
236
+ # Store the loaded tile back to the output array at the same offset
237
+ wp.tile_store(output, tile, offset=(TILE_OFFSET_X, TILE_OFFSET_Y))
238
+
239
+
240
+ def test_tile_load_aligned_offset_unaligned_size(test, device):
241
+ """Test loading a tile with aligned offset but unaligned size."""
242
+
243
+ rng = np.random.default_rng(42)
244
+ array_shape = [TILE_N, TILE_M]
245
+
246
+ input_array = wp.array(rng.random(array_shape), dtype=float, requires_grad=True, device=device)
247
+ output_array = wp.zeros(array_shape, dtype=float, device=device)
248
+
249
+ wp.launch_tiled(
250
+ test_tile_load_aligned_offset_unaligned_size_kernel,
251
+ dim=[1],
252
+ inputs=[input_array, output_array],
253
+ block_dim=TILE_DIM,
254
+ device=device,
255
+ )
256
+
257
+ # Region before the tile offset should be zeros
258
+ assert_np_equal(output_array.numpy()[:TILE_WIDTH, :TILE_OFFSET_Y], np.zeros((TILE_WIDTH, TILE_OFFSET_Y)))
259
+
260
+ # Region where the tile was loaded/stored should match input
261
+ assert_np_equal(
262
+ output_array.numpy()[:TILE_WIDTH, TILE_OFFSET_Y : TILE_OFFSET_Y + TILE_WIDTH],
263
+ input_array.numpy()[:TILE_WIDTH, TILE_OFFSET_Y : TILE_OFFSET_Y + TILE_WIDTH],
264
+ )
265
+
266
+ # Region after the tile should be zeros
267
+ remaining_width = TILE_M - (TILE_OFFSET_Y + TILE_WIDTH)
268
+ assert_np_equal(
269
+ output_array.numpy()[:TILE_WIDTH, TILE_OFFSET_Y + TILE_WIDTH :], np.zeros((TILE_WIDTH, remaining_width))
270
+ )
271
+
272
+ # Rows below the tile should all be zeros
273
+ remaining_height = TILE_N - TILE_WIDTH
274
+ assert_np_equal(output_array.numpy()[TILE_WIDTH:, :], np.zeros((remaining_height, TILE_M)))
275
+
276
+
277
+ @wp.kernel
278
+ def test_tile_load_stride_unaligned_kernel(input: wp.array2d(dtype=wp.float32), output: wp.array2d(dtype=wp.float32)):
279
+ tile = wp.tile_load(input, shape=(4, 4))
280
+ wp.tile_store(output, tile)
281
+
282
+
283
+ # regression test for float4 aligned tiles that load from a source array with an incommensurate stride
284
+ def test_tile_load_stride_unaligned(test, device):
285
+ DIM = 5
286
+ input_np = np.eye(DIM) * 2.0
287
+ input_array = wp.array(input_np, dtype=wp.float32, device=device)
288
+ output_array = wp.zeros_like(input_array)
289
+
290
+ wp.launch_tiled(
291
+ test_tile_load_stride_unaligned_kernel,
292
+ dim=(1, 1),
293
+ inputs=[input_array],
294
+ outputs=[output_array],
295
+ block_dim=TILE_DIM,
296
+ device=device,
297
+ )
298
+
299
+ input_np[DIM - 1, DIM - 1] = 0.0
300
+ assert_np_equal(output_array.numpy(), input_np)
301
+
302
+
187
303
  # ----------------------------------------------------------------------------------------
188
304
 
189
305
  TILE_SIZE = 4
@@ -388,6 +504,14 @@ add_function_test(TestTileLoad, "test_tile_load_2d", test_tile_load(tile_load_2d
388
504
  add_function_test(TestTileLoad, "test_tile_load_3d", test_tile_load(tile_load_3d_kernel, 3), devices=devices)
389
505
  add_function_test(TestTileLoad, "test_tile_load_4d", test_tile_load(tile_load_4d_kernel, 4), devices=devices)
390
506
  add_function_test(TestTileLoad, "test_tile_load_unaligned", test_tile_load_unaligned, devices=devices)
507
+ add_function_test(TestTileLoad, "test_tile_load_aligned_small", test_tile_load_aligned_small, devices=devices)
508
+ add_function_test(
509
+ TestTileLoad,
510
+ "test_tile_load_aligned_offset_unaligned_size",
511
+ test_tile_load_aligned_offset_unaligned_size,
512
+ devices=devices,
513
+ )
514
+ add_function_test(TestTileLoad, "test_tile_load_stride_unaligned", test_tile_load_stride_unaligned, devices=devices)
391
515
 
392
516
  add_function_test(TestTileLoad, "test_tile_extract_1d", test_tile_extract(tile_extract_1d_kernel, 1), devices=devices)
393
517
  add_function_test(TestTileLoad, "test_tile_extract_2d", test_tile_extract(tile_extract_2d_kernel, 2), devices=devices)
@@ -116,8 +116,7 @@ def default_suite(test_loader: unittest.TestLoader = unittest.defaultTestLoader)
116
116
  from warp.tests.sim.test_collision import TestCollision
117
117
  from warp.tests.sim.test_coloring import TestColoring
118
118
  from warp.tests.sim.test_model import TestModel
119
-
120
- # from warp.tests.test_sim_grad import TestSimGradients Disabled, flaky
119
+ from warp.tests.sim.test_sim_grad import TestSimGradients
121
120
  from warp.tests.sim.test_sim_kinematics import TestSimKinematics
122
121
  from warp.tests.sim.test_vbd import TestVbd
123
122
  from warp.tests.test_adam import TestAdam
@@ -281,7 +280,7 @@ def default_suite(test_loader: unittest.TestLoader = unittest.defaultTestLoader)
281
280
  TestRounding,
282
281
  TestRunlengthEncode,
283
282
  TestScalarOps,
284
- # TestSimGradients, Disabled, flaky
283
+ TestSimGradients,
285
284
  TestSimKinematics,
286
285
  TestSmoothstep,
287
286
  TestSnippets,
@@ -357,7 +356,6 @@ def kit_suite(test_loader: unittest.TestLoader = unittest.defaultTestLoader):
357
356
  from warp.tests.test_noise import TestNoise
358
357
  from warp.tests.test_operators import TestOperators
359
358
  from warp.tests.test_rand import TestRand
360
- from warp.tests.test_reload import TestReload
361
359
  from warp.tests.test_rounding import TestRounding
362
360
  from warp.tests.test_runlength_encode import TestRunlengthEncode
363
361
  from warp.tests.test_scalar_ops import TestScalarOps
@@ -407,7 +405,6 @@ def kit_suite(test_loader: unittest.TestLoader = unittest.defaultTestLoader):
407
405
  TestPeer,
408
406
  TestPinned,
409
407
  TestRand,
410
- TestReload,
411
408
  TestRounding,
412
409
  TestRunlengthEncode,
413
410
  TestScalarOps,
warp/types.py CHANGED
@@ -278,7 +278,12 @@ def vector(length, dtype):
278
278
  def __str__(self):
279
279
  return f"[{', '.join(map(str, self))}]"
280
280
 
281
+ def __repr__(self):
282
+ return f"{type_repr(self)}([{', '.join(map(repr, self))}])"
283
+
281
284
  def __eq__(self, other):
285
+ if self._length_ != len(other):
286
+ return False
282
287
  for i in range(self._length_):
283
288
  if self[i] != other[i]:
284
289
  return False
@@ -421,7 +426,11 @@ def matrix(shape, dtype):
421
426
  return "[" + ",\n ".join(row_str) + "]"
422
427
 
423
428
  def __eq__(self, other):
429
+ if self._shape_[0] != len(other):
430
+ return False
424
431
  for i in range(self._shape_[0]):
432
+ if self._shape_[1] != len(other[i]):
433
+ return False
425
434
  for j in range(self._shape_[1]):
426
435
  if self[i][j] != other[i][j]:
427
436
  return False
@@ -723,7 +732,7 @@ def transformation(dtype=Any):
723
732
  super().__init__(*args)
724
733
  return
725
734
 
726
- # Even if the arguments match the original from components
735
+ # Even if the arguments match the original "from components"
727
736
  # signature, we still need to make sure that they represent
728
737
  # sequences that can be unpacked.
729
738
  if hasattr(p, "__len__") and hasattr(q, "__len__"):
@@ -1101,6 +1110,39 @@ def dtype_to_numpy(warp_dtype):
1101
1110
  raise TypeError(f"Cannot convert {warp_dtype} to a NumPy type")
1102
1111
 
1103
1112
 
1113
+ np_dtype_compatible_sets: dict[np.dtype, set[Any]] = {
1114
+ np.dtype(np.bool_): {bool, int8, uint8},
1115
+ np.dtype(np.int8): {int8, uint8},
1116
+ np.dtype(np.uint8): {int8, uint8},
1117
+ np.dtype(np.int16): {int16, uint16},
1118
+ np.dtype(np.uint16): {int16, uint16},
1119
+ np.dtype(np.int32): {int32, uint32},
1120
+ np.dtype(np.int64): {int64, uint64},
1121
+ np.dtype(np.uint32): {int32, uint32},
1122
+ np.dtype(np.uint64): {int64, uint64},
1123
+ np.dtype(np.byte): {bool, int8, uint8},
1124
+ np.dtype(np.ubyte): {bool, int8, uint8},
1125
+ np.dtype(np.float16): {float16},
1126
+ np.dtype(np.float32): {float32},
1127
+ np.dtype(np.float64): {float64},
1128
+ }
1129
+
1130
+
1131
+ def np_dtype_is_compatible(numpy_dtype: np.dtype, warp_dtype) -> builtins.bool:
1132
+ """Evaluate whether the given NumPy dtype is compatible with the given Warp dtype."""
1133
+
1134
+ compatible_set: set[Any] | None = np_dtype_compatible_sets.get(numpy_dtype)
1135
+
1136
+ if compatible_set is not None:
1137
+ if warp_dtype in compatible_set:
1138
+ return True
1139
+ # check if it's a vector or matrix type
1140
+ if hasattr(warp_dtype, "_wp_scalar_type_"):
1141
+ return warp_dtype._wp_scalar_type_ in compatible_set
1142
+
1143
+ return False
1144
+
1145
+
1104
1146
  # represent a Python range iterator
1105
1147
  class range_t:
1106
1148
  def __init__(self):
@@ -1339,22 +1381,67 @@ def type_typestr(dtype: type) -> str:
1339
1381
  raise Exception("Unknown ctype")
1340
1382
 
1341
1383
 
1384
+ def scalar_short_name(t):
1385
+ if t == float32:
1386
+ return "f"
1387
+ elif t == float64:
1388
+ return "d"
1389
+ elif t == int8:
1390
+ return "b"
1391
+ elif t == int16:
1392
+ return "s"
1393
+ elif t == int32:
1394
+ return "i"
1395
+ elif t == int64:
1396
+ return "l"
1397
+ elif t == uint8:
1398
+ return "ub"
1399
+ elif t == uint16:
1400
+ return "us"
1401
+ elif t == uint32:
1402
+ return "ui"
1403
+ elif t == uint64:
1404
+ return "ul"
1405
+ return None
1406
+
1407
+
1342
1408
  # converts any known type to a human readable string, good for error messages, reporting etc
1343
1409
  def type_repr(t):
1344
1410
  if is_array(t):
1345
- return str(f"array(ndim={t.ndim}, dtype={t.dtype})")
1411
+ if t.device is None:
1412
+ # array is used as a type annotation - display ndim instead of shape
1413
+ return f"array(ndim={t.ndim}, dtype={type_repr(t.dtype)})"
1414
+ return f"array(shape={t.shape}, dtype={type_repr(t.dtype)})"
1346
1415
  if is_tile(t):
1347
- return str(f"tile(dtype={t.dtype}, shape={t.shape}")
1348
- if type_is_vector(t):
1349
- return str(f"vector(length={t._shape_[0]}, dtype={t._wp_scalar_type_})")
1350
- if type_is_matrix(t):
1351
- return str(f"matrix(shape=({t._shape_[0]}, {t._shape_[1]}), dtype={t._wp_scalar_type_})")
1416
+ return f"tile(shape={t.shape}, dtype={type_repr(t.dtype)})"
1352
1417
  if isinstance(t, warp.codegen.Struct):
1353
1418
  return type_repr(t.cls)
1419
+ sn = None
1420
+ if hasattr(t, "_wp_scalar_type_"):
1421
+ sn = scalar_short_name(t._wp_scalar_type_)
1422
+ if type_is_transformation(t):
1423
+ if sn is not None:
1424
+ return f"transform{sn}"
1425
+ return f"transform(dtype={type_repr(t._wp_scalar_type_)})"
1426
+ if type_is_quaternion(t):
1427
+ if sn is not None:
1428
+ return f"quat{sn}"
1429
+ return f"quat(dtype={type_repr(t._wp_scalar_type_)})"
1430
+ if type_is_vector(t):
1431
+ if sn is not None and t._shape_[0] <= 4:
1432
+ return f"vec{t._shape_[0]}{sn}"
1433
+ return f"vector(length={t._shape_[0]}, dtype={type_repr(t._wp_scalar_type_)})"
1434
+ if type_is_matrix(t):
1435
+ if sn is not None and t._shape_[0] <= 4 and t._shape_[1] <= 4:
1436
+ return f"mat{t._shape_[0]}{t._shape_[1]}({sn})"
1437
+ return f"matrix(shape=({t._shape_[0]}, {t._shape_[1]}), dtype={type_repr(t._wp_scalar_type_)})"
1354
1438
  if t in scalar_types:
1355
1439
  return t.__name__
1356
1440
 
1357
- name = getattr(t, "__qualname__", t.__name__)
1441
+ name = getattr(t, "__name__", None)
1442
+ if name is None:
1443
+ return repr(t)
1444
+ name = getattr(t, "__qualname__", name)
1358
1445
  return t.__module__ + "." + name
1359
1446
 
1360
1447
 
@@ -1418,7 +1505,7 @@ def is_array(a) -> builtins.bool:
1418
1505
  return isinstance(a, array_types)
1419
1506
 
1420
1507
 
1421
- def scalars_equal(a, b, match_generic):
1508
+ def scalars_equal(a, b, match_generic=False):
1422
1509
  # convert to canonical types
1423
1510
  if a == float:
1424
1511
  a = float32
@@ -1809,6 +1896,14 @@ class array(Array[DType]):
1809
1896
 
1810
1897
  if dtype == Any:
1811
1898
  dtype = np_dtype_to_warp_type[data_dtype]
1899
+ else:
1900
+ # Warn if the data type is compatible with the requested dtype
1901
+ if not np_dtype_is_compatible(data_dtype, dtype):
1902
+ warp.utils.warn(
1903
+ f"The input data type {data_dtype} does not appear to be "
1904
+ f"compatible with the requested dtype {dtype}. If "
1905
+ "data-type sizes do not match, then this may lead to memory-access violations."
1906
+ )
1812
1907
 
1813
1908
  if data_strides is None:
1814
1909
  data_strides = strides_from_shape(data_shape, dtype)
@@ -2235,6 +2330,9 @@ class array(Array[DType]):
2235
2330
  else:
2236
2331
  return str(self.numpy())
2237
2332
 
2333
+ def __repr__(self):
2334
+ return type_repr(self)
2335
+
2238
2336
  def __getitem__(self, key):
2239
2337
  if isinstance(key, int):
2240
2338
  if self.ndim == 1:
@@ -1,12 +1,18 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: warp-lang
3
- Version: 1.7.0
3
+ Version: 1.7.2rc1
4
4
  Summary: A Python framework for high-performance simulation and graphics programming
5
5
  Author-email: NVIDIA Corporation <warp-python@nvidia.com>
6
6
  License: Apache-2.0
7
- Project-URL: GitHub, https://github.com/NVIDIA/warp
7
+ Project-URL: Homepage, https://developer.nvidia.com/warp-python
8
8
  Project-URL: Documentation, https://nvidia.github.io/warp
9
+ Project-URL: Repository, https://github.com/NVIDIA/warp
10
+ Project-URL: Issues, https://github.com/NVIDIA/warp/issues
9
11
  Project-URL: Changelog, https://github.com/NVIDIA/warp/blob/main/CHANGELOG.md
12
+ Classifier: Development Status :: 5 - Production/Stable
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: Natural Language :: English
10
16
  Classifier: Programming Language :: Python :: 3.8
11
17
  Classifier: Programming Language :: Python :: 3.9
12
18
  Classifier: Programming Language :: Python :: 3.10
@@ -14,15 +20,22 @@ Classifier: Programming Language :: Python :: 3.11
14
20
  Classifier: Programming Language :: Python :: 3.12
15
21
  Classifier: Programming Language :: Python :: 3.13
16
22
  Classifier: Programming Language :: Python :: 3 :: Only
17
- Classifier: License :: OSI Approved :: Apache Software License
23
+ Classifier: Environment :: GPU :: NVIDIA CUDA
24
+ Classifier: Environment :: GPU :: NVIDIA CUDA :: 12
18
25
  Classifier: Operating System :: OS Independent
26
+ Classifier: Topic :: Scientific/Engineering
19
27
  Requires-Python: >=3.8
20
28
  Description-Content-Type: text/markdown
21
29
  License-File: LICENSE.md
22
30
  Requires-Dist: numpy
31
+ Provides-Extra: docs
32
+ Requires-Dist: nvidia-sphinx-theme; python_version >= "3.9" and extra == "docs"
33
+ Requires-Dist: sphinx-copybutton; extra == "docs"
34
+ Requires-Dist: ruff==0.11.10; extra == "docs"
35
+ Requires-Dist: myst_parser; extra == "docs"
23
36
  Provides-Extra: dev
24
37
  Requires-Dist: pre-commit; extra == "dev"
25
- Requires-Dist: ruff; extra == "dev"
38
+ Requires-Dist: ruff==0.11.10; extra == "dev"
26
39
  Requires-Dist: nvtx; extra == "dev"
27
40
  Requires-Dist: nvidia-sphinx-theme; python_version >= "3.9" and extra == "dev"
28
41
  Requires-Dist: sphinx-copybutton; extra == "dev"
@@ -52,7 +65,8 @@ and comes with a rich set of primitives that make it easy to write
52
65
  programs for physics simulation, perception, robotics, and geometry processing. In addition, Warp kernels
53
66
  are differentiable and can be used as part of machine-learning pipelines with frameworks such as PyTorch, JAX and Paddle.
54
67
 
55
- Please refer to the project [Documentation](https://nvidia.github.io/warp/) for API and language reference and [CHANGELOG.md](./CHANGELOG.md) for release history.
68
+ Please refer to the project [Documentation](https://nvidia.github.io/warp/) for API and language reference and
69
+ [CHANGELOG.md](https://github.com/NVIDIA/warp/blob/main/CHANGELOG.md) for release history.
56
70
 
57
71
  <div align="center">
58
72
  <img src="https://github.com/NVIDIA/warp/raw/main/docs/img/header.jpg">
@@ -82,9 +96,9 @@ the `pip install` command, e.g.
82
96
 
83
97
  | Platform | Install Command |
84
98
  | --------------- | ----------------------------------------------------------------------------------------------------------------------------- |
85
- | Linux aarch64 | `pip install https://github.com/NVIDIA/warp/releases/download/v1.7.0/warp_lang-1.7.0+cu11-py3-none-manylinux2014_aarch64.whl` |
86
- | Linux x86-64 | `pip install https://github.com/NVIDIA/warp/releases/download/v1.7.0/warp_lang-1.7.0+cu11-py3-none-manylinux2014_x86_64.whl` |
87
- | Windows x86-64 | `pip install https://github.com/NVIDIA/warp/releases/download/v1.7.0/warp_lang-1.7.0+cu11-py3-none-win_amd64.whl` |
99
+ | Linux aarch64 | `pip install https://github.com/NVIDIA/warp/releases/download/v1.7.2/warp_lang-1.7.2+cu11-py3-none-manylinux2014_aarch64.whl` |
100
+ | Linux x86-64 | `pip install https://github.com/NVIDIA/warp/releases/download/v1.7.2/warp_lang-1.7.2+cu11-py3-none-manylinux2014_x86_64.whl` |
101
+ | Windows x86-64 | `pip install https://github.com/NVIDIA/warp/releases/download/v1.7.2/warp_lang-1.7.2+cu11-py3-none-win_amd64.whl` |
88
102
 
89
103
  The `--force-reinstall` option may need to be used to overwrite a previous installation.
90
104
 
@@ -491,26 +505,34 @@ Note that prior to 0.11.0, this schema was not strictly adhered to.
491
505
 
492
506
  ## License
493
507
 
494
- Warp is provided under the Apache License, Version 2.0. Please see [LICENSE.md](./LICENSE.md) for full license text.
508
+ Warp is provided under the Apache License, Version 2.0.
509
+ Please see [LICENSE.md](https://github.com/NVIDIA/warp/blob/main/LICENSE.md) for full license text.
495
510
 
496
511
  ## Contributing
497
512
 
498
- Contributions and pull requests from the community are welcome and are taken under the
499
- terms described in the **Feedback** section of [LICENSE.md](LICENSE.md#9-feedback).
513
+ Contributions and pull requests from the community are welcome.
500
514
  Please see the [Contribution Guide](https://nvidia.github.io/warp/modules/contribution_guide.html) for more
501
515
  information on contributing to the development of Warp.
502
516
 
503
- ## Citing
517
+ ## Publications & Citation
504
518
 
505
- If you use Warp in your research, please use the following citation:
519
+ ### Research Using Warp
520
+
521
+ Our [PUBLICATIONS.md](https://github.com/NVIDIA/warp/blob/main/PUBLICATIONS.md) file lists academic and research
522
+ publications that leverage the capabilities of Warp.
523
+ We encourage you to add your own published work using Warp to this list.
524
+
525
+ ### Citing Warp
526
+
527
+ To cite Warp itself in your own publications, please use the following BibTeX entry:
506
528
 
507
529
  ```bibtex
508
530
  @misc{warp2022,
509
- title= {Warp: A High-performance Python Framework for GPU Simulation and Graphics},
510
- author = {Miles Macklin},
511
- month = {March},
512
- year = {2022},
513
- note= {NVIDIA GPU Technology Conference (GTC)},
514
- howpublished = {\url{https://github.com/nvidia/warp}}
531
+ title = {Warp: A High-performance Python Framework for GPU Simulation and Graphics},
532
+ author = {Miles Macklin},
533
+ month = {March},
534
+ year = {2022},
535
+ note = {NVIDIA GPU Technology Conference (GTC)},
536
+ howpublished = {\url{https://github.com/nvidia/warp}}
515
537
  }
516
538
  ```