warp-lang 1.4.2__py3-none-win_amd64.whl → 1.5.0__py3-none-win_amd64.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 (158) hide show
  1. warp/__init__.py +4 -0
  2. warp/autograd.py +43 -8
  3. warp/bin/warp-clang.dll +0 -0
  4. warp/bin/warp.dll +0 -0
  5. warp/build.py +21 -2
  6. warp/build_dll.py +23 -6
  7. warp/builtins.py +1783 -2
  8. warp/codegen.py +177 -45
  9. warp/config.py +2 -2
  10. warp/context.py +321 -73
  11. warp/examples/assets/pixel.jpg +0 -0
  12. warp/examples/benchmarks/benchmark_cloth_paddle.py +86 -0
  13. warp/examples/benchmarks/benchmark_gemm.py +121 -0
  14. warp/examples/benchmarks/benchmark_interop_paddle.py +158 -0
  15. warp/examples/benchmarks/benchmark_tile.py +179 -0
  16. warp/examples/fem/example_adaptive_grid.py +37 -10
  17. warp/examples/fem/example_apic_fluid.py +3 -2
  18. warp/examples/fem/example_convection_diffusion_dg.py +4 -5
  19. warp/examples/fem/example_deformed_geometry.py +1 -1
  20. warp/examples/fem/example_diffusion_3d.py +47 -4
  21. warp/examples/fem/example_distortion_energy.py +220 -0
  22. warp/examples/fem/example_magnetostatics.py +127 -85
  23. warp/examples/fem/example_nonconforming_contact.py +5 -5
  24. warp/examples/fem/example_stokes.py +3 -1
  25. warp/examples/fem/example_streamlines.py +12 -19
  26. warp/examples/fem/utils.py +38 -15
  27. warp/examples/sim/example_cloth.py +2 -25
  28. warp/examples/sim/example_quadruped.py +2 -1
  29. warp/examples/tile/example_tile_convolution.py +58 -0
  30. warp/examples/tile/example_tile_fft.py +47 -0
  31. warp/examples/tile/example_tile_filtering.py +105 -0
  32. warp/examples/tile/example_tile_matmul.py +79 -0
  33. warp/examples/tile/example_tile_mlp.py +375 -0
  34. warp/fem/__init__.py +8 -0
  35. warp/fem/cache.py +16 -12
  36. warp/fem/dirichlet.py +1 -1
  37. warp/fem/domain.py +44 -1
  38. warp/fem/field/__init__.py +1 -2
  39. warp/fem/field/field.py +31 -19
  40. warp/fem/field/nodal_field.py +101 -49
  41. warp/fem/field/virtual.py +794 -0
  42. warp/fem/geometry/__init__.py +2 -2
  43. warp/fem/geometry/deformed_geometry.py +3 -105
  44. warp/fem/geometry/element.py +13 -0
  45. warp/fem/geometry/geometry.py +165 -5
  46. warp/fem/geometry/grid_2d.py +3 -6
  47. warp/fem/geometry/grid_3d.py +31 -28
  48. warp/fem/geometry/hexmesh.py +3 -46
  49. warp/fem/geometry/nanogrid.py +3 -2
  50. warp/fem/geometry/{quadmesh_2d.py → quadmesh.py} +280 -159
  51. warp/fem/geometry/tetmesh.py +2 -43
  52. warp/fem/geometry/{trimesh_2d.py → trimesh.py} +354 -186
  53. warp/fem/integrate.py +683 -261
  54. warp/fem/linalg.py +404 -0
  55. warp/fem/operator.py +101 -18
  56. warp/fem/polynomial.py +5 -5
  57. warp/fem/quadrature/quadrature.py +45 -21
  58. warp/fem/space/__init__.py +45 -11
  59. warp/fem/space/basis_function_space.py +451 -0
  60. warp/fem/space/basis_space.py +58 -11
  61. warp/fem/space/function_space.py +146 -5
  62. warp/fem/space/grid_2d_function_space.py +80 -66
  63. warp/fem/space/grid_3d_function_space.py +113 -68
  64. warp/fem/space/hexmesh_function_space.py +96 -108
  65. warp/fem/space/nanogrid_function_space.py +62 -110
  66. warp/fem/space/quadmesh_function_space.py +208 -0
  67. warp/fem/space/shape/__init__.py +45 -7
  68. warp/fem/space/shape/cube_shape_function.py +328 -54
  69. warp/fem/space/shape/shape_function.py +10 -1
  70. warp/fem/space/shape/square_shape_function.py +328 -60
  71. warp/fem/space/shape/tet_shape_function.py +269 -19
  72. warp/fem/space/shape/triangle_shape_function.py +238 -19
  73. warp/fem/space/tetmesh_function_space.py +69 -37
  74. warp/fem/space/topology.py +38 -0
  75. warp/fem/space/trimesh_function_space.py +179 -0
  76. warp/fem/utils.py +6 -331
  77. warp/jax_experimental.py +3 -1
  78. warp/native/array.h +15 -0
  79. warp/native/builtin.h +66 -26
  80. warp/native/bvh.h +4 -0
  81. warp/native/coloring.cpp +600 -0
  82. warp/native/cuda_util.cpp +14 -0
  83. warp/native/cuda_util.h +2 -1
  84. warp/native/fabric.h +8 -0
  85. warp/native/hashgrid.h +4 -0
  86. warp/native/marching.cu +8 -0
  87. warp/native/mat.h +14 -3
  88. warp/native/mathdx.cpp +59 -0
  89. warp/native/mesh.h +4 -0
  90. warp/native/range.h +13 -1
  91. warp/native/reduce.cpp +9 -1
  92. warp/native/reduce.cu +7 -0
  93. warp/native/runlength_encode.cpp +9 -1
  94. warp/native/runlength_encode.cu +7 -1
  95. warp/native/scan.cpp +8 -0
  96. warp/native/scan.cu +8 -0
  97. warp/native/scan.h +8 -1
  98. warp/native/sparse.cpp +8 -0
  99. warp/native/sparse.cu +8 -0
  100. warp/native/temp_buffer.h +7 -0
  101. warp/native/tile.h +1857 -0
  102. warp/native/tile_gemm.h +341 -0
  103. warp/native/tile_reduce.h +210 -0
  104. warp/native/volume_builder.cu +8 -0
  105. warp/native/volume_builder.h +8 -0
  106. warp/native/warp.cpp +10 -2
  107. warp/native/warp.cu +369 -15
  108. warp/native/warp.h +12 -2
  109. warp/optim/adam.py +39 -4
  110. warp/paddle.py +29 -12
  111. warp/render/render_opengl.py +137 -65
  112. warp/sim/graph_coloring.py +292 -0
  113. warp/sim/integrator_euler.py +4 -2
  114. warp/sim/integrator_featherstone.py +115 -44
  115. warp/sim/integrator_vbd.py +6 -0
  116. warp/sim/model.py +88 -15
  117. warp/stubs.py +569 -4
  118. warp/tape.py +12 -7
  119. warp/tests/assets/pixel.npy +0 -0
  120. warp/tests/aux_test_instancing_gc.py +18 -0
  121. warp/tests/test_array.py +39 -0
  122. warp/tests/test_codegen.py +81 -1
  123. warp/tests/test_codegen_instancing.py +30 -0
  124. warp/tests/test_collision.py +110 -0
  125. warp/tests/test_coloring.py +241 -0
  126. warp/tests/test_context.py +34 -0
  127. warp/tests/test_examples.py +18 -4
  128. warp/tests/test_fem.py +453 -113
  129. warp/tests/test_func.py +13 -0
  130. warp/tests/test_generics.py +52 -0
  131. warp/tests/test_iter.py +68 -0
  132. warp/tests/test_mat_scalar_ops.py +1 -1
  133. warp/tests/test_mesh_query_point.py +1 -1
  134. warp/tests/test_module_hashing.py +23 -0
  135. warp/tests/test_paddle.py +27 -87
  136. warp/tests/test_print.py +56 -1
  137. warp/tests/test_spatial.py +1 -1
  138. warp/tests/test_tile.py +700 -0
  139. warp/tests/test_tile_mathdx.py +144 -0
  140. warp/tests/test_tile_mlp.py +383 -0
  141. warp/tests/test_tile_reduce.py +374 -0
  142. warp/tests/test_tile_shared_memory.py +190 -0
  143. warp/tests/test_vbd.py +12 -20
  144. warp/tests/test_volume.py +43 -0
  145. warp/tests/unittest_suites.py +19 -2
  146. warp/tests/unittest_utils.py +4 -0
  147. warp/types.py +338 -72
  148. warp/utils.py +22 -1
  149. {warp_lang-1.4.2.dist-info → warp_lang-1.5.0.dist-info}/METADATA +33 -7
  150. {warp_lang-1.4.2.dist-info → warp_lang-1.5.0.dist-info}/RECORD +153 -126
  151. {warp_lang-1.4.2.dist-info → warp_lang-1.5.0.dist-info}/WHEEL +1 -1
  152. warp/fem/field/test.py +0 -180
  153. warp/fem/field/trial.py +0 -183
  154. warp/fem/space/collocated_function_space.py +0 -102
  155. warp/fem/space/quadmesh_2d_function_space.py +0 -261
  156. warp/fem/space/trimesh_2d_function_space.py +0 -153
  157. {warp_lang-1.4.2.dist-info → warp_lang-1.5.0.dist-info}/LICENSE.md +0 -0
  158. {warp_lang-1.4.2.dist-info → warp_lang-1.5.0.dist-info}/top_level.txt +0 -0
@@ -7,18 +7,15 @@ from warp.fem.cache import (
7
7
  borrow_temporary_like,
8
8
  cached_arg_value,
9
9
  )
10
- from warp.fem.types import OUTSIDE, Coords, ElementIndex, Sample, make_free_sample
10
+ from warp.fem.types import OUTSIDE, Coords, ElementIndex, Sample
11
11
 
12
12
  from .element import LinearEdge, Square
13
13
  from .geometry import Geometry
14
14
 
15
- # from .closest_point import project_on_tet_at_origin
16
-
17
15
 
18
16
  @wp.struct
19
- class Quadmesh2DCellArg:
17
+ class QuadmeshCellArg:
20
18
  quad_vertex_indices: wp.array2d(dtype=int)
21
- positions: wp.array(dtype=wp.vec2)
22
19
 
23
20
  # for neighbor cell lookup
24
21
  vertex_quad_offsets: wp.array(dtype=int)
@@ -26,26 +23,24 @@ class Quadmesh2DCellArg:
26
23
 
27
24
 
28
25
  @wp.struct
29
- class Quadmesh2DSideArg:
30
- cell_arg: Quadmesh2DCellArg
26
+ class QuadmeshSideArg:
27
+ cell_arg: QuadmeshCellArg
31
28
  edge_vertex_indices: wp.array(dtype=wp.vec2i)
32
29
  edge_quad_indices: wp.array(dtype=wp.vec2i)
33
30
 
34
31
 
35
- class Quadmesh2D(Geometry):
36
- """Two-dimensional quadrilateral mesh geometry"""
37
-
38
- dimension = 2
32
+ class Quadmesh(Geometry):
33
+ """Quadrilateral mesh geometry"""
39
34
 
40
35
  def __init__(
41
36
  self, quad_vertex_indices: wp.array, positions: wp.array, temporary_store: Optional[TemporaryStore] = None
42
37
  ):
43
38
  """
44
- Constructs a two-dimensional quadrilateral mesh.
39
+ Constructs a D-dimensional quadrilateral mesh.
45
40
 
46
41
  Args:
47
42
  quad_vertex_indices: warp array of shape (num_tris, 4) containing vertex indices for each quad, in counter-clockwise order
48
- positions: warp array of shape (num_vertices, 2) containing 2d position for each vertex
43
+ positions: warp array of shape (num_vertices, D) containing the position of each vertex
49
44
  temporary_store: shared pool from which to allocate temporary arrays
50
45
  """
51
46
 
@@ -58,6 +53,16 @@ class Quadmesh2D(Geometry):
58
53
  self._vertex_quad_indices: wp.array = None
59
54
  self._build_topology(temporary_store)
60
55
 
56
+ # Flip edges so that normals point away from inner cell
57
+ wp.launch(
58
+ kernel=self._orient_edges,
59
+ device=positions.device,
60
+ dim=self.side_count(),
61
+ inputs=[self._edge_vertex_indices, self._edge_quad_indices, self.quad_vertex_indices, self.positions],
62
+ )
63
+
64
+ self._make_default_dependent_implementations()
65
+
61
66
  def cell_count(self):
62
67
  return self.quad_vertex_indices.shape[0]
63
68
 
@@ -84,71 +89,45 @@ class Quadmesh2D(Geometry):
84
89
  def edge_vertex_indices(self) -> wp.array:
85
90
  return self._edge_vertex_indices
86
91
 
87
- CellArg = Quadmesh2DCellArg
88
- SideArg = Quadmesh2DSideArg
89
-
90
92
  @wp.struct
91
93
  class SideIndexArg:
92
94
  boundary_edge_indices: wp.array(dtype=int)
93
95
 
94
- # Geometry device interface
95
-
96
96
  @cached_arg_value
97
- def cell_arg_value(self, device) -> CellArg:
98
- args = self.CellArg()
97
+ def _cell_topo_arg_value(self, device):
98
+ args = QuadmeshCellArg()
99
99
 
100
100
  args.quad_vertex_indices = self.quad_vertex_indices.to(device)
101
- args.positions = self.positions.to(device)
102
101
  args.vertex_quad_offsets = self._vertex_quad_offsets.to(device)
103
102
  args.vertex_quad_indices = self._vertex_quad_indices.to(device)
104
103
 
105
104
  return args
106
105
 
107
- @wp.func
108
- def cell_position(args: CellArg, s: Sample):
109
- quad_idx = args.quad_vertex_indices[s.element_index]
110
-
111
- w_p = s.element_coords
112
- w_m = Coords(1.0) - s.element_coords
106
+ @cached_arg_value
107
+ def _side_topo_arg_value(self, device):
108
+ args = QuadmeshSideArg()
113
109
 
114
- # 0 : m m
115
- # 1 : p m
116
- # 2 : p p
117
- # 3 : m p
110
+ args.cell_arg = self._cell_topo_arg_value(device)
111
+ args.edge_vertex_indices = self._edge_vertex_indices.to(device)
112
+ args.edge_quad_indices = self._edge_quad_indices.to(device)
118
113
 
119
- return (
120
- w_m[0] * w_m[1] * args.positions[quad_idx[0]]
121
- + w_p[0] * w_m[1] * args.positions[quad_idx[1]]
122
- + w_p[0] * w_p[1] * args.positions[quad_idx[2]]
123
- + w_m[0] * w_p[1] * args.positions[quad_idx[3]]
124
- )
114
+ return args
125
115
 
126
- @wp.func
127
- def cell_deformation_gradient(cell_arg: CellArg, s: Sample):
128
- """Deformation gradient at `coords`"""
129
- quad_idx = cell_arg.quad_vertex_indices[s.element_index]
116
+ def cell_arg_value(self, device):
117
+ args = self.CellArg()
130
118
 
131
- w_p = s.element_coords
132
- w_m = Coords(1.0) - s.element_coords
119
+ args.topology = self._cell_topo_arg_value(device)
120
+ args.positions = self.positions.to(device)
133
121
 
134
- return (
135
- wp.outer(cell_arg.positions[quad_idx[0]], wp.vec2(-w_m[1], -w_m[0]))
136
- + wp.outer(cell_arg.positions[quad_idx[1]], wp.vec2(w_m[1], -w_p[0]))
137
- + wp.outer(cell_arg.positions[quad_idx[2]], wp.vec2(w_p[1], w_p[0]))
138
- + wp.outer(cell_arg.positions[quad_idx[3]], wp.vec2(-w_p[1], w_m[0]))
139
- )
122
+ return args
140
123
 
141
- @wp.func
142
- def cell_inverse_deformation_gradient(cell_arg: CellArg, s: Sample):
143
- return wp.inverse(Quadmesh2D.cell_deformation_gradient(cell_arg, s))
124
+ def side_arg_value(self, device):
125
+ args = self.SideArg()
144
126
 
145
- @wp.func
146
- def cell_measure(args: CellArg, s: Sample):
147
- return wp.abs(wp.determinant(Quadmesh2D.cell_deformation_gradient(args, s)))
127
+ args.topology = self._side_topo_arg_value(device)
128
+ args.positions = self.positions.to(device)
148
129
 
149
- @wp.func
150
- def cell_normal(args: CellArg, s: Sample):
151
- return wp.vec2(0.0)
130
+ return args
152
131
 
153
132
  @cached_arg_value
154
133
  def side_index_arg_value(self, device) -> SideIndexArg:
@@ -159,84 +138,9 @@ class Quadmesh2D(Geometry):
159
138
  return args
160
139
 
161
140
  @wp.func
162
- def boundary_side_index(args: SideIndexArg, boundary_side_index: int):
163
- """Boundary side to side index"""
164
-
165
- return args.boundary_edge_indices[boundary_side_index]
166
-
167
- @cached_arg_value
168
- def side_arg_value(self, device) -> CellArg:
169
- args = self.SideArg()
170
-
171
- args.cell_arg = self.cell_arg_value(device)
172
- args.edge_vertex_indices = self._edge_vertex_indices.to(device)
173
- args.edge_quad_indices = self._edge_quad_indices.to(device)
174
-
175
- return args
176
-
177
- @wp.func
178
- def side_position(args: SideArg, s: Sample):
179
- edge_idx = args.edge_vertex_indices[s.element_index]
180
- return (1.0 - s.element_coords[0]) * args.cell_arg.positions[edge_idx[0]] + s.element_coords[
181
- 0
182
- ] * args.cell_arg.positions[edge_idx[1]]
183
-
184
- @wp.func
185
- def side_deformation_gradient(args: SideArg, s: Sample):
186
- edge_idx = args.edge_vertex_indices[s.element_index]
187
- v0 = args.cell_arg.positions[edge_idx[0]]
188
- v1 = args.cell_arg.positions[edge_idx[1]]
189
- return v1 - v0
190
-
191
- @wp.func
192
- def side_inner_inverse_deformation_gradient(args: SideArg, s: Sample):
193
- cell_index = Quadmesh2D.side_inner_cell_index(args, s.element_index)
194
- cell_coords = Quadmesh2D.side_inner_cell_coords(args, s.element_index, s.element_coords)
195
- return Quadmesh2D.cell_inverse_deformation_gradient(args.cell_arg, make_free_sample(cell_index, cell_coords))
196
-
197
- @wp.func
198
- def side_outer_inverse_deformation_gradient(args: SideArg, s: Sample):
199
- cell_index = Quadmesh2D.side_outer_cell_index(args, s.element_index)
200
- cell_coords = Quadmesh2D.side_outer_cell_coords(args, s.element_index, s.element_coords)
201
- return Quadmesh2D.cell_inverse_deformation_gradient(args.cell_arg, make_free_sample(cell_index, cell_coords))
202
-
203
- @wp.func
204
- def side_measure(args: SideArg, s: Sample):
205
- edge_idx = args.edge_vertex_indices[s.element_index]
206
- v0 = args.cell_arg.positions[edge_idx[0]]
207
- v1 = args.cell_arg.positions[edge_idx[1]]
208
- return wp.length(v1 - v0)
209
-
210
- @wp.func
211
- def side_measure_ratio(args: SideArg, s: Sample):
212
- inner = Quadmesh2D.side_inner_cell_index(args, s.element_index)
213
- outer = Quadmesh2D.side_outer_cell_index(args, s.element_index)
214
- inner_coords = Quadmesh2D.side_inner_cell_coords(args, s.element_index, s.element_coords)
215
- outer_coords = Quadmesh2D.side_outer_cell_coords(args, s.element_index, s.element_coords)
216
- return Quadmesh2D.side_measure(args, s) / wp.min(
217
- Quadmesh2D.cell_measure(args.cell_arg, make_free_sample(inner, inner_coords)),
218
- Quadmesh2D.cell_measure(args.cell_arg, make_free_sample(outer, outer_coords)),
219
- )
220
-
221
- @wp.func
222
- def side_normal(args: SideArg, s: Sample):
223
- edge_idx = args.edge_vertex_indices[s.element_index]
224
- v0 = args.cell_arg.positions[edge_idx[0]]
225
- v1 = args.cell_arg.positions[edge_idx[1]]
226
- e = v1 - v0
227
-
228
- return wp.normalize(wp.vec2(-e[1], e[0]))
229
-
230
- @wp.func
231
- def side_inner_cell_index(arg: SideArg, side_index: ElementIndex):
232
- return arg.edge_quad_indices[side_index][0]
233
-
234
- @wp.func
235
- def side_outer_cell_index(arg: SideArg, side_index: ElementIndex):
236
- return arg.edge_quad_indices[side_index][1]
237
-
238
- @wp.func
239
- def edge_to_quad_coords(args: SideArg, side_index: ElementIndex, quad_index: ElementIndex, side_coords: Coords):
141
+ def _edge_to_quad_coords(
142
+ args: QuadmeshSideArg, side_index: ElementIndex, quad_index: ElementIndex, side_coords: Coords
143
+ ):
240
144
  edge_vidx = args.edge_vertex_indices[side_index]
241
145
  quad_vidx = args.cell_arg.quad_vertex_indices[quad_index]
242
146
 
@@ -255,18 +159,8 @@ class Quadmesh2D(Geometry):
255
159
  return wp.select(ve == quad_vidx[0], Coords(s, 1.0, 0.0), Coords(0.0, 1.0 - s, 0.0))
256
160
 
257
161
  @wp.func
258
- def side_inner_cell_coords(args: SideArg, side_index: ElementIndex, side_coords: Coords):
259
- inner_cell_index = Quadmesh2D.side_inner_cell_index(args, side_index)
260
- return Quadmesh2D.edge_to_quad_coords(args, side_index, inner_cell_index, side_coords)
261
-
262
- @wp.func
263
- def side_outer_cell_coords(args: SideArg, side_index: ElementIndex, side_coords: Coords):
264
- outer_cell_index = Quadmesh2D.side_outer_cell_index(args, side_index)
265
- return Quadmesh2D.edge_to_quad_coords(args, side_index, outer_cell_index, side_coords)
266
-
267
- @wp.func
268
- def side_from_cell_coords(
269
- args: SideArg,
162
+ def _quad_to_edge_coords(
163
+ args: QuadmeshSideArg,
270
164
  side_index: ElementIndex,
271
165
  quad_index: ElementIndex,
272
166
  quad_coords: Coords,
@@ -295,8 +189,10 @@ class Quadmesh2D(Geometry):
295
189
  return wp.select(oc == 0.0, Coords(OUTSIDE), Coords(ec, 0.0, 0.0))
296
190
 
297
191
  @wp.func
298
- def side_to_cell_arg(side_arg: SideArg):
299
- return side_arg.cell_arg
192
+ def boundary_side_index(args: SideIndexArg, boundary_side_index: int):
193
+ """Boundary side to side index"""
194
+
195
+ return args.boundary_edge_indices[boundary_side_index]
300
196
 
301
197
  def _build_topology(self, temporary_store: TemporaryStore):
302
198
  from warp.fem.utils import compress_node_indices, host_read_at_index, masked_indices
@@ -384,14 +280,6 @@ class Quadmesh2D(Geometry):
384
280
  vertex_edge_ends.release()
385
281
  vertex_edge_quads.release()
386
282
 
387
- # Flip normals if necessary
388
- wp.launch(
389
- kernel=Quadmesh2D._flip_edge_normals,
390
- device=device,
391
- dim=self.side_count(),
392
- inputs=[self._edge_vertex_indices, self._edge_quad_indices, self.quad_vertex_indices, self.positions],
393
- )
394
-
395
283
  boundary_edge_indices, _ = masked_indices(boundary_mask.array, temporary_store=temporary_store)
396
284
  self._boundary_edge_indices = boundary_edge_indices.detach()
397
285
 
@@ -497,8 +385,107 @@ class Quadmesh2D(Geometry):
497
385
  else:
498
386
  boundary_mask[edge_index] = 0
499
387
 
388
+
389
+ @wp.struct
390
+ class Quadmesh2DCellArg:
391
+ topology: QuadmeshCellArg
392
+ positions: wp.array(dtype=wp.vec2)
393
+
394
+
395
+ @wp.struct
396
+ class Quadmesh2DSideArg:
397
+ topology: QuadmeshSideArg
398
+ positions: wp.array(dtype=wp.vec2)
399
+
400
+
401
+ class Quadmesh2D(Quadmesh):
402
+ """Two-dimensional quadrilateral mesh"""
403
+
404
+ dimension = 2
405
+ CellArg = Quadmesh2DCellArg
406
+ SideArg = Quadmesh2DSideArg
407
+
408
+ @wp.func
409
+ def cell_position(args: CellArg, s: Sample):
410
+ quad_idx = args.topology.quad_vertex_indices[s.element_index]
411
+
412
+ w_p = s.element_coords
413
+ w_m = Coords(1.0) - s.element_coords
414
+
415
+ # 0 : m m
416
+ # 1 : p m
417
+ # 2 : p p
418
+ # 3 : m p
419
+
420
+ return (
421
+ w_m[0] * w_m[1] * args.positions[quad_idx[0]]
422
+ + w_p[0] * w_m[1] * args.positions[quad_idx[1]]
423
+ + w_p[0] * w_p[1] * args.positions[quad_idx[2]]
424
+ + w_m[0] * w_p[1] * args.positions[quad_idx[3]]
425
+ )
426
+
427
+ @wp.func
428
+ def cell_deformation_gradient(cell_arg: CellArg, s: Sample):
429
+ """Deformation gradient at `coords`"""
430
+ quad_idx = cell_arg.topology.quad_vertex_indices[s.element_index]
431
+
432
+ w_p = s.element_coords
433
+ w_m = Coords(1.0) - s.element_coords
434
+
435
+ return (
436
+ wp.outer(cell_arg.positions[quad_idx[0]], wp.vec2(-w_m[1], -w_m[0]))
437
+ + wp.outer(cell_arg.positions[quad_idx[1]], wp.vec2(w_m[1], -w_p[0]))
438
+ + wp.outer(cell_arg.positions[quad_idx[2]], wp.vec2(w_p[1], w_p[0]))
439
+ + wp.outer(cell_arg.positions[quad_idx[3]], wp.vec2(-w_p[1], w_m[0]))
440
+ )
441
+
442
+ @wp.func
443
+ def side_position(args: SideArg, s: Sample):
444
+ edge_idx = args.topology.edge_vertex_indices[s.element_index]
445
+ return (1.0 - s.element_coords[0]) * args.positions[edge_idx[0]] + s.element_coords[0] * args.positions[
446
+ edge_idx[1]
447
+ ]
448
+
449
+ @wp.func
450
+ def side_deformation_gradient(args: SideArg, s: Sample):
451
+ edge_idx = args.topology.edge_vertex_indices[s.element_index]
452
+ v0 = args.positions[edge_idx[0]]
453
+ v1 = args.positions[edge_idx[1]]
454
+ return v1 - v0
455
+
456
+ @wp.func
457
+ def side_inner_cell_index(arg: SideArg, side_index: ElementIndex):
458
+ return arg.topology.edge_quad_indices[side_index][0]
459
+
460
+ @wp.func
461
+ def side_outer_cell_index(arg: SideArg, side_index: ElementIndex):
462
+ return arg.topology.edge_quad_indices[side_index][1]
463
+
464
+ @wp.func
465
+ def side_inner_cell_coords(args: SideArg, side_index: ElementIndex, side_coords: Coords):
466
+ inner_cell_index = Quadmesh2D.side_inner_cell_index(args, side_index)
467
+ return Quadmesh._edge_to_quad_coords(args.topology, side_index, inner_cell_index, side_coords)
468
+
469
+ @wp.func
470
+ def side_outer_cell_coords(args: SideArg, side_index: ElementIndex, side_coords: Coords):
471
+ outer_cell_index = Quadmesh2D.side_outer_cell_index(args, side_index)
472
+ return Quadmesh._edge_to_quad_coords(args.topology, side_index, outer_cell_index, side_coords)
473
+
474
+ @wp.func
475
+ def side_from_cell_coords(
476
+ args: SideArg,
477
+ side_index: ElementIndex,
478
+ quad_index: ElementIndex,
479
+ quad_coords: Coords,
480
+ ):
481
+ return Quadmesh._quad_to_edge_coords(args.topology, side_index, quad_index, quad_coords)
482
+
483
+ @wp.func
484
+ def side_to_cell_arg(side_arg: SideArg):
485
+ return Quadmesh2DCellArg(side_arg.topology.cell_arg, side_arg.positions)
486
+
500
487
  @wp.kernel
501
- def _flip_edge_normals(
488
+ def _orient_edges(
502
489
  edge_vertex_indices: wp.array(dtype=wp.vec2i),
503
490
  edge_quad_indices: wp.array(dtype=wp.vec2i),
504
491
  quad_vertex_indices: wp.array2d(dtype=int),
@@ -525,3 +512,137 @@ class Quadmesh2D(Geometry):
525
512
  # if edge normal points toward first triangle centroid, flip indices
526
513
  if wp.dot(quad_centroid - edge_center, edge_normal) > 0.0:
527
514
  edge_vertex_indices[e] = wp.vec2i(edge_vidx[1], edge_vidx[0])
515
+
516
+
517
+ @wp.struct
518
+ class Quadmesh3DCellArg:
519
+ topology: QuadmeshCellArg
520
+ positions: wp.array(dtype=wp.vec3)
521
+
522
+
523
+ @wp.struct
524
+ class Quadmesh3DSideArg:
525
+ topology: QuadmeshSideArg
526
+ positions: wp.array(dtype=wp.vec3)
527
+
528
+
529
+ class Quadmesh3D(Quadmesh):
530
+ """Three-dimensional quadrilateral mesh"""
531
+
532
+ dimension = 3
533
+ CellArg = Quadmesh3DCellArg
534
+ SideArg = Quadmesh3DSideArg
535
+
536
+ @wp.func
537
+ def cell_position(args: CellArg, s: Sample):
538
+ quad_idx = args.topology.quad_vertex_indices[s.element_index]
539
+
540
+ w_p = s.element_coords
541
+ w_m = Coords(1.0) - s.element_coords
542
+
543
+ # 0 : m m
544
+ # 1 : p m
545
+ # 2 : p p
546
+ # 3 : m p
547
+
548
+ return (
549
+ w_m[0] * w_m[1] * args.positions[quad_idx[0]]
550
+ + w_p[0] * w_m[1] * args.positions[quad_idx[1]]
551
+ + w_p[0] * w_p[1] * args.positions[quad_idx[2]]
552
+ + w_m[0] * w_p[1] * args.positions[quad_idx[3]]
553
+ )
554
+
555
+ @wp.func
556
+ def cell_deformation_gradient(cell_arg: CellArg, s: Sample):
557
+ """Deformation gradient at `coords`"""
558
+ quad_idx = cell_arg.topology.quad_vertex_indices[s.element_index]
559
+
560
+ w_p = s.element_coords
561
+ w_m = Coords(1.0) - s.element_coords
562
+
563
+ return (
564
+ wp.outer(cell_arg.positions[quad_idx[0]], wp.vec2(-w_m[1], -w_m[0]))
565
+ + wp.outer(cell_arg.positions[quad_idx[1]], wp.vec2(w_m[1], -w_p[0]))
566
+ + wp.outer(cell_arg.positions[quad_idx[2]], wp.vec2(w_p[1], w_p[0]))
567
+ + wp.outer(cell_arg.positions[quad_idx[3]], wp.vec2(-w_p[1], w_m[0]))
568
+ )
569
+
570
+ @wp.func
571
+ def side_position(args: SideArg, s: Sample):
572
+ edge_idx = args.topology.edge_vertex_indices[s.element_index]
573
+ return (1.0 - s.element_coords[0]) * args.positions[edge_idx[0]] + s.element_coords[0] * args.positions[
574
+ edge_idx[1]
575
+ ]
576
+
577
+ @wp.func
578
+ def side_deformation_gradient(args: SideArg, s: Sample):
579
+ edge_idx = args.topology.edge_vertex_indices[s.element_index]
580
+ v0 = args.positions[edge_idx[0]]
581
+ v1 = args.positions[edge_idx[1]]
582
+ return v1 - v0
583
+
584
+ @wp.func
585
+ def side_inner_cell_index(arg: SideArg, side_index: ElementIndex):
586
+ return arg.topology.edge_quad_indices[side_index][0]
587
+
588
+ @wp.func
589
+ def side_outer_cell_index(arg: SideArg, side_index: ElementIndex):
590
+ return arg.topology.edge_quad_indices[side_index][1]
591
+
592
+ @wp.func
593
+ def side_inner_cell_coords(args: SideArg, side_index: ElementIndex, side_coords: Coords):
594
+ inner_cell_index = Quadmesh3D.side_inner_cell_index(args, side_index)
595
+ return Quadmesh._edge_to_quad_coords(args.topology, side_index, inner_cell_index, side_coords)
596
+
597
+ @wp.func
598
+ def side_outer_cell_coords(args: SideArg, side_index: ElementIndex, side_coords: Coords):
599
+ outer_cell_index = Quadmesh3D.side_outer_cell_index(args, side_index)
600
+ return Quadmesh._edge_to_quad_coords(args.topology, side_index, outer_cell_index, side_coords)
601
+
602
+ @wp.func
603
+ def side_from_cell_coords(
604
+ args: SideArg,
605
+ side_index: ElementIndex,
606
+ quad_index: ElementIndex,
607
+ quad_coords: Coords,
608
+ ):
609
+ return Quadmesh._quad_to_edge_coords(args.topology, side_index, quad_index, quad_coords)
610
+
611
+ @wp.func
612
+ def side_to_cell_arg(side_arg: SideArg):
613
+ return Quadmesh3DCellArg(side_arg.topology.cell_arg, side_arg.positions)
614
+
615
+ @wp.kernel
616
+ def _orient_edges(
617
+ edge_vertex_indices: wp.array(dtype=wp.vec2i),
618
+ edge_quad_indices: wp.array(dtype=wp.vec2i),
619
+ quad_vertex_indices: wp.array2d(dtype=int),
620
+ positions: wp.array(dtype=wp.vec3),
621
+ ):
622
+ e = wp.tid()
623
+
624
+ tri = edge_quad_indices[e][0]
625
+
626
+ quad_vidx = quad_vertex_indices[tri]
627
+ edge_vidx = edge_vertex_indices[e]
628
+
629
+ p0 = positions[quad_vidx[0]]
630
+ p1 = positions[quad_vidx[1]]
631
+ p2 = positions[quad_vidx[2]]
632
+ p3 = positions[quad_vidx[3]]
633
+
634
+ quad_centroid = (
635
+ positions[quad_vidx[0]] + positions[quad_vidx[1]] + positions[quad_vidx[2]] + positions[quad_vidx[3]]
636
+ ) / 4.0
637
+ quad_normal = wp.cross(p2 - p0, p3 - p1)
638
+
639
+ v0 = positions[edge_vidx[0]]
640
+ v1 = positions[edge_vidx[1]]
641
+
642
+ edge_center = 0.5 * (v1 + v0)
643
+ edge_vec = v1 - v0
644
+ edge_normal = wp.cross(edge_vec, quad_normal)
645
+
646
+ # if edge normal points toward first triangle centroid, flip indices
647
+ if wp.dot(quad_centroid - edge_center, edge_normal) > 0.0:
648
+ edge_vertex_indices[e] = wp.vec2i(edge_vidx[1], edge_vidx[0])
@@ -78,6 +78,8 @@ class Tetmesh(Geometry):
78
78
  self._edge_count = 0
79
79
  self._build_topology(temporary_store)
80
80
 
81
+ self._make_default_dependent_implementations()
82
+
81
83
  self._tet_bvh: wp.Bvh = None
82
84
  if build_bvh:
83
85
  self._build_bvh()
@@ -250,18 +252,6 @@ class Tetmesh(Geometry):
250
252
 
251
253
  return make_free_sample(closest_tet, closest_coords)
252
254
 
253
- @wp.func
254
- def cell_measure(args: CellArg, s: Sample):
255
- return wp.abs(wp.determinant(Tetmesh.cell_deformation_gradient(args, s))) / 6.0
256
-
257
- @wp.func
258
- def cell_measure_ratio(args: CellArg, s: Sample):
259
- return 1.0
260
-
261
- @wp.func
262
- def cell_normal(args: CellArg, s: Sample):
263
- return wp.vec3(0.0)
264
-
265
255
  @cached_arg_value
266
256
  def side_index_arg_value(self, device) -> SideIndexArg:
267
257
  args = self.SideIndexArg()
@@ -309,37 +299,6 @@ class Tetmesh(Geometry):
309
299
  e1, e2 = Tetmesh._side_vecs(args, s.element_index)
310
300
  return _mat32(e1, e2)
311
301
 
312
- @wp.func
313
- def side_inner_inverse_deformation_gradient(args: SideArg, s: Sample):
314
- cell_index = Tetmesh.side_inner_cell_index(args, s.element_index)
315
- s_cell = make_free_sample(cell_index, Coords())
316
- return Tetmesh.cell_inverse_deformation_gradient(args.cell_arg, s_cell)
317
-
318
- @wp.func
319
- def side_outer_inverse_deformation_gradient(args: SideArg, s: Sample):
320
- cell_index = Tetmesh.side_outer_cell_index(args, s.element_index)
321
- s_cell = make_free_sample(cell_index, Coords())
322
- return Tetmesh.cell_inverse_deformation_gradient(args.cell_arg, s_cell)
323
-
324
- @wp.func
325
- def side_measure(args: SideArg, s: Sample):
326
- e1, e2 = Tetmesh._side_vecs(args, s.element_index)
327
- return 0.5 * wp.length(wp.cross(e1, e2))
328
-
329
- @wp.func
330
- def side_measure_ratio(args: SideArg, s: Sample):
331
- inner = Tetmesh.side_inner_cell_index(args, s.element_index)
332
- outer = Tetmesh.side_outer_cell_index(args, s.element_index)
333
- return Tetmesh.side_measure(args, s) / wp.min(
334
- Tetmesh.cell_measure(args.cell_arg, make_free_sample(inner, Coords())),
335
- Tetmesh.cell_measure(args.cell_arg, make_free_sample(outer, Coords())),
336
- )
337
-
338
- @wp.func
339
- def side_normal(args: SideArg, s: Sample):
340
- e1, e2 = Tetmesh._side_vecs(args, s.element_index)
341
- return wp.normalize(wp.cross(e1, e2))
342
-
343
302
  @wp.func
344
303
  def side_inner_cell_index(arg: SideArg, side_index: ElementIndex):
345
304
  return arg.face_tet_indices[side_index][0]