warp-lang 1.1.0__py3-none-manylinux2014_x86_64.whl → 1.2.0__py3-none-manylinux2014_x86_64.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 (218) hide show
  1. warp/bin/warp-clang.so +0 -0
  2. warp/bin/warp.so +0 -0
  3. warp/build.py +10 -37
  4. warp/build_dll.py +2 -2
  5. warp/builtins.py +274 -6
  6. warp/codegen.py +51 -4
  7. warp/config.py +2 -2
  8. warp/constants.py +4 -0
  9. warp/context.py +418 -203
  10. warp/examples/benchmarks/benchmark_api.py +0 -2
  11. warp/examples/benchmarks/benchmark_cloth_warp.py +0 -1
  12. warp/examples/benchmarks/benchmark_launches.py +0 -2
  13. warp/examples/core/example_dem.py +0 -2
  14. warp/examples/core/example_fluid.py +0 -2
  15. warp/examples/core/example_graph_capture.py +0 -2
  16. warp/examples/core/example_marching_cubes.py +0 -2
  17. warp/examples/core/example_mesh.py +0 -2
  18. warp/examples/core/example_mesh_intersect.py +0 -2
  19. warp/examples/core/example_nvdb.py +0 -2
  20. warp/examples/core/example_raycast.py +0 -2
  21. warp/examples/core/example_raymarch.py +0 -2
  22. warp/examples/core/example_render_opengl.py +0 -2
  23. warp/examples/core/example_sph.py +0 -2
  24. warp/examples/core/example_torch.py +0 -3
  25. warp/examples/core/example_wave.py +0 -2
  26. warp/examples/fem/example_apic_fluid.py +140 -115
  27. warp/examples/fem/example_burgers.py +262 -0
  28. warp/examples/fem/example_convection_diffusion.py +0 -2
  29. warp/examples/fem/example_convection_diffusion_dg.py +0 -2
  30. warp/examples/fem/example_deformed_geometry.py +0 -2
  31. warp/examples/fem/example_diffusion.py +0 -2
  32. warp/examples/fem/example_diffusion_3d.py +5 -4
  33. warp/examples/fem/example_diffusion_mgpu.py +0 -2
  34. warp/examples/fem/example_mixed_elasticity.py +0 -2
  35. warp/examples/fem/example_navier_stokes.py +0 -2
  36. warp/examples/fem/example_stokes.py +0 -2
  37. warp/examples/fem/example_stokes_transfer.py +0 -2
  38. warp/examples/optim/example_bounce.py +0 -2
  39. warp/examples/optim/example_cloth_throw.py +0 -2
  40. warp/examples/optim/example_diffray.py +0 -2
  41. warp/examples/optim/example_drone.py +0 -2
  42. warp/examples/optim/example_inverse_kinematics.py +0 -2
  43. warp/examples/optim/example_inverse_kinematics_torch.py +0 -2
  44. warp/examples/optim/example_spring_cage.py +0 -2
  45. warp/examples/optim/example_trajectory.py +0 -2
  46. warp/examples/optim/example_walker.py +0 -2
  47. warp/examples/sim/example_cartpole.py +0 -2
  48. warp/examples/sim/example_cloth.py +0 -2
  49. warp/examples/sim/example_granular.py +0 -2
  50. warp/examples/sim/example_granular_collision_sdf.py +0 -2
  51. warp/examples/sim/example_jacobian_ik.py +0 -2
  52. warp/examples/sim/example_particle_chain.py +0 -2
  53. warp/examples/sim/example_quadruped.py +0 -2
  54. warp/examples/sim/example_rigid_chain.py +0 -2
  55. warp/examples/sim/example_rigid_contact.py +0 -2
  56. warp/examples/sim/example_rigid_force.py +0 -2
  57. warp/examples/sim/example_rigid_gyroscopic.py +0 -2
  58. warp/examples/sim/example_rigid_soft_contact.py +0 -2
  59. warp/examples/sim/example_soft_body.py +0 -2
  60. warp/fem/__init__.py +1 -0
  61. warp/fem/cache.py +3 -1
  62. warp/fem/geometry/__init__.py +1 -0
  63. warp/fem/geometry/element.py +4 -0
  64. warp/fem/geometry/grid_3d.py +0 -4
  65. warp/fem/geometry/nanogrid.py +455 -0
  66. warp/fem/integrate.py +63 -9
  67. warp/fem/space/__init__.py +43 -158
  68. warp/fem/space/basis_space.py +34 -0
  69. warp/fem/space/collocated_function_space.py +1 -1
  70. warp/fem/space/grid_2d_function_space.py +13 -132
  71. warp/fem/space/grid_3d_function_space.py +16 -154
  72. warp/fem/space/hexmesh_function_space.py +37 -134
  73. warp/fem/space/nanogrid_function_space.py +202 -0
  74. warp/fem/space/quadmesh_2d_function_space.py +12 -119
  75. warp/fem/space/restriction.py +4 -1
  76. warp/fem/space/shape/__init__.py +77 -0
  77. warp/fem/space/shape/cube_shape_function.py +5 -15
  78. warp/fem/space/tetmesh_function_space.py +6 -76
  79. warp/fem/space/trimesh_2d_function_space.py +6 -76
  80. warp/native/array.h +12 -3
  81. warp/native/builtin.h +48 -5
  82. warp/native/bvh.cpp +14 -10
  83. warp/native/bvh.cu +23 -15
  84. warp/native/bvh.h +1 -0
  85. warp/native/clang/clang.cpp +2 -1
  86. warp/native/crt.cpp +11 -1
  87. warp/native/crt.h +18 -1
  88. warp/native/exports.h +187 -0
  89. warp/native/mat.h +47 -0
  90. warp/native/mesh.cpp +1 -1
  91. warp/native/mesh.cu +1 -2
  92. warp/native/nanovdb/GridHandle.h +366 -0
  93. warp/native/nanovdb/HostBuffer.h +590 -0
  94. warp/native/nanovdb/NanoVDB.h +3999 -2157
  95. warp/native/nanovdb/PNanoVDB.h +936 -99
  96. warp/native/quat.h +28 -1
  97. warp/native/rand.h +5 -1
  98. warp/native/vec.h +45 -1
  99. warp/native/volume.cpp +335 -103
  100. warp/native/volume.cu +39 -13
  101. warp/native/volume.h +725 -303
  102. warp/native/volume_builder.cu +381 -360
  103. warp/native/volume_builder.h +16 -1
  104. warp/native/volume_impl.h +61 -0
  105. warp/native/warp.cu +8 -2
  106. warp/native/warp.h +15 -7
  107. warp/render/render_opengl.py +191 -52
  108. warp/sim/integrator_featherstone.py +10 -3
  109. warp/sim/integrator_xpbd.py +16 -22
  110. warp/sparse.py +89 -27
  111. warp/stubs.py +83 -0
  112. warp/tests/assets/test_index_grid.nvdb +0 -0
  113. warp/tests/aux_test_dependent.py +0 -2
  114. warp/tests/aux_test_grad_customs.py +0 -2
  115. warp/tests/aux_test_reference.py +0 -2
  116. warp/tests/aux_test_reference_reference.py +0 -2
  117. warp/tests/aux_test_square.py +0 -2
  118. warp/tests/disabled_kinematics.py +0 -2
  119. warp/tests/test_adam.py +0 -2
  120. warp/tests/test_arithmetic.py +0 -36
  121. warp/tests/test_array.py +9 -11
  122. warp/tests/test_array_reduce.py +0 -2
  123. warp/tests/test_async.py +0 -2
  124. warp/tests/test_atomic.py +0 -2
  125. warp/tests/test_bool.py +58 -50
  126. warp/tests/test_builtins_resolution.py +0 -2
  127. warp/tests/test_bvh.py +0 -2
  128. warp/tests/test_closest_point_edge_edge.py +0 -1
  129. warp/tests/test_codegen.py +0 -4
  130. warp/tests/test_compile_consts.py +130 -10
  131. warp/tests/test_conditional.py +0 -2
  132. warp/tests/test_copy.py +0 -2
  133. warp/tests/test_ctypes.py +6 -8
  134. warp/tests/test_dense.py +0 -2
  135. warp/tests/test_devices.py +0 -2
  136. warp/tests/test_dlpack.py +9 -11
  137. warp/tests/test_examples.py +42 -39
  138. warp/tests/test_fabricarray.py +0 -3
  139. warp/tests/test_fast_math.py +0 -2
  140. warp/tests/test_fem.py +75 -54
  141. warp/tests/test_fp16.py +0 -2
  142. warp/tests/test_func.py +0 -2
  143. warp/tests/test_generics.py +27 -2
  144. warp/tests/test_grad.py +147 -8
  145. warp/tests/test_grad_customs.py +0 -2
  146. warp/tests/test_hash_grid.py +1 -3
  147. warp/tests/test_import.py +0 -2
  148. warp/tests/test_indexedarray.py +0 -2
  149. warp/tests/test_intersect.py +0 -2
  150. warp/tests/test_jax.py +0 -2
  151. warp/tests/test_large.py +11 -9
  152. warp/tests/test_launch.py +0 -2
  153. warp/tests/test_lerp.py +10 -54
  154. warp/tests/test_linear_solvers.py +3 -5
  155. warp/tests/test_lvalue.py +0 -2
  156. warp/tests/test_marching_cubes.py +0 -2
  157. warp/tests/test_mat.py +0 -2
  158. warp/tests/test_mat_lite.py +0 -2
  159. warp/tests/test_mat_scalar_ops.py +0 -2
  160. warp/tests/test_math.py +0 -2
  161. warp/tests/test_matmul.py +35 -37
  162. warp/tests/test_matmul_lite.py +29 -31
  163. warp/tests/test_mempool.py +0 -2
  164. warp/tests/test_mesh.py +0 -3
  165. warp/tests/test_mesh_query_aabb.py +0 -2
  166. warp/tests/test_mesh_query_point.py +0 -2
  167. warp/tests/test_mesh_query_ray.py +0 -2
  168. warp/tests/test_mlp.py +0 -2
  169. warp/tests/test_model.py +0 -2
  170. warp/tests/test_module_hashing.py +111 -0
  171. warp/tests/test_modules_lite.py +0 -3
  172. warp/tests/test_multigpu.py +0 -2
  173. warp/tests/test_noise.py +0 -4
  174. warp/tests/test_operators.py +0 -2
  175. warp/tests/test_options.py +0 -2
  176. warp/tests/test_peer.py +0 -2
  177. warp/tests/test_pinned.py +0 -2
  178. warp/tests/test_print.py +0 -2
  179. warp/tests/test_quat.py +0 -2
  180. warp/tests/test_rand.py +41 -5
  181. warp/tests/test_reload.py +0 -10
  182. warp/tests/test_rounding.py +0 -2
  183. warp/tests/test_runlength_encode.py +0 -2
  184. warp/tests/test_sim_grad.py +0 -2
  185. warp/tests/test_sim_kinematics.py +0 -2
  186. warp/tests/test_smoothstep.py +0 -2
  187. warp/tests/test_snippet.py +0 -2
  188. warp/tests/test_sparse.py +0 -2
  189. warp/tests/test_spatial.py +0 -2
  190. warp/tests/test_special_values.py +362 -0
  191. warp/tests/test_streams.py +0 -2
  192. warp/tests/test_struct.py +0 -2
  193. warp/tests/test_tape.py +0 -2
  194. warp/tests/test_torch.py +0 -2
  195. warp/tests/test_transient_module.py +0 -2
  196. warp/tests/test_types.py +0 -2
  197. warp/tests/test_utils.py +0 -2
  198. warp/tests/test_vec.py +0 -2
  199. warp/tests/test_vec_lite.py +0 -2
  200. warp/tests/test_vec_scalar_ops.py +0 -2
  201. warp/tests/test_verify_fp.py +0 -2
  202. warp/tests/test_volume.py +237 -13
  203. warp/tests/test_volume_write.py +86 -3
  204. warp/tests/unittest_serial.py +10 -9
  205. warp/tests/unittest_suites.py +6 -2
  206. warp/tests/unittest_utils.py +2 -171
  207. warp/tests/unused_test_misc.py +0 -2
  208. warp/tests/walkthrough_debug.py +1 -1
  209. warp/thirdparty/unittest_parallel.py +37 -40
  210. warp/types.py +514 -77
  211. {warp_lang-1.1.0.dist-info → warp_lang-1.2.0.dist-info}/METADATA +57 -30
  212. warp_lang-1.2.0.dist-info/RECORD +359 -0
  213. warp/examples/fem/example_convection_diffusion_dg0.py +0 -204
  214. warp/native/nanovdb/PNanoVDBWrite.h +0 -295
  215. warp_lang-1.1.0.dist-info/RECORD +0 -352
  216. {warp_lang-1.1.0.dist-info → warp_lang-1.2.0.dist-info}/LICENSE.md +0 -0
  217. {warp_lang-1.1.0.dist-info → warp_lang-1.2.0.dist-info}/WHEEL +0 -0
  218. {warp_lang-1.1.0.dist-info → warp_lang-1.2.0.dist-info}/top_level.txt +0 -0
@@ -1,3 +1,9 @@
1
+ from enum import Enum
2
+ from typing import Optional
3
+
4
+ from warp.fem.geometry import element as _element
5
+ from warp.fem.polynomial import Polynomial
6
+
1
7
  from .cube_shape_function import (
2
8
  CubeNonConformingPolynomialShapeFunctions,
3
9
  CubeSerendipityShapeFunctions,
@@ -11,3 +17,74 @@ from .square_shape_function import (
11
17
  )
12
18
  from .tet_shape_function import TetrahedronNonConformingPolynomialShapeFunctions, TetrahedronPolynomialShapeFunctions
13
19
  from .triangle_shape_function import Triangle2DNonConformingPolynomialShapeFunctions, Triangle2DPolynomialShapeFunctions
20
+
21
+
22
+ class ElementBasis(Enum):
23
+ """Choice of basis function to equip individual elements"""
24
+
25
+ LAGRANGE = 0
26
+ """Lagrange basis functions :math:`P_k` for simplices, tensor products :math:`Q_k` for squares and cubes"""
27
+ SERENDIPITY = 1
28
+ """Serendipity elements :math:`S_k`, corresponding to Lagrange nodes with interior points removed (for degree <= 3)"""
29
+ NONCONFORMING_POLYNOMIAL = 2
30
+ """Simplex Lagrange basis functions :math:`P_{kd}` embedded into non conforming reference elements (e.g. squares or cubes). Discontinuous only."""
31
+
32
+
33
+ def get_shape_function(
34
+ element: _element.Element,
35
+ space_dimension: int,
36
+ degree: int,
37
+ element_basis: ElementBasis,
38
+ family: Optional[Polynomial] = None,
39
+ ):
40
+ """
41
+ Equips a reference element with a shape function basis.
42
+
43
+ Args:
44
+ element: the reference element on which to build the shape function
45
+ space_dimension: the dimension of the embedding space
46
+ degree: polynomial degree of the per-element shape functions
47
+ element_basis: type of basis function for the individual elements
48
+ family: Polynomial family used to generate the shape function basis. If not provided, a reasonable basis is chosen.
49
+
50
+ Returns:
51
+ the corresponding shape function
52
+ """
53
+
54
+ if degree == 0:
55
+ return ConstantShapeFunction(element, space_dimension)
56
+
57
+ if family is None:
58
+ family = Polynomial.LOBATTO_GAUSS_LEGENDRE
59
+
60
+ if isinstance(element, _element.Square):
61
+ if element_basis == ElementBasis.NONCONFORMING_POLYNOMIAL:
62
+ return SquareNonConformingPolynomialShapeFunctions(degree=degree)
63
+ if element_basis == ElementBasis.SERENDIPITY and degree > 1:
64
+ return SquareSerendipityShapeFunctions(degree=degree, family=family)
65
+
66
+ return SquareBipolynomialShapeFunctions(degree=degree, family=family)
67
+ if isinstance(element, _element.Triangle):
68
+ if element_basis == ElementBasis.NONCONFORMING_POLYNOMIAL:
69
+ return Triangle2DNonConformingPolynomialShapeFunctions(degree=degree)
70
+ if element_basis == ElementBasis.SERENDIPITY and degree > 2:
71
+ raise NotImplementedError("Serendipity variant not implemented yet for Triangle elements")
72
+
73
+ return Triangle2DPolynomialShapeFunctions(degree=degree)
74
+
75
+ if isinstance(element, _element.Cube):
76
+ if element_basis == ElementBasis.NONCONFORMING_POLYNOMIAL:
77
+ return CubeNonConformingPolynomialShapeFunctions(degree=degree)
78
+ if element_basis == ElementBasis.SERENDIPITY and degree > 1:
79
+ return CubeSerendipityShapeFunctions(degree=degree, family=family)
80
+
81
+ return CubeTripolynomialShapeFunctions(degree=degree, family=family)
82
+ if isinstance(element, _element.Tetrahedron):
83
+ if element_basis == ElementBasis.NONCONFORMING_POLYNOMIAL:
84
+ return TetrahedronNonConformingPolynomialShapeFunctions(degree=degree)
85
+ if element_basis == ElementBasis.SERENDIPITY and degree > 2:
86
+ raise NotImplementedError("Serendipity variant not implemented yet for Tet elements")
87
+
88
+ return TetrahedronPolynomialShapeFunctions(degree=degree)
89
+
90
+ return NotImplementedError("Unrecognized element type")
@@ -10,16 +10,6 @@ from warp.fem.types import Coords
10
10
 
11
11
  from .tet_shape_function import TetrahedronPolynomialShapeFunctions
12
12
 
13
- _CUBE_EDGE_INDICES = wp.constant(
14
- wp.mat(shape=(3, 4), dtype=int)(
15
- [
16
- [0, 4, 2, 6],
17
- [3, 1, 7, 5],
18
- [8, 11, 9, 10],
19
- ]
20
- )
21
- )
22
-
23
13
 
24
14
  class CubeTripolynomialShapeFunctions:
25
15
  VERTEX = 0
@@ -96,13 +86,13 @@ class CubeTripolynomialShapeFunctions:
96
86
  return CubeTripolynomialShapeFunctions.VERTEX, type_instance, 0
97
87
 
98
88
  # z edge
99
- type_instance = _CUBE_EDGE_INDICES[2, mi * 2 + mj]
89
+ type_instance = 8 + mi * 2 + mj
100
90
  type_index = k - 1
101
91
  return CubeTripolynomialShapeFunctions.EDGE, type_instance, type_index
102
92
 
103
93
  if zk + mk == 1:
104
94
  # y edge
105
- type_instance = _CUBE_EDGE_INDICES[1, mk * 2 + mi]
95
+ type_instance = 4 + mk * 2 + mi
106
96
  type_index = j - 1
107
97
  return CubeTripolynomialShapeFunctions.EDGE, type_instance, type_index
108
98
 
@@ -114,7 +104,7 @@ class CubeTripolynomialShapeFunctions:
114
104
  if zj + mj == 1:
115
105
  if zk + mk == 1:
116
106
  # x edge
117
- type_instance = _CUBE_EDGE_INDICES[0, mj * 2 + mk]
107
+ type_instance = mj * 2 + mk
118
108
  type_index = i - 1
119
109
  return CubeTripolynomialShapeFunctions.EDGE, type_instance, type_index
120
110
 
@@ -399,7 +389,7 @@ class CubeSerendipityShapeFunctions:
399
389
  def _edge_coords(type_index: int):
400
390
  index_in_side = type_index // 4
401
391
  side_offset = type_index - 4 * index_in_side
402
- return (wp.vec3i(index_in_side + 1, side_offset // 2, side_offset % 2),)
392
+ return wp.vec3i(index_in_side + 1, side_offset // 2, side_offset & 1)
403
393
 
404
394
  @wp.func
405
395
  def _edge_axis(node_type: int):
@@ -410,7 +400,7 @@ class CubeSerendipityShapeFunctions:
410
400
  index_in_side = type_index // 4
411
401
  side_offset = type_index - 4 * index_in_side
412
402
 
413
- return _CUBE_EDGE_INDICES[node_type - CubeSerendipityShapeFunctions.EDGE_X, side_offset], index_in_side
403
+ return 4 * (node_type - CubeSerendipityShapeFunctions.EDGE_X) + side_offset, index_in_side
414
404
 
415
405
  def _get_node_lobatto_indices(self):
416
406
  ORDER = self.ORDER
@@ -1,16 +1,13 @@
1
1
  import warp as wp
2
2
  from warp.fem import cache
3
3
  from warp.fem.geometry import Tetmesh
4
- from warp.fem.types import Coords, ElementIndex
4
+ from warp.fem.types import ElementIndex
5
5
 
6
- from .basis_space import ShapeBasisSpace, TraceBasisSpace
7
6
  from .shape import (
8
- ConstantShapeFunction,
9
7
  ShapeFunction,
10
- TetrahedronNonConformingPolynomialShapeFunctions,
11
8
  TetrahedronPolynomialShapeFunctions,
12
9
  )
13
- from .topology import DiscontinuousSpaceTopologyMixin, SpaceTopology, forward_base_topology
10
+ from .topology import SpaceTopology, forward_base_topology
14
11
 
15
12
 
16
13
  @wp.struct
@@ -130,44 +127,6 @@ class TetmeshSpaceTopology(SpaceTopology):
130
127
  tet_face_indices[t1, t1_face] = e
131
128
 
132
129
 
133
- class TetmeshDiscontinuousSpaceTopology(
134
- DiscontinuousSpaceTopologyMixin,
135
- SpaceTopology,
136
- ):
137
- def __init__(self, mesh: Tetmesh, shape: ShapeFunction):
138
- super().__init__(mesh, shape.NODES_PER_ELEMENT)
139
-
140
-
141
- class TetmeshBasisSpace(ShapeBasisSpace):
142
- def __init__(self, topology: TetmeshSpaceTopology, shape: ShapeFunction):
143
- super().__init__(topology, shape)
144
-
145
- self._mesh: Tetmesh = topology.geometry
146
-
147
-
148
- class TetmeshPiecewiseConstantBasis(TetmeshBasisSpace):
149
- def __init__(self, mesh: Tetmesh):
150
- shape = ConstantShapeFunction(mesh.reference_cell(), space_dimension=3)
151
- topology = TetmeshDiscontinuousSpaceTopology(mesh, shape)
152
- super().__init__(shape=shape, topology=topology)
153
-
154
- class Trace(TraceBasisSpace):
155
- @wp.func
156
- def _node_coords_in_element(
157
- side_arg: Tetmesh.SideArg,
158
- basis_arg: TetmeshBasisSpace.BasisArg,
159
- element_index: ElementIndex,
160
- node_index_in_element: int,
161
- ):
162
- return Coords(1.0 / 3.0, 1.0 / 3.0, 1.0 / 3.0)
163
-
164
- def make_node_coords_in_element(self):
165
- return self._node_coords_in_element
166
-
167
- def trace(self):
168
- return TetmeshPiecewiseConstantBasis.Trace(self)
169
-
170
-
171
130
  class TetmeshPolynomialSpaceTopology(TetmeshSpaceTopology):
172
131
  def __init__(self, mesh: Tetmesh, shape: TetrahedronPolynomialShapeFunctions):
173
132
  super().__init__(mesh, shape, need_tet_edge_indices=shape.ORDER >= 2, need_tet_face_indices=shape.ORDER >= 3)
@@ -258,37 +217,8 @@ class TetmeshPolynomialSpaceTopology(TetmeshSpaceTopology):
258
217
  return element_node_index
259
218
 
260
219
 
261
- class TetmeshPolynomialBasisSpace(TetmeshBasisSpace):
262
- def __init__(
263
- self,
264
- mesh: Tetmesh,
265
- degree: int,
266
- ):
267
- shape = TetrahedronPolynomialShapeFunctions(degree)
268
- topology = forward_base_topology(TetmeshPolynomialSpaceTopology, mesh, shape)
269
-
270
- super().__init__(topology, shape)
271
-
272
-
273
- class TetmeshDGPolynomialBasisSpace(TetmeshBasisSpace):
274
- def __init__(
275
- self,
276
- mesh: Tetmesh,
277
- degree: int,
278
- ):
279
- shape = TetrahedronPolynomialShapeFunctions(degree)
280
- topology = TetmeshDiscontinuousSpaceTopology(mesh, shape)
281
-
282
- super().__init__(topology, shape)
283
-
284
-
285
- class TetmeshNonConformingPolynomialBasisSpace(TetmeshBasisSpace):
286
- def __init__(
287
- self,
288
- mesh: Tetmesh,
289
- degree: int,
290
- ):
291
- shape = TetrahedronNonConformingPolynomialShapeFunctions(degree)
292
- topology = TetmeshDiscontinuousSpaceTopology(mesh, shape)
220
+ def make_tetmesh_space_topology(mesh: Tetmesh, shape: ShapeFunction):
221
+ if isinstance(shape, TetrahedronPolynomialShapeFunctions):
222
+ return forward_base_topology(TetmeshPolynomialSpaceTopology, mesh, shape)
293
223
 
294
- super().__init__(topology, shape)
224
+ raise ValueError(f"Unsupported shape function {shape.name}")
@@ -1,16 +1,13 @@
1
1
  import warp as wp
2
2
  from warp.fem import cache
3
3
  from warp.fem.geometry import Trimesh2D
4
- from warp.fem.types import Coords, ElementIndex
4
+ from warp.fem.types import ElementIndex
5
5
 
6
- from .basis_space import ShapeBasisSpace, TraceBasisSpace
7
6
  from .shape import (
8
- ConstantShapeFunction,
9
7
  ShapeFunction,
10
- Triangle2DNonConformingPolynomialShapeFunctions,
11
8
  Triangle2DPolynomialShapeFunctions,
12
9
  )
13
- from .topology import DiscontinuousSpaceTopologyMixin, SpaceTopology, forward_base_topology
10
+ from .topology import SpaceTopology, forward_base_topology
14
11
 
15
12
 
16
13
  @wp.struct
@@ -95,44 +92,6 @@ class Trimesh2DSpaceTopology(SpaceTopology):
95
92
  tri_edge_indices[t1, t1_edge] = e
96
93
 
97
94
 
98
- class Trimesh2DDiscontinuousSpaceTopology(
99
- DiscontinuousSpaceTopologyMixin,
100
- SpaceTopology,
101
- ):
102
- def __init__(self, mesh: Trimesh2D, shape: ShapeFunction):
103
- super().__init__(mesh, shape.NODES_PER_ELEMENT)
104
-
105
-
106
- class Trimesh2DBasisSpace(ShapeBasisSpace):
107
- def __init__(self, topology: Trimesh2DSpaceTopology, shape: ShapeFunction):
108
- super().__init__(topology, shape)
109
-
110
- self._mesh: Trimesh2D = topology.geometry
111
-
112
-
113
- class Trimesh2DPiecewiseConstantBasis(Trimesh2DBasisSpace):
114
- def __init__(self, mesh: Trimesh2D):
115
- shape = ConstantShapeFunction(mesh.reference_cell(), space_dimension=2)
116
- topology = Trimesh2DDiscontinuousSpaceTopology(mesh, shape)
117
- super().__init__(shape=shape, topology=topology)
118
-
119
- class Trace(TraceBasisSpace):
120
- @wp.func
121
- def _node_coords_in_element(
122
- side_arg: Trimesh2D.SideArg,
123
- basis_arg: Trimesh2DBasisSpace.BasisArg,
124
- element_index: ElementIndex,
125
- node_index_in_element: int,
126
- ):
127
- return Coords(0.5, 0.0, 0.0)
128
-
129
- def make_node_coords_in_element(self):
130
- return self._node_coords_in_element
131
-
132
- def trace(self):
133
- return Trimesh2DPiecewiseConstantBasis.Trace(self)
134
-
135
-
136
95
  class Trimesh2DPolynomialSpaceTopology(Trimesh2DSpaceTopology):
137
96
  def __init__(self, mesh: Trimesh2D, shape: Triangle2DPolynomialShapeFunctions):
138
97
  super().__init__(mesh, shape)
@@ -187,37 +146,8 @@ class Trimesh2DPolynomialSpaceTopology(Trimesh2DSpaceTopology):
187
146
  return element_node_index
188
147
 
189
148
 
190
- class Trimesh2DPolynomialBasisSpace(Trimesh2DBasisSpace):
191
- def __init__(
192
- self,
193
- mesh: Trimesh2D,
194
- degree: int,
195
- ):
196
- shape = Triangle2DPolynomialShapeFunctions(degree)
197
- topology = forward_base_topology(Trimesh2DPolynomialSpaceTopology, mesh, shape)
198
-
199
- super().__init__(topology, shape)
200
-
201
-
202
- class Trimesh2DDGPolynomialBasisSpace(Trimesh2DBasisSpace):
203
- def __init__(
204
- self,
205
- mesh: Trimesh2D,
206
- degree: int,
207
- ):
208
- shape = Triangle2DPolynomialShapeFunctions(degree)
209
- topology = Trimesh2DDiscontinuousSpaceTopology(mesh, shape)
210
-
211
- super().__init__(topology, shape)
212
-
213
-
214
- class Trimesh2DNonConformingPolynomialBasisSpace(Trimesh2DBasisSpace):
215
- def __init__(
216
- self,
217
- mesh: Trimesh2D,
218
- degree: int,
219
- ):
220
- shape = Triangle2DNonConformingPolynomialShapeFunctions(degree)
221
- topology = Trimesh2DDiscontinuousSpaceTopology(mesh, shape)
149
+ def make_trimesh_2d_space_topology(mesh: Trimesh2D, shape: ShapeFunction):
150
+ if isinstance(shape, Triangle2DPolynomialShapeFunctions):
151
+ return forward_base_topology(Trimesh2DPolynomialSpaceTopology, mesh, shape)
222
152
 
223
- super().__init__(topology, shape)
153
+ raise ValueError(f"Unsupported shape function {shape.name}")
warp/native/array.h CHANGED
@@ -489,7 +489,10 @@ CUDA_CALLABLE inline array_t<T> view(array_t<T>& src, int i)
489
489
  assert(i >= 0 && i < src.shape[0]);
490
490
 
491
491
  array_t<T> a;
492
- a.data = data_at_byte_offset(src, byte_offset(src, i));
492
+ size_t offset = byte_offset(src, i);
493
+ a.data = data_at_byte_offset(src, offset);
494
+ if (src.grad)
495
+ a.grad = grad_at_byte_offset(src, offset);
493
496
  a.shape[0] = src.shape[1];
494
497
  a.shape[1] = src.shape[2];
495
498
  a.shape[2] = src.shape[3];
@@ -509,7 +512,10 @@ CUDA_CALLABLE inline array_t<T> view(array_t<T>& src, int i, int j)
509
512
  assert(j >= 0 && j < src.shape[1]);
510
513
 
511
514
  array_t<T> a;
512
- a.data = data_at_byte_offset(src, byte_offset(src, i, j));
515
+ size_t offset = byte_offset(src, i, j);
516
+ a.data = data_at_byte_offset(src, offset);
517
+ if (src.grad)
518
+ a.grad = grad_at_byte_offset(src, offset);
513
519
  a.shape[0] = src.shape[2];
514
520
  a.shape[1] = src.shape[3];
515
521
  a.strides[0] = src.strides[2];
@@ -528,7 +534,10 @@ CUDA_CALLABLE inline array_t<T> view(array_t<T>& src, int i, int j, int k)
528
534
  assert(k >= 0 && k < src.shape[2]);
529
535
 
530
536
  array_t<T> a;
531
- a.data = data_at_byte_offset(src, byte_offset(src, i, j, k));
537
+ size_t offset = byte_offset(src, i, j, k);
538
+ a.data = data_at_byte_offset(src, offset);
539
+ if (src.grad)
540
+ a.grad = grad_at_byte_offset(src, offset);
532
541
  a.shape[0] = src.shape[3];
533
542
  a.strides[0] = src.strides[3];
534
543
  a.ndim = src.ndim-3;
warp/native/builtin.h CHANGED
@@ -84,8 +84,17 @@ struct half
84
84
 
85
85
  unsigned short u;
86
86
 
87
- CUDA_CALLABLE inline bool operator==(const half& h) const { return u == h.u; }
88
- CUDA_CALLABLE inline bool operator!=(const half& h) const { return u != h.u; }
87
+ CUDA_CALLABLE inline bool operator==(const half& h) const
88
+ {
89
+ // Use float32 to get IEEE 754 behavior in case of a NaN
90
+ return float32(h) == float32(*this);
91
+ }
92
+
93
+ CUDA_CALLABLE inline bool operator!=(const half& h) const
94
+ {
95
+ // Use float32 to get IEEE 754 behavior in case of a NaN
96
+ return float32(h) != float32(*this);
97
+ }
89
98
  CUDA_CALLABLE inline bool operator>(const half& h) const { return half_to_float(*this) > half_to_float(h); }
90
99
  CUDA_CALLABLE inline bool operator>=(const half& h) const { return half_to_float(*this) >= half_to_float(h); }
91
100
  CUDA_CALLABLE inline bool operator<(const half& h) const { return half_to_float(*this) < half_to_float(h); }
@@ -293,7 +302,9 @@ inline CUDA_CALLABLE T bit_xor(T a, T b) { return a^b; } \
293
302
  inline CUDA_CALLABLE T lshift(T a, T b) { return a<<b; } \
294
303
  inline CUDA_CALLABLE T rshift(T a, T b) { return a>>b; } \
295
304
  inline CUDA_CALLABLE T invert(T x) { return ~x; } \
296
- inline CUDA_CALLABLE bool isfinite(T x) { return true; } \
305
+ inline CUDA_CALLABLE bool isfinite(T x) { return ::isfinite(double(x)); } \
306
+ inline CUDA_CALLABLE bool isnan(T x) { return ::isnan(double(x)); } \
307
+ inline CUDA_CALLABLE bool isinf(T x) { return ::isinf(double(x)); } \
297
308
  inline CUDA_CALLABLE void adj_mul(T a, T b, T& adj_a, T& adj_b, T adj_ret) { } \
298
309
  inline CUDA_CALLABLE void adj_div(T a, T b, T ret, T& adj_a, T& adj_b, T adj_ret) { } \
299
310
  inline CUDA_CALLABLE void adj_add(T a, T b, T& adj_a, T& adj_b, T adj_ret) { } \
@@ -313,7 +324,10 @@ inline CUDA_CALLABLE void adj_bit_or(T a, T b, T& adj_a, T& adj_b, T adj_ret) {
313
324
  inline CUDA_CALLABLE void adj_bit_xor(T a, T b, T& adj_a, T& adj_b, T adj_ret) { } \
314
325
  inline CUDA_CALLABLE void adj_lshift(T a, T b, T& adj_a, T& adj_b, T adj_ret) { } \
315
326
  inline CUDA_CALLABLE void adj_rshift(T a, T b, T& adj_a, T& adj_b, T adj_ret) { } \
316
- inline CUDA_CALLABLE void adj_invert(T x, T adj_x, T& adj_ret) { }
327
+ inline CUDA_CALLABLE void adj_invert(T x, T adj_x, T& adj_ret) { } \
328
+ inline CUDA_CALLABLE void adj_isnan(const T&, T&, bool) { } \
329
+ inline CUDA_CALLABLE void adj_isinf(const T&, T&, bool) { } \
330
+ inline CUDA_CALLABLE void adj_isfinite(const T&, T&, bool) { }
317
331
 
318
332
  inline CUDA_CALLABLE int8 abs(int8 x) { return ::abs(x); }
319
333
  inline CUDA_CALLABLE int16 abs(int16 x) { return ::abs(x); }
@@ -354,7 +368,7 @@ inline CUDA_CALLABLE uint32 sign(uint32 x) { return 1; }
354
368
  inline CUDA_CALLABLE uint64 sign(uint64 x) { return 1; }
355
369
 
356
370
 
357
- // Catch-all for non-float types
371
+ // Catch-all for non-float, non-integer types
358
372
  template<typename T>
359
373
  inline bool CUDA_CALLABLE isfinite(const T&)
360
374
  {
@@ -374,6 +388,32 @@ inline bool CUDA_CALLABLE isfinite(double x)
374
388
  return ::isfinite(x);
375
389
  }
376
390
 
391
+ inline bool CUDA_CALLABLE isnan(half x)
392
+ {
393
+ return ::isnan(float(x));
394
+ }
395
+ inline bool CUDA_CALLABLE isnan(float x)
396
+ {
397
+ return ::isnan(x);
398
+ }
399
+ inline bool CUDA_CALLABLE isnan(double x)
400
+ {
401
+ return ::isnan(x);
402
+ }
403
+
404
+ inline bool CUDA_CALLABLE isinf(half x)
405
+ {
406
+ return ::isinf(float(x));
407
+ }
408
+ inline bool CUDA_CALLABLE isinf(float x)
409
+ {
410
+ return ::isinf(x);
411
+ }
412
+ inline bool CUDA_CALLABLE isinf(double x)
413
+ {
414
+ return ::isinf(x);
415
+ }
416
+
377
417
  template<typename T>
378
418
  inline CUDA_CALLABLE void print(const T&)
379
419
  {
@@ -466,6 +506,9 @@ inline CUDA_CALLABLE void adj_div(T a, T b, T ret, T& adj_a, T& adj_b, T adj_ret
466
506
  assert(0);\
467
507
  })\
468
508
  }\
509
+ inline CUDA_CALLABLE void adj_isnan(const T&, T&, bool) { }\
510
+ inline CUDA_CALLABLE void adj_isinf(const T&, T&, bool) { }\
511
+ inline CUDA_CALLABLE void adj_isfinite(const T&, T&, bool) { }
469
512
 
470
513
  DECLARE_FLOAT_OPS(float16)
471
514
  DECLARE_FLOAT_OPS(float32)
warp/native/bvh.cpp CHANGED
@@ -339,6 +339,19 @@ void bvh_rem_descriptor(uint64_t id)
339
339
  }
340
340
 
341
341
 
342
+ // create in-place given existing descriptor
343
+ void bvh_create_host(vec3* lowers, vec3* uppers, int num_items, BVH& bvh)
344
+ {
345
+ memset(&bvh, 0, sizeof(BVH));
346
+
347
+ bvh.item_lowers = lowers;
348
+ bvh.item_uppers = uppers;
349
+ bvh.num_items = num_items;
350
+
351
+ MedianBVHBuilder builder;
352
+ builder.build(bvh, lowers, uppers, num_items);
353
+ }
354
+
342
355
  void bvh_destroy_host(BVH& bvh)
343
356
  {
344
357
  delete[] bvh.node_lowers;
@@ -360,16 +373,7 @@ void bvh_destroy_host(BVH& bvh)
360
373
  uint64_t bvh_create_host(vec3* lowers, vec3* uppers, int num_items)
361
374
  {
362
375
  BVH* bvh = new BVH();
363
- memset(bvh, 0, sizeof(BVH));
364
-
365
- bvh->context = NULL;
366
-
367
- bvh->item_lowers = lowers;
368
- bvh->item_uppers = uppers;
369
- bvh->num_items = num_items;
370
-
371
- MedianBVHBuilder builder;
372
- builder.build(*bvh, lowers, uppers, num_items);
376
+ wp::bvh_create_host(lowers, uppers, num_items, *bvh);
373
377
 
374
378
  return (uint64_t)bvh;
375
379
  }
warp/native/bvh.cu CHANGED
@@ -455,7 +455,28 @@ void LinearBVHBuilderGPU::build(BVH& bvh, const vec3* item_lowers, const vec3* i
455
455
 
456
456
  }
457
457
 
458
- void bvh_destroy_device(wp::BVH& bvh)
458
+ // create in-place given existing descriptor
459
+ void bvh_create_device(void* context, vec3* lowers, vec3* uppers, int num_items, BVH& bvh_host)
460
+ {
461
+ ContextGuard guard(context);
462
+
463
+ bvh_host.num_items = num_items;
464
+ bvh_host.max_nodes = 2*num_items;
465
+ bvh_host.node_lowers = (BVHPackedNodeHalf*)alloc_device(WP_CURRENT_CONTEXT, sizeof(BVHPackedNodeHalf)*bvh_host.max_nodes);
466
+ bvh_host.node_uppers = (BVHPackedNodeHalf*)alloc_device(WP_CURRENT_CONTEXT, sizeof(BVHPackedNodeHalf)*bvh_host.max_nodes);
467
+ bvh_host.node_parents = (int*)alloc_device(WP_CURRENT_CONTEXT, sizeof(int)*bvh_host.max_nodes);
468
+ bvh_host.node_counts = (int*)alloc_device(WP_CURRENT_CONTEXT, sizeof(int)*bvh_host.max_nodes);
469
+ bvh_host.root = (int*)alloc_device(WP_CURRENT_CONTEXT, sizeof(int));
470
+ bvh_host.item_lowers = lowers;
471
+ bvh_host.item_uppers = uppers;
472
+
473
+ bvh_host.context = context ? context : cuda_context_get_current();
474
+
475
+ LinearBVHBuilderGPU builder;
476
+ builder.build(bvh_host, lowers, uppers, num_items, NULL);
477
+ }
478
+
479
+ void bvh_destroy_device(BVH& bvh)
459
480
  {
460
481
  ContextGuard guard(bvh.context);
461
482
 
@@ -485,20 +506,7 @@ uint64_t bvh_create_device(void* context, wp::vec3* lowers, wp::vec3* uppers, in
485
506
  ContextGuard guard(context);
486
507
 
487
508
  wp::BVH bvh_host;
488
- bvh_host.num_items = num_items;
489
- bvh_host.max_nodes = 2*num_items;
490
- bvh_host.node_lowers = (wp::BVHPackedNodeHalf*)alloc_device(WP_CURRENT_CONTEXT, sizeof(wp::BVHPackedNodeHalf)*bvh_host.max_nodes);
491
- bvh_host.node_uppers = (wp::BVHPackedNodeHalf*)alloc_device(WP_CURRENT_CONTEXT, sizeof(wp::BVHPackedNodeHalf)*bvh_host.max_nodes);
492
- bvh_host.node_parents = (int*)alloc_device(WP_CURRENT_CONTEXT, sizeof(int)*bvh_host.max_nodes);
493
- bvh_host.node_counts = (int*)alloc_device(WP_CURRENT_CONTEXT, sizeof(int)*bvh_host.max_nodes);
494
- bvh_host.root = (int*)alloc_device(WP_CURRENT_CONTEXT, sizeof(int));
495
- bvh_host.item_lowers = lowers;
496
- bvh_host.item_uppers = uppers;
497
-
498
- bvh_host.context = context ? context : cuda_context_get_current();
499
-
500
- wp::LinearBVHBuilderGPU builder;
501
- builder.build(bvh_host, lowers, uppers, num_items, NULL);
509
+ bvh_create_device(WP_CURRENT_CONTEXT, lowers, uppers, num_items, bvh_host);
502
510
 
503
511
  // create device-side BVH descriptor
504
512
  wp::BVH* bvh_device = (wp::BVH*)alloc_device(WP_CURRENT_CONTEXT, sizeof(wp::BVH));
warp/native/bvh.h CHANGED
@@ -417,6 +417,7 @@ CUDA_CALLABLE void bvh_rem_descriptor(uint64_t id);
417
417
 
418
418
  #if !__CUDA_ARCH__
419
419
 
420
+ void bvh_create_host(vec3* lowers, vec3* uppers, int num_items, BVH& bvh);
420
421
  void bvh_destroy_host(wp::BVH& bvh);
421
422
  void bvh_refit_host(wp::BVH& bvh);
422
423
 
@@ -413,6 +413,8 @@ WP_API int load_obj(const char* object_file, const char* module_name)
413
413
  SYMBOL(memcpy), SYMBOL(memset), SYMBOL(memmove),
414
414
  SYMBOL(_wp_assert),
415
415
  SYMBOL(_wp_isfinite),
416
+ SYMBOL(_wp_isnan),
417
+ SYMBOL(_wp_isinf),
416
418
  #if defined(_WIN64)
417
419
  // For functions with large stack frames the compiler will emit a call to
418
420
  // __chkstk() to linearly touch each memory page. This grows the stack without
@@ -492,4 +494,3 @@ WP_API uint64_t lookup(const char* dll_name, const char* function_name)
492
494
  } // extern "C"
493
495
 
494
496
  } // namespace wp
495
-
warp/native/crt.cpp CHANGED
@@ -17,6 +17,16 @@ extern "C" WP_API int _wp_isfinite(double x)
17
17
  return std::isfinite(x);
18
18
  }
19
19
 
20
+ extern "C" WP_API int _wp_isnan(double x)
21
+ {
22
+ return std::isnan(x);
23
+ }
24
+
25
+ extern "C" WP_API int _wp_isinf(double x)
26
+ {
27
+ return std::isinf(x);
28
+ }
29
+
20
30
  extern "C" WP_API void _wp_assert(const char* expression, const char* file, unsigned int line)
21
31
  {
22
32
  fflush(stdout);
@@ -29,4 +39,4 @@ extern "C" WP_API void _wp_assert(const char* expression, const char* file, unsi
29
39
  // Now invoke the standard assert(), which may abort the program or break
30
40
  // into the debugger as decided by the runtime environment.
31
41
  assert(false && "assert() failed");
32
- }
42
+ }
warp/native/crt.h CHANGED
@@ -38,6 +38,12 @@ extern "C" WP_API void _wp_assert(const char* message, const char* file, unsigne
38
38
  // Helper for implementing isfinite()
39
39
  extern "C" WP_API int _wp_isfinite(double);
40
40
 
41
+ // Helper for implementing isnan()
42
+ extern "C" WP_API int _wp_isnan(double);
43
+
44
+ // Helper for implementing isinf()
45
+ extern "C" WP_API int _wp_isinf(double);
46
+
41
47
  #endif // !__CUDA_ARCH__
42
48
 
43
49
  #if !defined(WP_NO_CRT)
@@ -124,6 +130,7 @@ enum {
124
130
  #define INFINITY ((float)(DBL_MAX * DBL_MAX))
125
131
  #define HUGE_VAL ((double)INFINITY)
126
132
  #define HUGE_VALF ((float)INFINITY)
133
+ #define NAN ((float)(0.0 / 0.0))
127
134
 
128
135
  /// stdint.h
129
136
  typedef signed char int8_t;
@@ -320,6 +327,16 @@ inline bool isfinite(double x)
320
327
  return _wp_isfinite(x);
321
328
  }
322
329
 
330
+ inline bool isnan(double x)
331
+ {
332
+ return _wp_isnan(x);
333
+ }
334
+
335
+ inline bool isinf(double x)
336
+ {
337
+ return _wp_isinf(x);
338
+ }
339
+
323
340
  // assert.h
324
341
  #ifdef NDEBUG
325
342
  #define assert(expression) ((void)0)
@@ -332,4 +349,4 @@ inline bool isfinite(double x)
332
349
 
333
350
  #endif // !__CUDACC__
334
351
 
335
- #endif // WP_NO_CRT
352
+ #endif // WP_NO_CRT