warp-lang 1.7.2rc1__py3-none-manylinux_2_34_aarch64.whl → 1.8.0__py3-none-manylinux_2_34_aarch64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of warp-lang might be problematic. Click here for more details.

Files changed (181) hide show
  1. warp/__init__.py +3 -1
  2. warp/__init__.pyi +3489 -1
  3. warp/autograd.py +45 -122
  4. warp/bin/warp-clang.so +0 -0
  5. warp/bin/warp.so +0 -0
  6. warp/build.py +241 -252
  7. warp/build_dll.py +125 -26
  8. warp/builtins.py +1907 -384
  9. warp/codegen.py +257 -101
  10. warp/config.py +12 -1
  11. warp/constants.py +1 -1
  12. warp/context.py +657 -223
  13. warp/dlpack.py +1 -1
  14. warp/examples/benchmarks/benchmark_cloth.py +2 -2
  15. warp/examples/benchmarks/benchmark_tile_sort.py +155 -0
  16. warp/examples/core/example_sample_mesh.py +1 -1
  17. warp/examples/core/example_spin_lock.py +93 -0
  18. warp/examples/core/example_work_queue.py +118 -0
  19. warp/examples/fem/example_adaptive_grid.py +5 -5
  20. warp/examples/fem/example_apic_fluid.py +1 -1
  21. warp/examples/fem/example_burgers.py +1 -1
  22. warp/examples/fem/example_convection_diffusion.py +9 -6
  23. warp/examples/fem/example_darcy_ls_optimization.py +489 -0
  24. warp/examples/fem/example_deformed_geometry.py +1 -1
  25. warp/examples/fem/example_diffusion.py +2 -2
  26. warp/examples/fem/example_diffusion_3d.py +1 -1
  27. warp/examples/fem/example_distortion_energy.py +1 -1
  28. warp/examples/fem/example_elastic_shape_optimization.py +387 -0
  29. warp/examples/fem/example_magnetostatics.py +5 -3
  30. warp/examples/fem/example_mixed_elasticity.py +5 -3
  31. warp/examples/fem/example_navier_stokes.py +11 -9
  32. warp/examples/fem/example_nonconforming_contact.py +5 -3
  33. warp/examples/fem/example_streamlines.py +8 -3
  34. warp/examples/fem/utils.py +9 -8
  35. warp/examples/interop/example_jax_ffi_callback.py +2 -2
  36. warp/examples/optim/example_drone.py +1 -1
  37. warp/examples/sim/example_cloth.py +1 -1
  38. warp/examples/sim/example_cloth_self_contact.py +48 -54
  39. warp/examples/tile/example_tile_block_cholesky.py +502 -0
  40. warp/examples/tile/example_tile_cholesky.py +2 -1
  41. warp/examples/tile/example_tile_convolution.py +1 -1
  42. warp/examples/tile/example_tile_filtering.py +1 -1
  43. warp/examples/tile/example_tile_matmul.py +1 -1
  44. warp/examples/tile/example_tile_mlp.py +2 -0
  45. warp/fabric.py +7 -7
  46. warp/fem/__init__.py +5 -0
  47. warp/fem/adaptivity.py +1 -1
  48. warp/fem/cache.py +152 -63
  49. warp/fem/dirichlet.py +2 -2
  50. warp/fem/domain.py +136 -6
  51. warp/fem/field/field.py +141 -99
  52. warp/fem/field/nodal_field.py +85 -39
  53. warp/fem/field/virtual.py +97 -52
  54. warp/fem/geometry/adaptive_nanogrid.py +91 -86
  55. warp/fem/geometry/closest_point.py +13 -0
  56. warp/fem/geometry/deformed_geometry.py +102 -40
  57. warp/fem/geometry/element.py +56 -2
  58. warp/fem/geometry/geometry.py +323 -22
  59. warp/fem/geometry/grid_2d.py +157 -62
  60. warp/fem/geometry/grid_3d.py +116 -20
  61. warp/fem/geometry/hexmesh.py +86 -20
  62. warp/fem/geometry/nanogrid.py +166 -86
  63. warp/fem/geometry/partition.py +59 -25
  64. warp/fem/geometry/quadmesh.py +86 -135
  65. warp/fem/geometry/tetmesh.py +47 -119
  66. warp/fem/geometry/trimesh.py +77 -270
  67. warp/fem/integrate.py +107 -52
  68. warp/fem/linalg.py +25 -58
  69. warp/fem/operator.py +124 -27
  70. warp/fem/quadrature/pic_quadrature.py +36 -14
  71. warp/fem/quadrature/quadrature.py +40 -16
  72. warp/fem/space/__init__.py +1 -1
  73. warp/fem/space/basis_function_space.py +66 -46
  74. warp/fem/space/basis_space.py +17 -4
  75. warp/fem/space/dof_mapper.py +1 -1
  76. warp/fem/space/function_space.py +2 -2
  77. warp/fem/space/grid_2d_function_space.py +4 -1
  78. warp/fem/space/hexmesh_function_space.py +4 -2
  79. warp/fem/space/nanogrid_function_space.py +3 -1
  80. warp/fem/space/partition.py +11 -2
  81. warp/fem/space/quadmesh_function_space.py +4 -1
  82. warp/fem/space/restriction.py +5 -2
  83. warp/fem/space/shape/__init__.py +10 -8
  84. warp/fem/space/tetmesh_function_space.py +4 -1
  85. warp/fem/space/topology.py +52 -21
  86. warp/fem/space/trimesh_function_space.py +4 -1
  87. warp/fem/utils.py +53 -8
  88. warp/jax.py +1 -2
  89. warp/jax_experimental/ffi.py +12 -17
  90. warp/jax_experimental/xla_ffi.py +37 -24
  91. warp/math.py +171 -1
  92. warp/native/array.h +99 -0
  93. warp/native/builtin.h +174 -31
  94. warp/native/coloring.cpp +1 -1
  95. warp/native/exports.h +118 -63
  96. warp/native/intersect.h +3 -3
  97. warp/native/mat.h +5 -10
  98. warp/native/mathdx.cpp +11 -5
  99. warp/native/matnn.h +1 -123
  100. warp/native/quat.h +28 -4
  101. warp/native/sparse.cpp +121 -258
  102. warp/native/sparse.cu +181 -274
  103. warp/native/spatial.h +305 -17
  104. warp/native/tile.h +583 -72
  105. warp/native/tile_radix_sort.h +1108 -0
  106. warp/native/tile_reduce.h +237 -2
  107. warp/native/tile_scan.h +240 -0
  108. warp/native/tuple.h +189 -0
  109. warp/native/vec.h +6 -16
  110. warp/native/warp.cpp +36 -4
  111. warp/native/warp.cu +574 -51
  112. warp/native/warp.h +47 -74
  113. warp/optim/linear.py +5 -1
  114. warp/paddle.py +7 -8
  115. warp/py.typed +0 -0
  116. warp/render/render_opengl.py +58 -29
  117. warp/render/render_usd.py +124 -61
  118. warp/sim/__init__.py +9 -0
  119. warp/sim/collide.py +252 -78
  120. warp/sim/graph_coloring.py +8 -1
  121. warp/sim/import_mjcf.py +4 -3
  122. warp/sim/import_usd.py +11 -7
  123. warp/sim/integrator.py +5 -2
  124. warp/sim/integrator_euler.py +1 -1
  125. warp/sim/integrator_featherstone.py +1 -1
  126. warp/sim/integrator_vbd.py +751 -320
  127. warp/sim/integrator_xpbd.py +1 -1
  128. warp/sim/model.py +265 -260
  129. warp/sim/utils.py +10 -7
  130. warp/sparse.py +303 -166
  131. warp/tape.py +52 -51
  132. warp/tests/cuda/test_conditional_captures.py +1046 -0
  133. warp/tests/cuda/test_streams.py +1 -1
  134. warp/tests/geometry/test_volume.py +2 -2
  135. warp/tests/interop/test_dlpack.py +9 -9
  136. warp/tests/interop/test_jax.py +0 -1
  137. warp/tests/run_coverage_serial.py +1 -1
  138. warp/tests/sim/disabled_kinematics.py +2 -2
  139. warp/tests/sim/{test_vbd.py → test_cloth.py} +296 -113
  140. warp/tests/sim/test_collision.py +159 -51
  141. warp/tests/sim/test_coloring.py +15 -1
  142. warp/tests/test_array.py +254 -2
  143. warp/tests/test_array_reduce.py +2 -2
  144. warp/tests/test_atomic_cas.py +299 -0
  145. warp/tests/test_codegen.py +142 -19
  146. warp/tests/test_conditional.py +47 -1
  147. warp/tests/test_ctypes.py +0 -20
  148. warp/tests/test_devices.py +8 -0
  149. warp/tests/test_fabricarray.py +4 -2
  150. warp/tests/test_fem.py +58 -25
  151. warp/tests/test_func.py +42 -1
  152. warp/tests/test_grad.py +1 -1
  153. warp/tests/test_lerp.py +1 -3
  154. warp/tests/test_map.py +481 -0
  155. warp/tests/test_mat.py +1 -24
  156. warp/tests/test_quat.py +6 -15
  157. warp/tests/test_rounding.py +10 -38
  158. warp/tests/test_runlength_encode.py +7 -7
  159. warp/tests/test_smoothstep.py +1 -1
  160. warp/tests/test_sparse.py +51 -2
  161. warp/tests/test_spatial.py +507 -1
  162. warp/tests/test_struct.py +2 -2
  163. warp/tests/test_tuple.py +265 -0
  164. warp/tests/test_types.py +2 -2
  165. warp/tests/test_utils.py +24 -18
  166. warp/tests/tile/test_tile.py +420 -1
  167. warp/tests/tile/test_tile_mathdx.py +518 -14
  168. warp/tests/tile/test_tile_reduce.py +213 -0
  169. warp/tests/tile/test_tile_shared_memory.py +130 -1
  170. warp/tests/tile/test_tile_sort.py +117 -0
  171. warp/tests/unittest_suites.py +4 -6
  172. warp/types.py +462 -308
  173. warp/utils.py +647 -86
  174. {warp_lang-1.7.2rc1.dist-info → warp_lang-1.8.0.dist-info}/METADATA +20 -6
  175. {warp_lang-1.7.2rc1.dist-info → warp_lang-1.8.0.dist-info}/RECORD +178 -166
  176. warp/stubs.py +0 -3381
  177. warp/tests/sim/test_xpbd.py +0 -399
  178. warp/tests/test_mlp.py +0 -282
  179. {warp_lang-1.7.2rc1.dist-info → warp_lang-1.8.0.dist-info}/WHEEL +0 -0
  180. {warp_lang-1.7.2rc1.dist-info → warp_lang-1.8.0.dist-info}/licenses/LICENSE.md +0 -0
  181. {warp_lang-1.7.2rc1.dist-info → warp_lang-1.8.0.dist-info}/top_level.txt +0 -0
@@ -13,10 +13,11 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
+ from functools import cached_property
16
17
  from typing import Any
17
18
 
18
19
  import warp as wp
19
- from warp.fem.cache import TemporaryStore, borrow_temporary, cached_arg_value
20
+ from warp.fem.cache import TemporaryStore, borrow_temporary, cached_arg_value, dynamic_struct
20
21
  from warp.fem.types import NULL_ELEMENT_INDEX, ElementIndex
21
22
  from warp.fem.utils import masked_indices
22
23
 
@@ -63,9 +64,15 @@ class GeometryPartition:
63
64
  def cell_arg_value(self, device):
64
65
  raise NotImplementedError()
65
66
 
67
+ def fill_cell_arg(self, args: CellArg, device):
68
+ raise NotImplementedError()
69
+
66
70
  def side_arg_value(self, device):
67
71
  raise NotImplementedError()
68
72
 
73
+ def fill_side_arg(self, args: SideArg, device):
74
+ raise NotImplementedError()
75
+
69
76
  @staticmethod
70
77
  def cell_index(args: CellArg, partition_cell_index: int):
71
78
  """Index in the geometry of a partition cell"""
@@ -103,6 +110,7 @@ class WholeGeometryPartition(GeometryPartition):
103
110
 
104
111
  self.SideArg = geometry.SideIndexArg
105
112
  self.side_arg_value = geometry.side_index_arg_value
113
+ self.fill_side_arg = geometry.fill_side_index_arg
106
114
 
107
115
  self.cell_index = WholeGeometryPartition._identity_element_index
108
116
  self.partition_cell_index = WholeGeometryPartition._identity_element_index
@@ -135,6 +143,9 @@ class WholeGeometryPartition(GeometryPartition):
135
143
  arg = WholeGeometryPartition.CellArg()
136
144
  return arg
137
145
 
146
+ def fill_cell_arg(self, args: CellArg, device):
147
+ pass
148
+
138
149
  @wp.func
139
150
  def _identity_element_index(args: Any, idx: ElementIndex):
140
151
  return idx
@@ -143,6 +154,10 @@ class WholeGeometryPartition(GeometryPartition):
143
154
  def name(self) -> str:
144
155
  return self.geometry.name
145
156
 
157
+ @wp.func
158
+ def side_to_cell_arg(side_arg: Any):
159
+ return WholeGeometryPartition.CellArg()
160
+
146
161
 
147
162
  class CellBasedGeometryPartition(GeometryPartition):
148
163
  """Geometry partition based on a subset of cells. Interior, boundary and frontier sides are automatically categorized."""
@@ -154,11 +169,19 @@ class CellBasedGeometryPartition(GeometryPartition):
154
169
  ):
155
170
  super().__init__(geometry)
156
171
 
157
- @wp.struct
158
- class SideArg:
159
- partition_side_indices: wp.array(dtype=int)
160
- boundary_side_indices: wp.array(dtype=int)
161
- frontier_side_indices: wp.array(dtype=int)
172
+ @cached_property
173
+ def SideArg(self):
174
+ return self._make_side_arg()
175
+
176
+ def _make_side_arg(self):
177
+ @dynamic_struct(suffix=self.name)
178
+ class SideArg:
179
+ cell_arg: self.CellArg
180
+ partition_side_indices: wp.array(dtype=int)
181
+ boundary_side_indices: wp.array(dtype=int)
182
+ frontier_side_indices: wp.array(dtype=int)
183
+
184
+ return SideArg
162
185
 
163
186
  def side_count(self) -> int:
164
187
  return self._partition_side_indices.array.shape[0]
@@ -171,24 +194,28 @@ class CellBasedGeometryPartition(GeometryPartition):
171
194
 
172
195
  @cached_arg_value
173
196
  def side_arg_value(self, device):
174
- arg = LinearGeometryPartition.SideArg()
175
- arg.partition_side_indices = self._partition_side_indices.array.to(device)
176
- arg.boundary_side_indices = self._boundary_side_indices.array.to(device)
177
- arg.frontier_side_indices = self._frontier_side_indices.array.to(device)
197
+ arg = self.SideArg()
198
+ self.fill_side_arg(arg, device)
178
199
  return arg
179
200
 
201
+ def fill_side_arg(self, args: SideArg, device):
202
+ self.fill_cell_arg(args.cell_arg, device)
203
+ args.partition_side_indices = self._partition_side_indices.array.to(device)
204
+ args.boundary_side_indices = self._boundary_side_indices.array.to(device)
205
+ args.frontier_side_indices = self._frontier_side_indices.array.to(device)
206
+
180
207
  @wp.func
181
- def side_index(args: SideArg, partition_side_index: int):
208
+ def side_index(args: Any, partition_side_index: int):
182
209
  """partition side to side index"""
183
210
  return args.partition_side_indices[partition_side_index]
184
211
 
185
212
  @wp.func
186
- def boundary_side_index(args: SideArg, boundary_side_index: int):
213
+ def boundary_side_index(args: Any, boundary_side_index: int):
187
214
  """Boundary side to side index"""
188
215
  return args.boundary_side_indices[boundary_side_index]
189
216
 
190
217
  @wp.func
191
- def frontier_side_index(args: SideArg, frontier_side_index: int):
218
+ def frontier_side_index(args: Any, frontier_side_index: int):
192
219
  """Frontier side to side index"""
193
220
  return args.frontier_side_indices[frontier_side_index]
194
221
 
@@ -271,6 +298,10 @@ class CellBasedGeometryPartition(GeometryPartition):
271
298
  boundary_side_mask.release()
272
299
  frontier_side_mask.release()
273
300
 
301
+ @wp.func
302
+ def side_to_cell_arg(side_arg: Any):
303
+ return side_arg.cell_arg
304
+
274
305
 
275
306
  class LinearGeometryPartition(CellBasedGeometryPartition):
276
307
  def __init__(
@@ -314,10 +345,13 @@ class LinearGeometryPartition(CellBasedGeometryPartition):
314
345
 
315
346
  def cell_arg_value(self, device):
316
347
  arg = LinearGeometryPartition.CellArg()
317
- arg.cell_begin = self.cell_begin
318
- arg.cell_end = self.cell_end
348
+ self.fill_cell_arg(arg, device)
319
349
  return arg
320
350
 
351
+ def fill_cell_arg(self, args: CellArg, device):
352
+ args.cell_begin = self.cell_begin
353
+ args.cell_end = self.cell_end
354
+
321
355
  @wp.func
322
356
  def cell_index(args: CellArg, partition_cell_index: int):
323
357
  """Partition cell to cell index"""
@@ -326,14 +360,11 @@ class LinearGeometryPartition(CellBasedGeometryPartition):
326
360
  @wp.func
327
361
  def partition_cell_index(args: CellArg, cell_index: int):
328
362
  """Partition cell to cell index"""
329
- if cell_index > args.cell_end:
330
- return NULL_ELEMENT_INDEX
331
-
332
- partition_cell_index = cell_index - args.cell_begin
333
- if partition_cell_index < 0:
334
- return NULL_ELEMENT_INDEX
335
-
336
- return partition_cell_index
363
+ return wp.where(
364
+ cell_index >= args.cell_begin and cell_index < args.cell_end,
365
+ cell_index - args.cell_begin,
366
+ NULL_ELEMENT_INDEX,
367
+ )
337
368
 
338
369
  @wp.func
339
370
  def _cell_inclusion_test(arg: CellArg, cell_index: int):
@@ -372,10 +403,13 @@ class ExplicitGeometryPartition(CellBasedGeometryPartition):
372
403
  @cached_arg_value
373
404
  def cell_arg_value(self, device):
374
405
  arg = ExplicitGeometryPartition.CellArg()
375
- arg.cell_index = self._cells.array.to(device)
376
- arg.partition_cell_index = self._partition_cells.array.to(device)
406
+ self.fill_cell_arg(arg, device)
377
407
  return arg
378
408
 
409
+ def fill_cell_arg(self, args: CellArg, device):
410
+ args.cell_index = self._cells.array.to(device)
411
+ args.partition_cell_index = self._partition_cells.array.to(device)
412
+
379
413
  @wp.func
380
414
  def cell_index(args: CellArg, partition_cell_index: int):
381
415
  return args.cell_index[partition_cell_index]
@@ -13,7 +13,7 @@
13
13
  # See the License for the specific language governing permissions and
14
14
  # limitations under the License.
15
15
 
16
- from typing import Optional
16
+ from typing import Any, Optional
17
17
 
18
18
  import warp as wp
19
19
  from warp.fem.cache import (
@@ -24,6 +24,7 @@ from warp.fem.cache import (
24
24
  )
25
25
  from warp.fem.types import OUTSIDE, Coords, ElementIndex, Sample
26
26
 
27
+ from .closest_point import project_on_seg_at_origin
27
28
  from .element import LinearEdge, Square
28
29
  from .geometry import Geometry
29
30
 
@@ -32,9 +33,7 @@ from .geometry import Geometry
32
33
  class QuadmeshCellArg:
33
34
  quad_vertex_indices: wp.array2d(dtype=int)
34
35
 
35
- # for neighbor cell lookup
36
- vertex_quad_offsets: wp.array(dtype=int)
37
- vertex_quad_indices: wp.array(dtype=int)
36
+ quad_bvh: wp.uint64
38
37
 
39
38
 
40
39
  @wp.struct
@@ -48,7 +47,11 @@ class Quadmesh(Geometry):
48
47
  """Quadrilateral mesh geometry"""
49
48
 
50
49
  def __init__(
51
- self, quad_vertex_indices: wp.array, positions: wp.array, temporary_store: Optional[TemporaryStore] = None
50
+ self,
51
+ quad_vertex_indices: wp.array,
52
+ positions: wp.array,
53
+ build_bvh: bool = False,
54
+ temporary_store: Optional[TemporaryStore] = None,
52
55
  ):
53
56
  """
54
57
  Constructs a D-dimensional quadrilateral mesh.
@@ -77,6 +80,12 @@ class Quadmesh(Geometry):
77
80
  )
78
81
 
79
82
  self._make_default_dependent_implementations()
83
+ self.cell_closest_point = self._make_cell_closest_point()
84
+ self.cell_coordinates = self._make_cell_coordinates()
85
+ self.side_coordinates = self._make_side_coordinates(assume_linear=True)
86
+
87
+ if build_bvh:
88
+ self.build_bvh(self.positions.device)
80
89
 
81
90
  def cell_count(self):
82
91
  return self.quad_vertex_indices.shape[0]
@@ -108,50 +117,42 @@ class Quadmesh(Geometry):
108
117
  class SideIndexArg:
109
118
  boundary_edge_indices: wp.array(dtype=int)
110
119
 
111
- @cached_arg_value
112
- def _cell_topo_arg_value(self, device):
113
- args = QuadmeshCellArg()
114
-
120
+ def fill_cell_topo_arg(self, args: QuadmeshCellArg, device):
115
121
  args.quad_vertex_indices = self.quad_vertex_indices.to(device)
116
- args.vertex_quad_offsets = self._vertex_quad_offsets.to(device)
117
- args.vertex_quad_indices = self._vertex_quad_indices.to(device)
118
-
119
- return args
122
+ args.quad_bvh = self.bvh_id(device)
120
123
 
121
- @cached_arg_value
122
- def _side_topo_arg_value(self, device):
123
- args = QuadmeshSideArg()
124
-
125
- args.cell_arg = self._cell_topo_arg_value(device)
124
+ def fill_side_topo_arg(self, args: QuadmeshSideArg, device):
125
+ self.fill_cell_topo_arg(args.cell_arg, device)
126
126
  args.edge_vertex_indices = self._edge_vertex_indices.to(device)
127
127
  args.edge_quad_indices = self._edge_quad_indices.to(device)
128
128
 
129
- return args
130
-
131
129
  def cell_arg_value(self, device):
132
130
  args = self.CellArg()
131
+ self.fill_cell_arg(args, device)
132
+ return args
133
133
 
134
- args.topology = self._cell_topo_arg_value(device)
134
+ def fill_cell_arg(self, args: "Quadmesh.CellArg", device):
135
+ self.fill_cell_topo_arg(args.topology, device)
135
136
  args.positions = self.positions.to(device)
136
137
 
137
- return args
138
-
139
138
  def side_arg_value(self, device):
140
139
  args = self.SideArg()
140
+ self.fill_side_arg(args, device)
141
+ return args
141
142
 
142
- args.topology = self._side_topo_arg_value(device)
143
+ def fill_side_arg(self, args: "Quadmesh.SideArg", device):
144
+ self.fill_side_topo_arg(args.topology, device)
143
145
  args.positions = self.positions.to(device)
144
146
 
145
- return args
146
-
147
147
  @cached_arg_value
148
148
  def side_index_arg_value(self, device) -> SideIndexArg:
149
149
  args = self.SideIndexArg()
150
+ self.fill_side_index_arg(args, device)
151
+ return args
150
152
 
153
+ def fill_side_index_arg(self, args: "SideIndexArg", device):
151
154
  args.boundary_edge_indices = self._boundary_edge_indices.to(device)
152
155
 
153
- return args
154
-
155
156
  @wp.func
156
157
  def _edge_to_quad_coords(
157
158
  args: QuadmeshSideArg, side_index: ElementIndex, quad_index: ElementIndex, side_coords: Coords
@@ -400,28 +401,8 @@ class Quadmesh(Geometry):
400
401
  else:
401
402
  boundary_mask[edge_index] = 0
402
403
 
403
-
404
- @wp.struct
405
- class Quadmesh2DCellArg:
406
- topology: QuadmeshCellArg
407
- positions: wp.array(dtype=wp.vec2)
408
-
409
-
410
- @wp.struct
411
- class Quadmesh2DSideArg:
412
- topology: QuadmeshSideArg
413
- positions: wp.array(dtype=wp.vec2)
414
-
415
-
416
- class Quadmesh2D(Quadmesh):
417
- """Two-dimensional quadrilateral mesh"""
418
-
419
- dimension = 2
420
- CellArg = Quadmesh2DCellArg
421
- SideArg = Quadmesh2DSideArg
422
-
423
404
  @wp.func
424
- def cell_position(args: CellArg, s: Sample):
405
+ def cell_position(args: Any, s: Sample):
425
406
  quad_idx = args.topology.quad_vertex_indices[s.element_index]
426
407
 
427
408
  w_p = s.element_coords
@@ -440,7 +421,7 @@ class Quadmesh2D(Quadmesh):
440
421
  )
441
422
 
442
423
  @wp.func
443
- def cell_deformation_gradient(cell_arg: CellArg, s: Sample):
424
+ def cell_deformation_gradient(cell_arg: Any, s: Sample):
444
425
  """Deformation gradient at `coords`"""
445
426
  quad_idx = cell_arg.topology.quad_vertex_indices[s.element_index]
446
427
 
@@ -455,46 +436,91 @@ class Quadmesh2D(Quadmesh):
455
436
  )
456
437
 
457
438
  @wp.func
458
- def side_position(args: SideArg, s: Sample):
439
+ def side_position(args: Any, s: Sample):
459
440
  edge_idx = args.topology.edge_vertex_indices[s.element_index]
460
441
  return (1.0 - s.element_coords[0]) * args.positions[edge_idx[0]] + s.element_coords[0] * args.positions[
461
442
  edge_idx[1]
462
443
  ]
463
444
 
464
445
  @wp.func
465
- def side_deformation_gradient(args: SideArg, s: Sample):
446
+ def side_deformation_gradient(args: Any, s: Sample):
466
447
  edge_idx = args.topology.edge_vertex_indices[s.element_index]
467
448
  v0 = args.positions[edge_idx[0]]
468
449
  v1 = args.positions[edge_idx[1]]
469
450
  return v1 - v0
470
451
 
471
452
  @wp.func
472
- def side_inner_cell_index(arg: SideArg, side_index: ElementIndex):
453
+ def side_closest_point(args: Any, side_index: ElementIndex, pos: Any):
454
+ edge_idx = args.topology.edge_vertex_indices[side_index]
455
+ p0 = args.positions[edge_idx[0]]
456
+
457
+ q = pos - p0
458
+ e = args.positions[edge_idx[1]] - p0
459
+
460
+ dist, t = project_on_seg_at_origin(q, e, wp.lengh_sq(e))
461
+ return Coords(t, 0.0, 0.0), dist
462
+
463
+ @wp.func
464
+ def side_inner_cell_index(arg: Any, side_index: ElementIndex):
473
465
  return arg.topology.edge_quad_indices[side_index][0]
474
466
 
475
467
  @wp.func
476
- def side_outer_cell_index(arg: SideArg, side_index: ElementIndex):
468
+ def side_outer_cell_index(arg: Any, side_index: ElementIndex):
477
469
  return arg.topology.edge_quad_indices[side_index][1]
478
470
 
479
471
  @wp.func
480
- def side_inner_cell_coords(args: SideArg, side_index: ElementIndex, side_coords: Coords):
481
- inner_cell_index = Quadmesh2D.side_inner_cell_index(args, side_index)
472
+ def side_inner_cell_coords(args: Any, side_index: ElementIndex, side_coords: Coords):
473
+ inner_cell_index = Quadmesh3D.side_inner_cell_index(args, side_index)
482
474
  return Quadmesh._edge_to_quad_coords(args.topology, side_index, inner_cell_index, side_coords)
483
475
 
484
476
  @wp.func
485
- def side_outer_cell_coords(args: SideArg, side_index: ElementIndex, side_coords: Coords):
486
- outer_cell_index = Quadmesh2D.side_outer_cell_index(args, side_index)
477
+ def side_outer_cell_coords(args: Any, side_index: ElementIndex, side_coords: Coords):
478
+ outer_cell_index = Quadmesh3D.side_outer_cell_index(args, side_index)
487
479
  return Quadmesh._edge_to_quad_coords(args.topology, side_index, outer_cell_index, side_coords)
488
480
 
489
481
  @wp.func
490
482
  def side_from_cell_coords(
491
- args: SideArg,
483
+ args: Any,
492
484
  side_index: ElementIndex,
493
485
  quad_index: ElementIndex,
494
486
  quad_coords: Coords,
495
487
  ):
496
488
  return Quadmesh._quad_to_edge_coords(args.topology, side_index, quad_index, quad_coords)
497
489
 
490
+ @wp.func
491
+ def cell_bvh_id(cell_arg: Any):
492
+ return cell_arg.topology.quad_bvh
493
+
494
+ @wp.func
495
+ def cell_bounds(cell_arg: Any, cell_index: ElementIndex):
496
+ vidx = cell_arg.topology.quad_vertex_indices[cell_index]
497
+ p0 = cell_arg.positions[vidx[0]]
498
+ p1 = cell_arg.positions[vidx[1]]
499
+ p2 = cell_arg.positions[vidx[2]]
500
+ p3 = cell_arg.positions[vidx[3]]
501
+
502
+ return wp.min(wp.min(p0, p1), wp.min(p2, p3)), wp.max(wp.max(p0, p1), wp.max(p2, p3))
503
+
504
+
505
+ @wp.struct
506
+ class Quadmesh2DCellArg:
507
+ topology: QuadmeshCellArg
508
+ positions: wp.array(dtype=wp.vec2)
509
+
510
+
511
+ @wp.struct
512
+ class Quadmesh2DSideArg:
513
+ topology: QuadmeshSideArg
514
+ positions: wp.array(dtype=wp.vec2)
515
+
516
+
517
+ class Quadmesh2D(Quadmesh):
518
+ """Two-dimensional quadrilateral mesh"""
519
+
520
+ dimension = 2
521
+ CellArg = Quadmesh2DCellArg
522
+ SideArg = Quadmesh2DSideArg
523
+
498
524
  @wp.func
499
525
  def side_to_cell_arg(side_arg: SideArg):
500
526
  return Quadmesh2DCellArg(side_arg.topology.cell_arg, side_arg.positions)
@@ -522,7 +548,7 @@ class Quadmesh2D(Quadmesh):
522
548
 
523
549
  edge_center = 0.5 * (v1 + v0)
524
550
  edge_vec = v1 - v0
525
- edge_normal = wp.vec2(-edge_vec[1], edge_vec[0])
551
+ edge_normal = Geometry._element_normal(edge_vec)
526
552
 
527
553
  # if edge normal points toward first triangle centroid, flip indices
528
554
  if wp.dot(quad_centroid - edge_center, edge_normal) > 0.0:
@@ -548,81 +574,6 @@ class Quadmesh3D(Quadmesh):
548
574
  CellArg = Quadmesh3DCellArg
549
575
  SideArg = Quadmesh3DSideArg
550
576
 
551
- @wp.func
552
- def cell_position(args: CellArg, s: Sample):
553
- quad_idx = args.topology.quad_vertex_indices[s.element_index]
554
-
555
- w_p = s.element_coords
556
- w_m = Coords(1.0) - s.element_coords
557
-
558
- # 0 : m m
559
- # 1 : p m
560
- # 2 : p p
561
- # 3 : m p
562
-
563
- return (
564
- w_m[0] * w_m[1] * args.positions[quad_idx[0]]
565
- + w_p[0] * w_m[1] * args.positions[quad_idx[1]]
566
- + w_p[0] * w_p[1] * args.positions[quad_idx[2]]
567
- + w_m[0] * w_p[1] * args.positions[quad_idx[3]]
568
- )
569
-
570
- @wp.func
571
- def cell_deformation_gradient(cell_arg: CellArg, s: Sample):
572
- """Deformation gradient at `coords`"""
573
- quad_idx = cell_arg.topology.quad_vertex_indices[s.element_index]
574
-
575
- w_p = s.element_coords
576
- w_m = Coords(1.0) - s.element_coords
577
-
578
- return (
579
- wp.outer(cell_arg.positions[quad_idx[0]], wp.vec2(-w_m[1], -w_m[0]))
580
- + wp.outer(cell_arg.positions[quad_idx[1]], wp.vec2(w_m[1], -w_p[0]))
581
- + wp.outer(cell_arg.positions[quad_idx[2]], wp.vec2(w_p[1], w_p[0]))
582
- + wp.outer(cell_arg.positions[quad_idx[3]], wp.vec2(-w_p[1], w_m[0]))
583
- )
584
-
585
- @wp.func
586
- def side_position(args: SideArg, s: Sample):
587
- edge_idx = args.topology.edge_vertex_indices[s.element_index]
588
- return (1.0 - s.element_coords[0]) * args.positions[edge_idx[0]] + s.element_coords[0] * args.positions[
589
- edge_idx[1]
590
- ]
591
-
592
- @wp.func
593
- def side_deformation_gradient(args: SideArg, s: Sample):
594
- edge_idx = args.topology.edge_vertex_indices[s.element_index]
595
- v0 = args.positions[edge_idx[0]]
596
- v1 = args.positions[edge_idx[1]]
597
- return v1 - v0
598
-
599
- @wp.func
600
- def side_inner_cell_index(arg: SideArg, side_index: ElementIndex):
601
- return arg.topology.edge_quad_indices[side_index][0]
602
-
603
- @wp.func
604
- def side_outer_cell_index(arg: SideArg, side_index: ElementIndex):
605
- return arg.topology.edge_quad_indices[side_index][1]
606
-
607
- @wp.func
608
- def side_inner_cell_coords(args: SideArg, side_index: ElementIndex, side_coords: Coords):
609
- inner_cell_index = Quadmesh3D.side_inner_cell_index(args, side_index)
610
- return Quadmesh._edge_to_quad_coords(args.topology, side_index, inner_cell_index, side_coords)
611
-
612
- @wp.func
613
- def side_outer_cell_coords(args: SideArg, side_index: ElementIndex, side_coords: Coords):
614
- outer_cell_index = Quadmesh3D.side_outer_cell_index(args, side_index)
615
- return Quadmesh._edge_to_quad_coords(args.topology, side_index, outer_cell_index, side_coords)
616
-
617
- @wp.func
618
- def side_from_cell_coords(
619
- args: SideArg,
620
- side_index: ElementIndex,
621
- quad_index: ElementIndex,
622
- quad_coords: Coords,
623
- ):
624
- return Quadmesh._quad_to_edge_coords(args.topology, side_index, quad_index, quad_coords)
625
-
626
577
  @wp.func
627
578
  def side_to_cell_arg(side_arg: SideArg):
628
579
  return Quadmesh3DCellArg(side_arg.topology.cell_arg, side_arg.positions)