warp-lang 1.4.1__py3-none-manylinux2014_aarch64.whl → 1.5.0__py3-none-manylinux2014_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of warp-lang might be problematic. Click here for more details.
- warp/__init__.py +4 -0
- warp/autograd.py +43 -8
- warp/bin/warp-clang.so +0 -0
- warp/bin/warp.so +0 -0
- warp/build.py +21 -2
- warp/build_dll.py +23 -6
- warp/builtins.py +1920 -111
- warp/codegen.py +186 -62
- warp/config.py +2 -2
- warp/context.py +322 -73
- warp/examples/assets/pixel.jpg +0 -0
- warp/examples/benchmarks/benchmark_cloth_paddle.py +86 -0
- warp/examples/benchmarks/benchmark_gemm.py +121 -0
- warp/examples/benchmarks/benchmark_interop_paddle.py +158 -0
- warp/examples/benchmarks/benchmark_tile.py +179 -0
- warp/examples/core/example_dem.py +2 -1
- warp/examples/core/example_mesh_intersect.py +3 -3
- warp/examples/fem/example_adaptive_grid.py +37 -10
- warp/examples/fem/example_apic_fluid.py +3 -2
- warp/examples/fem/example_convection_diffusion_dg.py +4 -5
- warp/examples/fem/example_deformed_geometry.py +1 -1
- warp/examples/fem/example_diffusion_3d.py +47 -4
- warp/examples/fem/example_distortion_energy.py +220 -0
- warp/examples/fem/example_magnetostatics.py +127 -85
- warp/examples/fem/example_nonconforming_contact.py +5 -5
- warp/examples/fem/example_stokes.py +3 -1
- warp/examples/fem/example_streamlines.py +12 -19
- warp/examples/fem/utils.py +38 -15
- warp/examples/optim/example_walker.py +2 -2
- warp/examples/sim/example_cloth.py +2 -25
- warp/examples/sim/example_jacobian_ik.py +6 -2
- warp/examples/sim/example_quadruped.py +2 -1
- warp/examples/tile/example_tile_convolution.py +58 -0
- warp/examples/tile/example_tile_fft.py +47 -0
- warp/examples/tile/example_tile_filtering.py +105 -0
- warp/examples/tile/example_tile_matmul.py +79 -0
- warp/examples/tile/example_tile_mlp.py +375 -0
- warp/fem/__init__.py +8 -0
- warp/fem/cache.py +16 -12
- warp/fem/dirichlet.py +1 -1
- warp/fem/domain.py +44 -1
- warp/fem/field/__init__.py +1 -2
- warp/fem/field/field.py +31 -19
- warp/fem/field/nodal_field.py +101 -49
- warp/fem/field/virtual.py +794 -0
- warp/fem/geometry/__init__.py +2 -2
- warp/fem/geometry/deformed_geometry.py +3 -105
- warp/fem/geometry/element.py +13 -0
- warp/fem/geometry/geometry.py +165 -5
- warp/fem/geometry/grid_2d.py +3 -6
- warp/fem/geometry/grid_3d.py +31 -28
- warp/fem/geometry/hexmesh.py +3 -46
- warp/fem/geometry/nanogrid.py +3 -2
- warp/fem/geometry/{quadmesh_2d.py → quadmesh.py} +280 -159
- warp/fem/geometry/tetmesh.py +2 -43
- warp/fem/geometry/{trimesh_2d.py → trimesh.py} +354 -186
- warp/fem/integrate.py +683 -261
- warp/fem/linalg.py +404 -0
- warp/fem/operator.py +101 -18
- warp/fem/polynomial.py +5 -5
- warp/fem/quadrature/quadrature.py +45 -21
- warp/fem/space/__init__.py +45 -11
- warp/fem/space/basis_function_space.py +451 -0
- warp/fem/space/basis_space.py +58 -11
- warp/fem/space/function_space.py +146 -5
- warp/fem/space/grid_2d_function_space.py +80 -66
- warp/fem/space/grid_3d_function_space.py +113 -68
- warp/fem/space/hexmesh_function_space.py +96 -108
- warp/fem/space/nanogrid_function_space.py +62 -110
- warp/fem/space/quadmesh_function_space.py +208 -0
- warp/fem/space/shape/__init__.py +45 -7
- warp/fem/space/shape/cube_shape_function.py +328 -54
- warp/fem/space/shape/shape_function.py +10 -1
- warp/fem/space/shape/square_shape_function.py +328 -60
- warp/fem/space/shape/tet_shape_function.py +269 -19
- warp/fem/space/shape/triangle_shape_function.py +238 -19
- warp/fem/space/tetmesh_function_space.py +69 -37
- warp/fem/space/topology.py +38 -0
- warp/fem/space/trimesh_function_space.py +179 -0
- warp/fem/utils.py +6 -331
- warp/jax_experimental.py +3 -1
- warp/native/array.h +55 -40
- warp/native/builtin.h +124 -43
- warp/native/bvh.h +4 -0
- warp/native/coloring.cpp +600 -0
- warp/native/cuda_util.cpp +14 -0
- warp/native/cuda_util.h +2 -1
- warp/native/fabric.h +8 -0
- warp/native/hashgrid.h +4 -0
- warp/native/marching.cu +8 -0
- warp/native/mat.h +14 -3
- warp/native/mathdx.cpp +59 -0
- warp/native/mesh.h +4 -0
- warp/native/range.h +13 -1
- warp/native/reduce.cpp +9 -1
- warp/native/reduce.cu +7 -0
- warp/native/runlength_encode.cpp +9 -1
- warp/native/runlength_encode.cu +7 -1
- warp/native/scan.cpp +8 -0
- warp/native/scan.cu +8 -0
- warp/native/scan.h +8 -1
- warp/native/sparse.cpp +8 -0
- warp/native/sparse.cu +8 -0
- warp/native/temp_buffer.h +7 -0
- warp/native/tile.h +1857 -0
- warp/native/tile_gemm.h +341 -0
- warp/native/tile_reduce.h +210 -0
- warp/native/volume_builder.cu +8 -0
- warp/native/volume_builder.h +8 -0
- warp/native/warp.cpp +10 -2
- warp/native/warp.cu +369 -15
- warp/native/warp.h +12 -2
- warp/optim/adam.py +39 -4
- warp/paddle.py +29 -12
- warp/render/render_opengl.py +137 -65
- warp/sim/graph_coloring.py +292 -0
- warp/sim/integrator_euler.py +4 -2
- warp/sim/integrator_featherstone.py +115 -44
- warp/sim/integrator_vbd.py +6 -0
- warp/sim/model.py +90 -17
- warp/stubs.py +651 -85
- warp/tape.py +12 -7
- warp/tests/assets/pixel.npy +0 -0
- warp/tests/aux_test_instancing_gc.py +18 -0
- warp/tests/test_array.py +207 -48
- warp/tests/test_closest_point_edge_edge.py +8 -8
- warp/tests/test_codegen.py +120 -1
- warp/tests/test_codegen_instancing.py +30 -0
- warp/tests/test_collision.py +110 -0
- warp/tests/test_coloring.py +241 -0
- warp/tests/test_context.py +34 -0
- warp/tests/test_examples.py +18 -4
- warp/tests/test_fabricarray.py +33 -0
- warp/tests/test_fem.py +453 -113
- warp/tests/test_func.py +48 -1
- warp/tests/test_generics.py +52 -0
- warp/tests/test_iter.py +68 -0
- warp/tests/test_mat_scalar_ops.py +1 -1
- warp/tests/test_mesh_query_point.py +5 -4
- warp/tests/test_module_hashing.py +23 -0
- warp/tests/test_paddle.py +27 -87
- warp/tests/test_print.py +191 -1
- warp/tests/test_spatial.py +1 -1
- warp/tests/test_tile.py +700 -0
- warp/tests/test_tile_mathdx.py +144 -0
- warp/tests/test_tile_mlp.py +383 -0
- warp/tests/test_tile_reduce.py +374 -0
- warp/tests/test_tile_shared_memory.py +190 -0
- warp/tests/test_vbd.py +12 -20
- warp/tests/test_volume.py +43 -0
- warp/tests/unittest_suites.py +23 -2
- warp/tests/unittest_utils.py +4 -0
- warp/types.py +339 -73
- warp/utils.py +22 -1
- {warp_lang-1.4.1.dist-info → warp_lang-1.5.0.dist-info}/METADATA +33 -7
- {warp_lang-1.4.1.dist-info → warp_lang-1.5.0.dist-info}/RECORD +159 -132
- {warp_lang-1.4.1.dist-info → warp_lang-1.5.0.dist-info}/WHEEL +1 -1
- warp/fem/field/test.py +0 -180
- warp/fem/field/trial.py +0 -183
- warp/fem/space/collocated_function_space.py +0 -102
- warp/fem/space/quadmesh_2d_function_space.py +0 -261
- warp/fem/space/trimesh_2d_function_space.py +0 -153
- {warp_lang-1.4.1.dist-info → warp_lang-1.5.0.dist-info}/LICENSE.md +0 -0
- {warp_lang-1.4.1.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
|
|
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
|
|
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
|
|
30
|
-
cell_arg:
|
|
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
|
|
36
|
-
"""
|
|
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
|
|
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,
|
|
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
|
|
98
|
-
args =
|
|
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
|
-
@
|
|
108
|
-
def
|
|
109
|
-
|
|
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
|
-
|
|
115
|
-
|
|
116
|
-
|
|
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
|
-
|
|
127
|
-
|
|
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
|
-
|
|
132
|
-
|
|
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
|
-
|
|
142
|
-
|
|
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
|
-
|
|
146
|
-
|
|
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
|
-
|
|
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
|
|
163
|
-
|
|
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
|
|
259
|
-
|
|
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
|
|
299
|
-
|
|
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
|
|
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])
|
warp/fem/geometry/tetmesh.py
CHANGED
|
@@ -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]
|