warp-lang 1.7.2__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.
- warp/__init__.py +3 -1
- warp/__init__.pyi +3489 -1
- warp/autograd.py +45 -122
- warp/bin/warp.so +0 -0
- warp/build.py +241 -252
- warp/build_dll.py +125 -26
- warp/builtins.py +1907 -384
- warp/codegen.py +257 -101
- warp/config.py +12 -1
- warp/constants.py +1 -1
- warp/context.py +657 -223
- warp/dlpack.py +1 -1
- warp/examples/benchmarks/benchmark_cloth.py +2 -2
- warp/examples/benchmarks/benchmark_tile_sort.py +155 -0
- warp/examples/core/example_sample_mesh.py +1 -1
- warp/examples/core/example_spin_lock.py +93 -0
- warp/examples/core/example_work_queue.py +118 -0
- warp/examples/fem/example_adaptive_grid.py +5 -5
- warp/examples/fem/example_apic_fluid.py +1 -1
- warp/examples/fem/example_burgers.py +1 -1
- warp/examples/fem/example_convection_diffusion.py +9 -6
- warp/examples/fem/example_darcy_ls_optimization.py +489 -0
- warp/examples/fem/example_deformed_geometry.py +1 -1
- warp/examples/fem/example_diffusion.py +2 -2
- warp/examples/fem/example_diffusion_3d.py +1 -1
- warp/examples/fem/example_distortion_energy.py +1 -1
- warp/examples/fem/example_elastic_shape_optimization.py +387 -0
- warp/examples/fem/example_magnetostatics.py +5 -3
- warp/examples/fem/example_mixed_elasticity.py +5 -3
- warp/examples/fem/example_navier_stokes.py +11 -9
- warp/examples/fem/example_nonconforming_contact.py +5 -3
- warp/examples/fem/example_streamlines.py +8 -3
- warp/examples/fem/utils.py +9 -8
- warp/examples/interop/example_jax_ffi_callback.py +2 -2
- warp/examples/optim/example_drone.py +1 -1
- warp/examples/sim/example_cloth.py +1 -1
- warp/examples/sim/example_cloth_self_contact.py +48 -54
- warp/examples/tile/example_tile_block_cholesky.py +502 -0
- warp/examples/tile/example_tile_cholesky.py +2 -1
- warp/examples/tile/example_tile_convolution.py +1 -1
- warp/examples/tile/example_tile_filtering.py +1 -1
- warp/examples/tile/example_tile_matmul.py +1 -1
- warp/examples/tile/example_tile_mlp.py +2 -0
- warp/fabric.py +7 -7
- warp/fem/__init__.py +5 -0
- warp/fem/adaptivity.py +1 -1
- warp/fem/cache.py +152 -63
- warp/fem/dirichlet.py +2 -2
- warp/fem/domain.py +136 -6
- warp/fem/field/field.py +141 -99
- warp/fem/field/nodal_field.py +85 -39
- warp/fem/field/virtual.py +97 -52
- warp/fem/geometry/adaptive_nanogrid.py +91 -86
- warp/fem/geometry/closest_point.py +13 -0
- warp/fem/geometry/deformed_geometry.py +102 -40
- warp/fem/geometry/element.py +56 -2
- warp/fem/geometry/geometry.py +323 -22
- warp/fem/geometry/grid_2d.py +157 -62
- warp/fem/geometry/grid_3d.py +116 -20
- warp/fem/geometry/hexmesh.py +86 -20
- warp/fem/geometry/nanogrid.py +166 -86
- warp/fem/geometry/partition.py +59 -25
- warp/fem/geometry/quadmesh.py +86 -135
- warp/fem/geometry/tetmesh.py +47 -119
- warp/fem/geometry/trimesh.py +77 -270
- warp/fem/integrate.py +107 -52
- warp/fem/linalg.py +25 -58
- warp/fem/operator.py +124 -27
- warp/fem/quadrature/pic_quadrature.py +36 -14
- warp/fem/quadrature/quadrature.py +40 -16
- warp/fem/space/__init__.py +1 -1
- warp/fem/space/basis_function_space.py +66 -46
- warp/fem/space/basis_space.py +17 -4
- warp/fem/space/dof_mapper.py +1 -1
- warp/fem/space/function_space.py +2 -2
- warp/fem/space/grid_2d_function_space.py +4 -1
- warp/fem/space/hexmesh_function_space.py +4 -2
- warp/fem/space/nanogrid_function_space.py +3 -1
- warp/fem/space/partition.py +11 -2
- warp/fem/space/quadmesh_function_space.py +4 -1
- warp/fem/space/restriction.py +5 -2
- warp/fem/space/shape/__init__.py +10 -8
- warp/fem/space/tetmesh_function_space.py +4 -1
- warp/fem/space/topology.py +52 -21
- warp/fem/space/trimesh_function_space.py +4 -1
- warp/fem/utils.py +53 -8
- warp/jax.py +1 -2
- warp/jax_experimental/ffi.py +12 -17
- warp/jax_experimental/xla_ffi.py +37 -24
- warp/math.py +171 -1
- warp/native/array.h +99 -0
- warp/native/builtin.h +174 -31
- warp/native/coloring.cpp +1 -1
- warp/native/exports.h +118 -63
- warp/native/intersect.h +3 -3
- warp/native/mat.h +5 -10
- warp/native/mathdx.cpp +11 -5
- warp/native/matnn.h +1 -123
- warp/native/quat.h +28 -4
- warp/native/sparse.cpp +121 -258
- warp/native/sparse.cu +181 -274
- warp/native/spatial.h +305 -17
- warp/native/tile.h +583 -72
- warp/native/tile_radix_sort.h +1108 -0
- warp/native/tile_reduce.h +237 -2
- warp/native/tile_scan.h +240 -0
- warp/native/tuple.h +189 -0
- warp/native/vec.h +6 -16
- warp/native/warp.cpp +36 -4
- warp/native/warp.cu +574 -51
- warp/native/warp.h +47 -74
- warp/optim/linear.py +5 -1
- warp/paddle.py +7 -8
- warp/py.typed +0 -0
- warp/render/render_opengl.py +58 -29
- warp/render/render_usd.py +124 -61
- warp/sim/__init__.py +9 -0
- warp/sim/collide.py +252 -78
- warp/sim/graph_coloring.py +8 -1
- warp/sim/import_mjcf.py +4 -3
- warp/sim/import_usd.py +11 -7
- warp/sim/integrator.py +5 -2
- warp/sim/integrator_euler.py +1 -1
- warp/sim/integrator_featherstone.py +1 -1
- warp/sim/integrator_vbd.py +751 -320
- warp/sim/integrator_xpbd.py +1 -1
- warp/sim/model.py +265 -260
- warp/sim/utils.py +10 -7
- warp/sparse.py +303 -166
- warp/tape.py +52 -51
- warp/tests/cuda/test_conditional_captures.py +1046 -0
- warp/tests/cuda/test_streams.py +1 -1
- warp/tests/geometry/test_volume.py +2 -2
- warp/tests/interop/test_dlpack.py +9 -9
- warp/tests/interop/test_jax.py +0 -1
- warp/tests/run_coverage_serial.py +1 -1
- warp/tests/sim/disabled_kinematics.py +2 -2
- warp/tests/sim/{test_vbd.py → test_cloth.py} +296 -113
- warp/tests/sim/test_collision.py +159 -51
- warp/tests/sim/test_coloring.py +15 -1
- warp/tests/test_array.py +254 -2
- warp/tests/test_array_reduce.py +2 -2
- warp/tests/test_atomic_cas.py +299 -0
- warp/tests/test_codegen.py +142 -19
- warp/tests/test_conditional.py +47 -1
- warp/tests/test_ctypes.py +0 -20
- warp/tests/test_devices.py +8 -0
- warp/tests/test_fabricarray.py +4 -2
- warp/tests/test_fem.py +58 -25
- warp/tests/test_func.py +42 -1
- warp/tests/test_grad.py +1 -1
- warp/tests/test_lerp.py +1 -3
- warp/tests/test_map.py +481 -0
- warp/tests/test_mat.py +1 -24
- warp/tests/test_quat.py +6 -15
- warp/tests/test_rounding.py +10 -38
- warp/tests/test_runlength_encode.py +7 -7
- warp/tests/test_smoothstep.py +1 -1
- warp/tests/test_sparse.py +51 -2
- warp/tests/test_spatial.py +507 -1
- warp/tests/test_struct.py +2 -2
- warp/tests/test_tuple.py +265 -0
- warp/tests/test_types.py +2 -2
- warp/tests/test_utils.py +24 -18
- warp/tests/tile/test_tile.py +420 -1
- warp/tests/tile/test_tile_mathdx.py +518 -14
- warp/tests/tile/test_tile_reduce.py +213 -0
- warp/tests/tile/test_tile_shared_memory.py +130 -1
- warp/tests/tile/test_tile_sort.py +117 -0
- warp/tests/unittest_suites.py +4 -6
- warp/types.py +462 -308
- warp/utils.py +647 -86
- {warp_lang-1.7.2.dist-info → warp_lang-1.8.0.dist-info}/METADATA +20 -6
- {warp_lang-1.7.2.dist-info → warp_lang-1.8.0.dist-info}/RECORD +177 -165
- warp/stubs.py +0 -3381
- warp/tests/sim/test_xpbd.py +0 -399
- warp/tests/test_mlp.py +0 -282
- {warp_lang-1.7.2.dist-info → warp_lang-1.8.0.dist-info}/WHEEL +0 -0
- {warp_lang-1.7.2.dist-info → warp_lang-1.8.0.dist-info}/licenses/LICENSE.md +0 -0
- {warp_lang-1.7.2.dist-info → warp_lang-1.8.0.dist-info}/top_level.txt +0 -0
warp/fem/geometry/tetmesh.py
CHANGED
|
@@ -23,15 +23,13 @@ from warp.fem.cache import (
|
|
|
23
23
|
cached_arg_value,
|
|
24
24
|
)
|
|
25
25
|
from warp.fem.types import (
|
|
26
|
-
NULL_ELEMENT_INDEX,
|
|
27
26
|
OUTSIDE,
|
|
28
27
|
Coords,
|
|
29
28
|
ElementIndex,
|
|
30
29
|
Sample,
|
|
31
|
-
make_free_sample,
|
|
32
30
|
)
|
|
33
31
|
|
|
34
|
-
from .closest_point import project_on_tet_at_origin
|
|
32
|
+
from .closest_point import project_on_tet_at_origin, project_on_tri_at_origin
|
|
35
33
|
from .element import Tetrahedron, Triangle
|
|
36
34
|
from .geometry import Geometry
|
|
37
35
|
|
|
@@ -41,10 +39,6 @@ class TetmeshCellArg:
|
|
|
41
39
|
tet_vertex_indices: wp.array2d(dtype=int)
|
|
42
40
|
positions: wp.array(dtype=wp.vec3)
|
|
43
41
|
|
|
44
|
-
# for neighbor cell lookup
|
|
45
|
-
vertex_tet_offsets: wp.array(dtype=int)
|
|
46
|
-
vertex_tet_indices: wp.array(dtype=int)
|
|
47
|
-
|
|
48
42
|
# for global cell lookup
|
|
49
43
|
tet_bvh: wp.uint64
|
|
50
44
|
|
|
@@ -56,9 +50,6 @@ class TetmeshSideArg:
|
|
|
56
50
|
face_tet_indices: wp.array(dtype=wp.vec2i)
|
|
57
51
|
|
|
58
52
|
|
|
59
|
-
_NULL_BVH = wp.constant(wp.uint64(-1))
|
|
60
|
-
|
|
61
|
-
|
|
62
53
|
class Tetmesh(Geometry):
|
|
63
54
|
"""Tetrahedral mesh geometry"""
|
|
64
55
|
|
|
@@ -77,8 +68,8 @@ class Tetmesh(Geometry):
|
|
|
77
68
|
Args:
|
|
78
69
|
tet_vertex_indices: warp array of shape (num_tets, 4) containing vertex indices for each tet
|
|
79
70
|
positions: warp array of shape (num_vertices, 3) containing 3d position for each vertex
|
|
80
|
-
temporary_store: shared pool from which to allocate temporary arrays
|
|
81
71
|
build_bvh: Whether to also build the tet BVH, which is necessary for the global `fem.lookup` operator to function without initial guess
|
|
72
|
+
temporary_store: shared pool from which to allocate temporary arrays
|
|
82
73
|
"""
|
|
83
74
|
|
|
84
75
|
self.tet_vertex_indices = tet_vertex_indices
|
|
@@ -93,38 +84,12 @@ class Tetmesh(Geometry):
|
|
|
93
84
|
self._build_topology(temporary_store)
|
|
94
85
|
|
|
95
86
|
self._make_default_dependent_implementations()
|
|
87
|
+
self.cell_coordinates = self._make_cell_coordinates(assume_linear=True)
|
|
88
|
+
self.side_coordinates = self._make_side_coordinates(assume_linear=True)
|
|
96
89
|
|
|
97
90
|
self._tet_bvh: wp.Bvh = None
|
|
98
91
|
if build_bvh:
|
|
99
|
-
self.
|
|
100
|
-
|
|
101
|
-
def update_bvh(self, force_rebuild: bool = False):
|
|
102
|
-
"""
|
|
103
|
-
Refits the BVH, or rebuilds it from scratch if `force_rebuild` is ``True``.
|
|
104
|
-
"""
|
|
105
|
-
|
|
106
|
-
if self._tet_bvh is None or force_rebuild:
|
|
107
|
-
return self.build_bvh()
|
|
108
|
-
|
|
109
|
-
wp.launch(
|
|
110
|
-
Tetmesh._compute_tet_bounds,
|
|
111
|
-
self.tet_vertex_indices,
|
|
112
|
-
self.positions,
|
|
113
|
-
self._tet_bvh.lowers,
|
|
114
|
-
self._tet_bvh.uppers,
|
|
115
|
-
)
|
|
116
|
-
self._tet_bvh.refit()
|
|
117
|
-
|
|
118
|
-
def _build_bvh(self, temporary_store: Optional[TemporaryStore] = None):
|
|
119
|
-
lowers = wp.array(shape=self.cell_count(), dtype=wp.vec3, device=self.positions.device)
|
|
120
|
-
uppers = wp.array(shape=self.cell_count(), dtype=wp.vec3, device=self.positions.device)
|
|
121
|
-
wp.launch(
|
|
122
|
-
Tetmesh._compute_tet_bounds,
|
|
123
|
-
device=self.positions.device,
|
|
124
|
-
dim=self.cell_count(),
|
|
125
|
-
inputs=[self.tet_vertex_indices, self.positions, lowers, uppers],
|
|
126
|
-
)
|
|
127
|
-
self._tet_bvh = wp.Bvh(lowers, uppers)
|
|
92
|
+
self.build_bvh(self.positions.device)
|
|
128
93
|
|
|
129
94
|
def cell_count(self):
|
|
130
95
|
return self.tet_vertex_indices.shape[0]
|
|
@@ -172,18 +137,15 @@ class Tetmesh(Geometry):
|
|
|
172
137
|
|
|
173
138
|
# Geometry device interface
|
|
174
139
|
|
|
175
|
-
@cached_arg_value
|
|
176
140
|
def cell_arg_value(self, device) -> CellArg:
|
|
177
141
|
args = self.CellArg()
|
|
142
|
+
self.fill_cell_arg(args, device)
|
|
143
|
+
return args
|
|
178
144
|
|
|
145
|
+
def fill_cell_arg(self, args: CellArg, device):
|
|
179
146
|
args.tet_vertex_indices = self.tet_vertex_indices.to(device)
|
|
180
147
|
args.positions = self.positions.to(device)
|
|
181
|
-
args.
|
|
182
|
-
args.vertex_tet_indices = self._vertex_tet_indices.to(device)
|
|
183
|
-
|
|
184
|
-
args.tet_bvh = _NULL_BVH if self._tet_bvh is None else self._tet_bvh.id
|
|
185
|
-
|
|
186
|
-
return args
|
|
148
|
+
args.tet_bvh = self.bvh_id(device)
|
|
187
149
|
|
|
188
150
|
@wp.func
|
|
189
151
|
def cell_position(args: CellArg, s: Sample):
|
|
@@ -209,87 +171,43 @@ class Tetmesh(Geometry):
|
|
|
209
171
|
return wp.inverse(Tetmesh.cell_deformation_gradient(args, s))
|
|
210
172
|
|
|
211
173
|
@wp.func
|
|
212
|
-
def
|
|
213
|
-
|
|
174
|
+
def cell_closest_point(args: CellArg, tet_index: int, pos: wp.vec3):
|
|
175
|
+
vidx = args.tet_vertex_indices[tet_index]
|
|
176
|
+
p0 = args.positions[vidx[0]]
|
|
214
177
|
|
|
215
178
|
q = pos - p0
|
|
216
|
-
e1 = args.positions[
|
|
217
|
-
e2 = args.positions[
|
|
218
|
-
e3 = args.positions[
|
|
179
|
+
e1 = args.positions[vidx[1]] - p0
|
|
180
|
+
e2 = args.positions[vidx[2]] - p0
|
|
181
|
+
e3 = args.positions[vidx[3]] - p0
|
|
219
182
|
|
|
220
183
|
dist, coords = project_on_tet_at_origin(q, e1, e2, e3)
|
|
221
|
-
return
|
|
222
|
-
|
|
223
|
-
@wp.func
|
|
224
|
-
def _bvh_lookup(args: CellArg, pos: wp.vec3):
|
|
225
|
-
closest_tet = int(NULL_ELEMENT_INDEX)
|
|
226
|
-
closest_coords = Coords(OUTSIDE)
|
|
227
|
-
closest_dist = float(1.0e8)
|
|
228
|
-
|
|
229
|
-
if args.tet_bvh != _NULL_BVH:
|
|
230
|
-
query = wp.bvh_query_aabb(args.tet_bvh, pos, pos)
|
|
231
|
-
tet = int(0)
|
|
232
|
-
while wp.bvh_query_next(query, tet):
|
|
233
|
-
dist, coords = Tetmesh._project_on_tet(args, pos, tet)
|
|
234
|
-
if dist <= closest_dist:
|
|
235
|
-
closest_dist = dist
|
|
236
|
-
closest_tet = tet
|
|
237
|
-
closest_coords = coords
|
|
238
|
-
|
|
239
|
-
return closest_dist, closest_tet, closest_coords
|
|
240
|
-
|
|
241
|
-
@wp.func
|
|
242
|
-
def cell_lookup(args: CellArg, pos: wp.vec3):
|
|
243
|
-
closest_dist, closest_tet, closest_coords = Tetmesh._bvh_lookup(args, pos)
|
|
244
|
-
|
|
245
|
-
return make_free_sample(closest_tet, closest_coords)
|
|
246
|
-
|
|
247
|
-
@wp.func
|
|
248
|
-
def cell_lookup(args: CellArg, pos: wp.vec3, guess: Sample):
|
|
249
|
-
closest_dist, closest_tet, closest_coords = Tetmesh._bvh_lookup(args, pos)
|
|
250
|
-
return make_free_sample(closest_tet, closest_coords)
|
|
251
|
-
|
|
252
|
-
if closest_tet == NULL_ELEMENT_INDEX:
|
|
253
|
-
# nothing found yet, bvh may not be available or outside mesh
|
|
254
|
-
for v in range(4):
|
|
255
|
-
vtx = args.tet_vertex_indices[guess.element_index, v]
|
|
256
|
-
tet_beg = args.vertex_tet_offsets[vtx]
|
|
257
|
-
tet_end = args.vertex_tet_offsets[vtx + 1]
|
|
258
|
-
|
|
259
|
-
for t in range(tet_beg, tet_end):
|
|
260
|
-
tet = args.vertex_tet_indices[t]
|
|
261
|
-
dist, coords = Tetmesh._project_on_tet(args, pos, tet)
|
|
262
|
-
if dist <= closest_dist:
|
|
263
|
-
closest_dist = dist
|
|
264
|
-
closest_tet = tet
|
|
265
|
-
closest_coords = coords
|
|
266
|
-
|
|
267
|
-
return make_free_sample(closest_tet, closest_coords)
|
|
184
|
+
return coords, dist
|
|
268
185
|
|
|
269
186
|
@cached_arg_value
|
|
270
187
|
def side_index_arg_value(self, device) -> SideIndexArg:
|
|
271
188
|
args = self.SideIndexArg()
|
|
189
|
+
self.fill_side_index_arg(args, device)
|
|
190
|
+
return args
|
|
272
191
|
|
|
192
|
+
def fill_side_index_arg(self, args: SideIndexArg, device):
|
|
273
193
|
args.boundary_face_indices = self._boundary_face_indices.to(device)
|
|
274
194
|
|
|
275
|
-
return args
|
|
276
|
-
|
|
277
195
|
@wp.func
|
|
278
196
|
def boundary_side_index(args: SideIndexArg, boundary_side_index: int):
|
|
279
197
|
"""Boundary side to side index"""
|
|
280
198
|
|
|
281
199
|
return args.boundary_face_indices[boundary_side_index]
|
|
282
200
|
|
|
283
|
-
@cached_arg_value
|
|
284
201
|
def side_arg_value(self, device) -> CellArg:
|
|
285
202
|
args = self.SideArg()
|
|
203
|
+
self.fill_side_arg(args, device)
|
|
204
|
+
return args
|
|
286
205
|
|
|
287
|
-
|
|
206
|
+
def fill_side_arg(self, args: SideArg, device):
|
|
207
|
+
self.fill_cell_arg(args.cell_arg, device)
|
|
288
208
|
args.face_vertex_indices = self._face_vertex_indices.to(device)
|
|
289
209
|
args.face_tet_indices = self._face_tet_indices.to(device)
|
|
290
210
|
|
|
291
|
-
return args
|
|
292
|
-
|
|
293
211
|
@wp.func
|
|
294
212
|
def side_position(args: SideArg, s: Sample):
|
|
295
213
|
face_idx = args.face_vertex_indices[s.element_index]
|
|
@@ -308,6 +226,18 @@ class Tetmesh(Geometry):
|
|
|
308
226
|
|
|
309
227
|
return v1 - v0, v2 - v0
|
|
310
228
|
|
|
229
|
+
@wp.func
|
|
230
|
+
def side_closest_point(args: SideArg, tri_index: ElementIndex, pos: wp.vec3):
|
|
231
|
+
vidx = args.topology.face_vertex_indices[tri_index]
|
|
232
|
+
p0 = args.positions[vidx[0]]
|
|
233
|
+
|
|
234
|
+
q = pos - p0
|
|
235
|
+
e1 = args.positions[vidx[1]] - p0
|
|
236
|
+
e2 = args.positions[vidx[2]] - p0
|
|
237
|
+
|
|
238
|
+
dist, coords = project_on_tri_at_origin(q, e1, e2)
|
|
239
|
+
return coords, dist
|
|
240
|
+
|
|
311
241
|
@wp.func
|
|
312
242
|
def side_deformation_gradient(args: SideArg, s: Sample):
|
|
313
243
|
e1, e2 = Tetmesh._side_vecs(args, s.element_index)
|
|
@@ -838,18 +768,16 @@ class Tetmesh(Geometry):
|
|
|
838
768
|
)
|
|
839
769
|
tet_edge_indices[t][k + 3] = edge_id
|
|
840
770
|
|
|
841
|
-
@wp.
|
|
842
|
-
def
|
|
843
|
-
|
|
844
|
-
positions: wp.array(dtype=wp.vec3),
|
|
845
|
-
lowers: wp.array(dtype=wp.vec3),
|
|
846
|
-
uppers: wp.array(dtype=wp.vec3),
|
|
847
|
-
):
|
|
848
|
-
t = wp.tid()
|
|
849
|
-
p0 = positions[tet_vertex_indices[t, 0]]
|
|
850
|
-
p1 = positions[tet_vertex_indices[t, 1]]
|
|
851
|
-
p2 = positions[tet_vertex_indices[t, 2]]
|
|
852
|
-
p3 = positions[tet_vertex_indices[t, 3]]
|
|
771
|
+
@wp.func
|
|
772
|
+
def cell_bvh_id(cell_arg: TetmeshCellArg):
|
|
773
|
+
return cell_arg.tet_bvh
|
|
853
774
|
|
|
854
|
-
|
|
855
|
-
|
|
775
|
+
@wp.func
|
|
776
|
+
def cell_bounds(cell_arg: TetmeshCellArg, cell_index: ElementIndex):
|
|
777
|
+
vidx = cell_arg.tet_vertex_indices[cell_index]
|
|
778
|
+
p0 = cell_arg.positions[vidx[0]]
|
|
779
|
+
p1 = cell_arg.positions[vidx[1]]
|
|
780
|
+
p2 = cell_arg.positions[vidx[2]]
|
|
781
|
+
p3 = cell_arg.positions[vidx[3]]
|
|
782
|
+
|
|
783
|
+
return wp.min(wp.min(p0, p1), wp.min(p2, p3)), wp.max(wp.max(p0, p1), wp.max(p2, p3))
|