warp-lang 1.7.2__py3-none-macosx_10_13_universal2.whl → 1.8.0__py3-none-macosx_10_13_universal2.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/libwarp-clang.dylib +0 -0
- warp/bin/libwarp.dylib +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 +178 -166
- 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
|
@@ -19,7 +19,7 @@ import numpy as np
|
|
|
19
19
|
|
|
20
20
|
import warp as wp
|
|
21
21
|
from warp.fem import cache, utils
|
|
22
|
-
from warp.fem.types import
|
|
22
|
+
from warp.fem.types import OUTSIDE, Coords, ElementIndex, Sample, make_free_sample
|
|
23
23
|
|
|
24
24
|
from .element import Cube, Square
|
|
25
25
|
from .geometry import Geometry
|
|
@@ -107,6 +107,13 @@ class AdaptiveNanogrid(Geometry):
|
|
|
107
107
|
self._stacked_face_grid = None
|
|
108
108
|
self._stacked_face_count = 0
|
|
109
109
|
|
|
110
|
+
transform = self.transform
|
|
111
|
+
self._inverse_transform = wp.mat33f(np.linalg.inv(transform))
|
|
112
|
+
self._cell_volume = abs(np.linalg.det(transform))
|
|
113
|
+
self._face_areas = wp.vec3(
|
|
114
|
+
tuple(np.linalg.norm(np.cross(transform[:, k - 2], transform[:, k - 1])) for k in range(3))
|
|
115
|
+
)
|
|
116
|
+
|
|
110
117
|
@property
|
|
111
118
|
def cell_grid(self) -> wp.Volume:
|
|
112
119
|
return self._cell_grid
|
|
@@ -167,17 +174,17 @@ class AdaptiveNanogrid(Geometry):
|
|
|
167
174
|
@cache.cached_arg_value
|
|
168
175
|
def cell_arg_value(self, device) -> CellArg:
|
|
169
176
|
args = self.CellArg()
|
|
170
|
-
args
|
|
171
|
-
args.cell_ijk = self._cell_ijk
|
|
172
|
-
args.cell_level = self._cell_level
|
|
173
|
-
|
|
174
|
-
transform = self.transform
|
|
175
|
-
args.inverse_transform = wp.mat33f(np.linalg.inv(transform))
|
|
176
|
-
args.cell_volume = abs(np.linalg.det(transform))
|
|
177
|
-
args.level_count = self.level_count
|
|
178
|
-
|
|
177
|
+
self.fill_cell_arg(args, device)
|
|
179
178
|
return args
|
|
180
179
|
|
|
180
|
+
def fill_cell_arg(self, arg: CellArg, device):
|
|
181
|
+
arg.cell_grid = self._cell_grid.id
|
|
182
|
+
arg.cell_ijk = self._cell_ijk
|
|
183
|
+
arg.cell_level = self._cell_level
|
|
184
|
+
arg.inverse_transform = self._inverse_transform
|
|
185
|
+
arg.cell_volume = self._cell_volume
|
|
186
|
+
arg.level_count = self.level_count
|
|
187
|
+
|
|
181
188
|
@wp.func
|
|
182
189
|
def _cell_scale(args: CellArg, cell_index: int):
|
|
183
190
|
return float(1 << int(args.cell_level[cell_index]))
|
|
@@ -202,72 +209,41 @@ class AdaptiveNanogrid(Geometry):
|
|
|
202
209
|
scale = AdaptiveNanogrid._cell_scale(args, s.element_index)
|
|
203
210
|
return args.inverse_transform / scale
|
|
204
211
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
ijk = args.cell_ijk[cell_index]
|
|
208
|
-
return make_free_sample(cell_index, (uvw - wp.vec3(ijk)) / AdaptiveNanogrid._cell_scale(args, cell_index))
|
|
212
|
+
def supports_cell_lookup(self, device):
|
|
213
|
+
return True
|
|
209
214
|
|
|
210
215
|
@wp.func
|
|
211
|
-
def
|
|
212
|
-
|
|
213
|
-
ijk = wp.vec3i(int(wp.floor(uvw[0])), int(wp.floor(uvw[1])), int(wp.floor(uvw[2])))
|
|
214
|
-
cell_index = AdaptiveNanogrid.find_cell(args.cell_grid, ijk, args.level_count, args.cell_level)
|
|
215
|
-
|
|
216
|
-
if cell_index == -1:
|
|
217
|
-
coords = uvw - wp.vec3(ijk)
|
|
218
|
-
|
|
219
|
-
if wp.min(coords) == 0.0 or wp.max(coords) == 1.0:
|
|
220
|
-
il = wp.where(coords[0] > 0.5, 0, -1)
|
|
221
|
-
jl = wp.where(coords[1] > 0.5, 0, -1)
|
|
222
|
-
kl = wp.where(coords[2] > 0.5, 0, -1)
|
|
223
|
-
|
|
224
|
-
for n in range(8):
|
|
225
|
-
ni = n >> 2
|
|
226
|
-
nj = (n & 2) >> 1
|
|
227
|
-
nk = n & 1
|
|
228
|
-
nijk = ijk + wp.vec3i(ni + il, nj + jl, nk + kl)
|
|
229
|
-
|
|
230
|
-
coords = uvw - wp.vec3(nijk)
|
|
231
|
-
if wp.min(coords) >= 0.0 and wp.max(coords) <= 1.0:
|
|
232
|
-
cell_index = AdaptiveNanogrid.find_cell(args.cell_grid, nijk, args.level_count, args.cell_level)
|
|
233
|
-
if cell_index != -1:
|
|
234
|
-
return AdaptiveNanogrid._make_sample(args, cell_index, uvw)
|
|
235
|
-
|
|
236
|
-
return make_free_sample(NULL_ELEMENT_INDEX, Coords(OUTSIDE))
|
|
237
|
-
|
|
238
|
-
return AdaptiveNanogrid._make_sample(args, cell_index, uvw)
|
|
216
|
+
def _lookup_cell_index(args: AdaptiveNanogridCellArg, i: int, j: int, k: int):
|
|
217
|
+
return AdaptiveNanogrid.find_cell(args.cell_grid, wp.vec3i(i, j, k), args.level_count, args.cell_level)
|
|
239
218
|
|
|
240
219
|
@wp.func
|
|
241
|
-
def
|
|
242
|
-
|
|
220
|
+
def _cell_coordinates_local(args: AdaptiveNanogridCellArg, cell_index: int, uvw: wp.vec3):
|
|
221
|
+
ijk = wp.vec3(args.cell_ijk[cell_index])
|
|
222
|
+
rel_pos = uvw - ijk
|
|
223
|
+
scale = AdaptiveNanogrid._cell_scale(args, cell_index)
|
|
224
|
+
return rel_pos / scale
|
|
243
225
|
|
|
244
|
-
|
|
245
|
-
|
|
226
|
+
@wp.func
|
|
227
|
+
def _cell_closest_point_local(args: AdaptiveNanogridCellArg, cell_index: int, uvw: wp.vec3):
|
|
228
|
+
ijk = wp.vec3(args.cell_ijk[cell_index])
|
|
229
|
+
rel_pos = uvw - ijk
|
|
230
|
+
scale = AdaptiveNanogrid._cell_scale(args, cell_index)
|
|
231
|
+
coords = wp.min(wp.max(rel_pos / scale, wp.vec3(0.0)), wp.vec3(1.0))
|
|
232
|
+
return wp.length_sq(wp.volume_index_to_world_dir(args.cell_grid, coords * scale - rel_pos)), coords
|
|
246
233
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
234
|
+
@wp.func
|
|
235
|
+
def cell_coordinates(args: AdaptiveNanogridCellArg, cell_index: int, pos: wp.vec3):
|
|
236
|
+
uvw = wp.volume_world_to_index(args.cell_grid, pos) + wp.vec3(0.5)
|
|
237
|
+
return AdaptiveNanogrid._cell_coordinates_local(args, cell_index, uvw)
|
|
250
238
|
|
|
251
|
-
|
|
239
|
+
@wp.func
|
|
240
|
+
def cell_closest_point(args: AdaptiveNanogridCellArg, cell_index: int, pos: wp.vec3):
|
|
252
241
|
uvw = wp.volume_world_to_index(args.cell_grid, pos) + wp.vec3(0.5)
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
cell_idx = AdaptiveNanogrid.find_cell(args.cell_grid, nijk, args.level_count, args.cell_level)
|
|
259
|
-
if cell_idx != -1:
|
|
260
|
-
nijk = args.cell_ijk[cell_idx]
|
|
261
|
-
scale = AdaptiveNanogrid._cell_scale(args, cell_idx)
|
|
262
|
-
coords = (uvw - wp.vec3(nijk)) / scale
|
|
263
|
-
dist, proj_coords = Nanogrid._project_on_voxel_at_origin(coords)
|
|
264
|
-
dist *= scale
|
|
265
|
-
if dist <= closest_dist:
|
|
266
|
-
closest_dist = dist
|
|
267
|
-
closest_voxel = cell_idx
|
|
268
|
-
closest_coords = proj_coords
|
|
269
|
-
|
|
270
|
-
return make_free_sample(closest_voxel, closest_coords)
|
|
242
|
+
dist, coords = AdaptiveNanogrid._cell_closest_point_local(args, cell_index, uvw)
|
|
243
|
+
return coords, dist
|
|
244
|
+
|
|
245
|
+
def make_filtered_cell_lookup(self, filter_func: wp.Function = None):
|
|
246
|
+
return Nanogrid._make_filtered_cell_lookup(self, filter_func)
|
|
271
247
|
|
|
272
248
|
@wp.func
|
|
273
249
|
def cell_measure(args: CellArg, s: Sample):
|
|
@@ -280,6 +256,7 @@ class AdaptiveNanogrid(Geometry):
|
|
|
280
256
|
|
|
281
257
|
SideIndexArg = Nanogrid.SideIndexArg
|
|
282
258
|
side_index_arg_value = Nanogrid.side_index_arg_value
|
|
259
|
+
fill_side_index_arg = Nanogrid.fill_side_index_arg
|
|
283
260
|
|
|
284
261
|
SideArg = AdaptiveNanogridSideArg
|
|
285
262
|
|
|
@@ -289,20 +266,20 @@ class AdaptiveNanogrid(Geometry):
|
|
|
289
266
|
|
|
290
267
|
@cache.cached_arg_value
|
|
291
268
|
def side_arg_value(self, device) -> SideArg:
|
|
292
|
-
self._ensure_face_grid()
|
|
293
|
-
|
|
294
269
|
args = self.SideArg()
|
|
295
|
-
|
|
296
|
-
args.face_ijk = self._face_ijk.to(device)
|
|
297
|
-
args.face_flags = self._face_flags.to(device)
|
|
298
|
-
args.face_cell_indices = self._face_cell_indices.to(device)
|
|
299
|
-
transform = self.transform
|
|
300
|
-
args.face_areas = wp.vec3(
|
|
301
|
-
tuple(np.linalg.norm(np.cross(transform[:, k - 2], transform[:, k - 1])) for k in range(3))
|
|
302
|
-
)
|
|
270
|
+
self.fill_side_arg(args, device)
|
|
303
271
|
|
|
304
272
|
return args
|
|
305
273
|
|
|
274
|
+
def fill_side_arg(self, arg: SideArg, device):
|
|
275
|
+
self._ensure_face_grid()
|
|
276
|
+
|
|
277
|
+
self.fill_cell_arg(arg.cell_arg, device)
|
|
278
|
+
arg.face_ijk = self._face_ijk.to(device)
|
|
279
|
+
arg.face_flags = self._face_flags.to(device)
|
|
280
|
+
arg.face_cell_indices = self._face_cell_indices.to(device)
|
|
281
|
+
arg.face_areas = self._face_areas
|
|
282
|
+
|
|
306
283
|
@wp.func
|
|
307
284
|
def boundary_side_index(args: SideIndexArg, boundary_side_index: int):
|
|
308
285
|
return args.boundary_face_indices[boundary_side_index]
|
|
@@ -320,9 +297,10 @@ class AdaptiveNanogrid(Geometry):
|
|
|
320
297
|
ijk = args.face_ijk[s.element_index]
|
|
321
298
|
flags = args.face_flags[s.element_index]
|
|
322
299
|
axis = Nanogrid._get_face_axis(flags)
|
|
300
|
+
flip = Nanogrid._get_face_inner_offset(flags)
|
|
323
301
|
scale = AdaptiveNanogrid._get_face_scale(flags)
|
|
324
302
|
|
|
325
|
-
uvw = wp.vec3(ijk) + scale * Nanogrid._side_to_cell_coords(axis, 0.0, s.element_coords)
|
|
303
|
+
uvw = wp.vec3(ijk) + scale * Nanogrid._side_to_cell_coords(axis, flip, 0.0, s.element_coords)
|
|
326
304
|
|
|
327
305
|
cell_grid = args.cell_arg.cell_grid
|
|
328
306
|
return wp.volume_index_to_world(cell_grid, uvw - wp.vec3(0.5))
|
|
@@ -391,9 +369,10 @@ class AdaptiveNanogrid(Geometry):
|
|
|
391
369
|
def side_inner_cell_coords(args: SideArg, side_index: ElementIndex, side_coords: Coords):
|
|
392
370
|
flags = args.face_flags[side_index]
|
|
393
371
|
axis = Nanogrid._get_face_axis(flags)
|
|
372
|
+
flip = Nanogrid._get_face_inner_offset(flags)
|
|
394
373
|
offset = Nanogrid._get_face_inner_offset(flags)
|
|
395
374
|
|
|
396
|
-
same_level_cell_coords = Nanogrid._side_to_cell_coords(axis, 1.0 - float(offset), side_coords)
|
|
375
|
+
same_level_cell_coords = Nanogrid._side_to_cell_coords(axis, flip, 1.0 - float(offset), side_coords)
|
|
397
376
|
same_level_cell_ijk = args.face_ijk[side_index]
|
|
398
377
|
side_level = AdaptiveNanogrid._get_face_level(flags)
|
|
399
378
|
same_level_cell_ijk[axis] += (offset - 1) << side_level
|
|
@@ -410,9 +389,10 @@ class AdaptiveNanogrid(Geometry):
|
|
|
410
389
|
def side_outer_cell_coords(args: SideArg, side_index: ElementIndex, side_coords: Coords):
|
|
411
390
|
flags = args.face_flags[side_index]
|
|
412
391
|
axis = Nanogrid._get_face_axis(flags)
|
|
392
|
+
flip = Nanogrid._get_face_inner_offset(flags)
|
|
413
393
|
offset = Nanogrid._get_face_outer_offset(flags)
|
|
414
394
|
|
|
415
|
-
same_level_cell_coords = Nanogrid._side_to_cell_coords(axis, float(offset), side_coords)
|
|
395
|
+
same_level_cell_coords = Nanogrid._side_to_cell_coords(axis, flip, float(offset), side_coords)
|
|
416
396
|
same_level_cell_ijk = args.face_ijk[side_index]
|
|
417
397
|
side_level = AdaptiveNanogrid._get_face_level(flags)
|
|
418
398
|
same_level_cell_ijk[axis] -= offset << side_level
|
|
@@ -434,6 +414,7 @@ class AdaptiveNanogrid(Geometry):
|
|
|
434
414
|
):
|
|
435
415
|
flags = args.face_flags[side_index]
|
|
436
416
|
axis = Nanogrid._get_face_axis(flags)
|
|
417
|
+
flip = Nanogrid._get_face_inner_offset(flags)
|
|
437
418
|
side_level = AdaptiveNanogrid._get_face_level(flags)
|
|
438
419
|
cell_level = int(args.cell_arg.cell_level[element_index])
|
|
439
420
|
|
|
@@ -450,11 +431,35 @@ class AdaptiveNanogrid(Geometry):
|
|
|
450
431
|
and wp.max(same_level_cell_coords) <= 1.0
|
|
451
432
|
)
|
|
452
433
|
|
|
453
|
-
return wp.where(
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
434
|
+
return wp.where(on_side, Nanogrid._cell_to_side_coords(axis, flip, same_level_cell_coords), Coords(OUTSIDE))
|
|
435
|
+
|
|
436
|
+
@wp.func
|
|
437
|
+
def side_coordinates(args: SideArg, side_index: int, pos: wp.vec3):
|
|
438
|
+
cell_arg = args.cell_arg
|
|
439
|
+
|
|
440
|
+
ijk = args.face_ijk[side_index]
|
|
441
|
+
fine_cell_coords = wp.volume_world_to_index(cell_arg.cell_grid, pos) + wp.vec3(0.5) - wp.vec3(ijk)
|
|
442
|
+
|
|
443
|
+
flags = args.face_flags[side_index]
|
|
444
|
+
side_level = AdaptiveNanogrid._get_face_level(flags)
|
|
445
|
+
axis = Nanogrid._get_face_axis(flags)
|
|
446
|
+
flip = Nanogrid._get_face_inner_offset(flags)
|
|
447
|
+
|
|
448
|
+
return Nanogrid._cell_to_side_coords(axis, flip, fine_cell_coords / float(1 << side_level))
|
|
449
|
+
|
|
450
|
+
@wp.func
|
|
451
|
+
def side_closest_point(args: SideArg, side_index: int, pos: wp.vec3):
|
|
452
|
+
coords = AdaptiveNanogrid.side_coordinates(args, side_index, pos)
|
|
453
|
+
|
|
454
|
+
proj_coords = Coords(wp.clamp(coords[0], 0.0, 1.0), wp.clamp(coords[1], 0.0, 1.0), 0.0)
|
|
455
|
+
|
|
456
|
+
flags = args.face_flags[side_index]
|
|
457
|
+
axis = Nanogrid._get_face_axis(flags)
|
|
458
|
+
flip = Nanogrid._get_face_inner_offset(flags)
|
|
459
|
+
side_level = AdaptiveNanogrid._get_face_level(flags)
|
|
460
|
+
cell_coord_offset = Nanogrid._side_to_cell_coords(axis, flip, 0, coords - proj_coords) * float(1 << side_level)
|
|
461
|
+
|
|
462
|
+
return proj_coords, wp.length_sq(wp.volume_index_to_world_dir(args.cell_grid, cell_coord_offset))
|
|
458
463
|
|
|
459
464
|
def _build_face_grid(self, temporary_store: Optional[cache.TemporaryStore] = None):
|
|
460
465
|
device = self._cell_grid.device
|
|
@@ -82,3 +82,16 @@ def project_on_tet_at_origin(q: wp.vec3, e1: wp.vec3, e2: wp.vec3, e3: wp.vec3):
|
|
|
82
82
|
return dmin, Coords(s31[2], 0.0, s31[1])
|
|
83
83
|
else:
|
|
84
84
|
return dmin, s123
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@wp.func
|
|
88
|
+
def project_on_box_at_origin(coords: wp.vec3, sizes: wp.vec3):
|
|
89
|
+
proj_coords = wp.min(wp.max(coords, wp.vec3(0.0)), sizes)
|
|
90
|
+
return wp.length_sq(coords - proj_coords), wp.cw_div(proj_coords, sizes)
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@wp.func
|
|
94
|
+
def project_on_box_at_origin(coords: wp.vec2, sizes: wp.vec2):
|
|
95
|
+
proj_coords = wp.min(wp.max(coords, wp.vec2(0.0)), sizes)
|
|
96
|
+
norm_coords = wp.cw_div(proj_coords, sizes)
|
|
97
|
+
return wp.length_sq(coords - proj_coords), Coords(norm_coords[0], norm_coords[1], 0.0)
|
|
@@ -13,9 +13,12 @@
|
|
|
13
13
|
# See the License for the specific language governing permissions and
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
|
+
from typing import ClassVar
|
|
17
|
+
|
|
16
18
|
import warp as wp
|
|
17
19
|
from warp.fem import cache
|
|
18
|
-
from warp.fem.
|
|
20
|
+
from warp.fem.polynomial import Polynomial
|
|
21
|
+
from warp.fem.types import Coords, ElementIndex, Sample, make_free_sample
|
|
19
22
|
|
|
20
23
|
from .geometry import Geometry
|
|
21
24
|
|
|
@@ -23,7 +26,31 @@ _mat32 = wp.mat(shape=(3, 2), dtype=float)
|
|
|
23
26
|
|
|
24
27
|
|
|
25
28
|
class DeformedGeometry(Geometry):
|
|
26
|
-
|
|
29
|
+
_dynamic_attribute_constructors_phase_1: ClassVar = {
|
|
30
|
+
"CellArg": lambda obj: obj._make_cell_arg(),
|
|
31
|
+
"SideArg": lambda obj: obj._make_side_arg(),
|
|
32
|
+
"cell_position": lambda obj: obj._make_cell_position(),
|
|
33
|
+
"cell_deformation_gradient": lambda obj: obj._make_cell_deformation_gradient(),
|
|
34
|
+
"side_to_cell_arg": lambda obj: obj._make_side_to_cell_arg(),
|
|
35
|
+
"side_position": lambda obj: obj._make_side_position(),
|
|
36
|
+
"side_deformation_gradient": lambda obj: obj._make_side_deformation_gradient(),
|
|
37
|
+
"side_inner_cell_index": lambda obj: obj._make_side_inner_cell_index(),
|
|
38
|
+
"side_outer_cell_index": lambda obj: obj._make_side_outer_cell_index(),
|
|
39
|
+
"side_inner_cell_coords": lambda obj: obj._make_side_inner_cell_coords(),
|
|
40
|
+
"side_outer_cell_coords": lambda obj: obj._make_side_outer_cell_coords(),
|
|
41
|
+
"side_from_cell_coords": lambda obj: obj._make_side_from_cell_coords(),
|
|
42
|
+
"cell_bvh_id": lambda obj: obj._make_cell_bvh_id(),
|
|
43
|
+
"cell_bounds": lambda obj: obj._make_cell_bounds(),
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
_dynamic_attribute_constructors_phase_2: ClassVar = {
|
|
47
|
+
"cell_closest_point": lambda obj: obj._make_cell_closest_point(),
|
|
48
|
+
"side_closest_point": lambda obj: obj._make_side_closest_point(),
|
|
49
|
+
"cell_coordinates": lambda obj: obj._make_cell_coordinates(),
|
|
50
|
+
"side_coordinates": lambda obj: obj._make_side_coordinates(),
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
def __init__(self, field: "wp.fem.field.GeometryField", relative: bool = True, build_bvh: bool = False):
|
|
27
54
|
"""Constructs a Deformed Geometry from a displacement or absolute position field defined over a base geometry.
|
|
28
55
|
The deformation field does not need to be isoparameteric.
|
|
29
56
|
|
|
@@ -33,10 +60,7 @@ class DeformedGeometry(Geometry):
|
|
|
33
60
|
from warp.fem.field import DiscreteField, GeometryField
|
|
34
61
|
|
|
35
62
|
if isinstance(field, DiscreteField):
|
|
36
|
-
if (
|
|
37
|
-
not wp.types.type_is_vector(field.dtype)
|
|
38
|
-
or wp.types.type_length(field.dtype) != field.geometry.dimension
|
|
39
|
-
):
|
|
63
|
+
if not wp.types.type_is_vector(field.dtype) or wp.types.type_size(field.dtype) != field.geometry.dimension:
|
|
40
64
|
raise ValueError(
|
|
41
65
|
"Invalid value type for position field, must be vector-valued with same dimension as underlying geometry"
|
|
42
66
|
)
|
|
@@ -46,14 +70,10 @@ class DeformedGeometry(Geometry):
|
|
|
46
70
|
self._relative = relative
|
|
47
71
|
|
|
48
72
|
self.field: GeometryField = field
|
|
73
|
+
self.field_trace = field.trace()
|
|
49
74
|
self.dimension = self.base.dimension
|
|
50
75
|
|
|
51
|
-
self.CellArg = self.field.ElementEvalArg
|
|
52
|
-
|
|
53
|
-
self.field_trace = field.trace()
|
|
54
|
-
self.SideArg = self._make_side_arg()
|
|
55
76
|
self.SideIndexArg = self.base.SideIndexArg
|
|
56
|
-
|
|
57
77
|
self.cell_count = self.base.cell_count
|
|
58
78
|
self.vertex_count = self.base.vertex_count
|
|
59
79
|
self.side_count = self.base.side_count
|
|
@@ -62,23 +82,18 @@ class DeformedGeometry(Geometry):
|
|
|
62
82
|
self.reference_side = self.base.reference_side
|
|
63
83
|
|
|
64
84
|
self.side_index_arg_value = self.base.side_index_arg_value
|
|
65
|
-
|
|
66
|
-
self.cell_position = self._make_cell_position()
|
|
67
|
-
self.cell_deformation_gradient = self._make_cell_deformation_gradient()
|
|
68
|
-
|
|
85
|
+
self.fill_side_index_arg = self.base.fill_side_index_arg
|
|
69
86
|
self.boundary_side_index = self.base.boundary_side_index
|
|
70
87
|
|
|
71
|
-
self
|
|
72
|
-
self.side_position = self._make_side_position()
|
|
73
|
-
self.side_deformation_gradient = self._make_side_deformation_gradient()
|
|
74
|
-
self.side_inner_cell_index = self._make_side_inner_cell_index()
|
|
75
|
-
self.side_outer_cell_index = self._make_side_outer_cell_index()
|
|
76
|
-
self.side_inner_cell_coords = self._make_side_inner_cell_coords()
|
|
77
|
-
self.side_outer_cell_coords = self._make_side_outer_cell_coords()
|
|
78
|
-
self.side_from_cell_coords = self._make_side_from_cell_coords()
|
|
88
|
+
cache.setup_dynamic_attributes(self, constructors=self._dynamic_attribute_constructors_phase_1)
|
|
79
89
|
|
|
80
90
|
self._make_default_dependent_implementations()
|
|
81
91
|
|
|
92
|
+
cache.setup_dynamic_attributes(self, constructors=self._dynamic_attribute_constructors_phase_2)
|
|
93
|
+
|
|
94
|
+
if build_bvh:
|
|
95
|
+
self.build_bvh(self.field.dof_values.device)
|
|
96
|
+
|
|
82
97
|
@property
|
|
83
98
|
def name(self) -> str:
|
|
84
99
|
return f"DefGeo_{self.field.name}_{'rel' if self._relative else 'abs'}"
|
|
@@ -89,35 +104,49 @@ class DeformedGeometry(Geometry):
|
|
|
89
104
|
|
|
90
105
|
# Geometry device interface
|
|
91
106
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
107
|
+
def _make_cell_arg(self):
|
|
108
|
+
@cache.dynamic_struct(suffix=self.name)
|
|
109
|
+
class CellArg:
|
|
110
|
+
base_arg: self.base.CellArg
|
|
111
|
+
field_arg: self.field.EvalArg
|
|
112
|
+
cell_bvh: wp.uint64
|
|
95
113
|
|
|
96
|
-
|
|
97
|
-
args.eval_arg = self.field.eval_arg_value(device)
|
|
114
|
+
return CellArg
|
|
98
115
|
|
|
116
|
+
def cell_arg_value(self, device) -> "DeformedGeometry.CellArg":
|
|
117
|
+
args = self.CellArg()
|
|
118
|
+
self.fill_cell_arg(args, device)
|
|
99
119
|
return args
|
|
100
120
|
|
|
121
|
+
def fill_cell_arg(self, args: "DeformedGeometry.CellArg", device):
|
|
122
|
+
self.base.fill_cell_arg(args.base_arg, device)
|
|
123
|
+
self.field.fill_eval_arg(args.field_arg, device)
|
|
124
|
+
args.cell_bvh = self.bvh_id(device)
|
|
125
|
+
|
|
101
126
|
def _make_cell_position(self):
|
|
102
127
|
@cache.dynamic_func(suffix=self.name)
|
|
103
128
|
def cell_position_absolute(cell_arg: self.CellArg, s: Sample):
|
|
104
|
-
|
|
129
|
+
field_arg = self.field.ElementEvalArg(cell_arg.base_arg, cell_arg.field_arg)
|
|
130
|
+
return self.field.eval_inner(field_arg, s)
|
|
105
131
|
|
|
106
132
|
@cache.dynamic_func(suffix=self.name)
|
|
107
133
|
def cell_position(cell_arg: self.CellArg, s: Sample):
|
|
108
|
-
|
|
134
|
+
field_arg = self.field.ElementEvalArg(cell_arg.base_arg, cell_arg.field_arg)
|
|
135
|
+
return self.field.eval_inner(field_arg, s) + self.base.cell_position(cell_arg.base_arg, s)
|
|
109
136
|
|
|
110
137
|
return cell_position if self._relative else cell_position_absolute
|
|
111
138
|
|
|
112
139
|
def _make_cell_deformation_gradient(self):
|
|
113
140
|
@cache.dynamic_func(suffix=self.name)
|
|
114
141
|
def cell_deformation_gradient_absolute(cell_arg: self.CellArg, s: Sample):
|
|
115
|
-
|
|
142
|
+
field_arg = self.field.ElementEvalArg(cell_arg.base_arg, cell_arg.field_arg)
|
|
143
|
+
return self.field.eval_reference_grad_inner(field_arg, s)
|
|
116
144
|
|
|
117
145
|
@cache.dynamic_func(suffix=self.name)
|
|
118
146
|
def cell_deformation_gradient(cell_arg: self.CellArg, s: Sample):
|
|
119
|
-
|
|
120
|
-
|
|
147
|
+
field_arg = self.field.ElementEvalArg(cell_arg.base_arg, cell_arg.field_arg)
|
|
148
|
+
return self.field.eval_reference_grad_inner(field_arg, s) + self.base.cell_deformation_gradient(
|
|
149
|
+
cell_arg.base_arg, s
|
|
121
150
|
)
|
|
122
151
|
|
|
123
152
|
return cell_deformation_gradient if self._relative else cell_deformation_gradient_absolute
|
|
@@ -128,19 +157,21 @@ class DeformedGeometry(Geometry):
|
|
|
128
157
|
base_arg: self.base.SideArg
|
|
129
158
|
trace_arg: self.field_trace.EvalArg
|
|
130
159
|
field_arg: self.field.EvalArg
|
|
160
|
+
cell_bvh: wp.uint64
|
|
131
161
|
|
|
132
162
|
return SideArg
|
|
133
163
|
|
|
134
|
-
@cache.cached_arg_value
|
|
135
164
|
def side_arg_value(self, device) -> "DeformedGeometry.SideArg":
|
|
136
165
|
args = self.SideArg()
|
|
137
|
-
|
|
138
|
-
args.base_arg = self.base.side_arg_value(device)
|
|
139
|
-
args.field_arg = self.field.eval_arg_value(device)
|
|
140
|
-
args.trace_arg = self.field_trace.eval_arg_value(device)
|
|
141
|
-
|
|
166
|
+
self.fill_side_arg(args, device)
|
|
142
167
|
return args
|
|
143
168
|
|
|
169
|
+
def fill_side_arg(self, args: "DeformedGeometry.SideArg", device):
|
|
170
|
+
self.base.fill_side_arg(args.base_arg, device)
|
|
171
|
+
self.field.fill_eval_arg(args.field_arg, device)
|
|
172
|
+
self.field_trace.fill_eval_arg(args.trace_arg, device)
|
|
173
|
+
args.cell_bvh = self.bvh_id(device)
|
|
174
|
+
|
|
144
175
|
def _make_side_position(self):
|
|
145
176
|
@cache.dynamic_func(suffix=self.name)
|
|
146
177
|
def side_position_absolute(args: self.SideArg, s: Sample):
|
|
@@ -216,6 +247,37 @@ class DeformedGeometry(Geometry):
|
|
|
216
247
|
def _make_side_to_cell_arg(self):
|
|
217
248
|
@cache.dynamic_func(suffix=self.name)
|
|
218
249
|
def side_to_cell_arg(side_arg: self.SideArg):
|
|
219
|
-
return self.CellArg(self.base.side_to_cell_arg(side_arg.base_arg), side_arg.field_arg)
|
|
250
|
+
return self.CellArg(self.base.side_to_cell_arg(side_arg.base_arg), side_arg.field_arg, side_arg.cell_bvh)
|
|
220
251
|
|
|
221
252
|
return side_to_cell_arg
|
|
253
|
+
|
|
254
|
+
def _make_cell_bvh_id(self):
|
|
255
|
+
@cache.dynamic_func(suffix=self.name)
|
|
256
|
+
def cell_bvh_id(cell_arg: self.CellArg):
|
|
257
|
+
return cell_arg.cell_bvh
|
|
258
|
+
|
|
259
|
+
return cell_bvh_id
|
|
260
|
+
|
|
261
|
+
def _make_cell_bounds(self):
|
|
262
|
+
points, _weights = self.reference_cell().instantiate_quadrature(
|
|
263
|
+
order=self.field.degree, family=Polynomial.LOBATTO_GAUSS_LEGENDRE
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
points = cache.cached_mat_type((len(points), 3), dtype=float)(points)
|
|
267
|
+
point_count = len(points)
|
|
268
|
+
|
|
269
|
+
@cache.dynamic_func(suffix=self.name)
|
|
270
|
+
def cell_bounds(cell_arg: self.CellArg, cell_index: ElementIndex):
|
|
271
|
+
lower = wp.vec3(1.0e8)
|
|
272
|
+
upper = wp.vec3(-1.0e8)
|
|
273
|
+
for k in range(point_count):
|
|
274
|
+
pos = self.cell_position(cell_arg, make_free_sample(cell_index, points[k]))
|
|
275
|
+
lower = wp.min(lower, pos)
|
|
276
|
+
upper = wp.max(upper, pos)
|
|
277
|
+
|
|
278
|
+
# pad the BBox to account for potential overflows
|
|
279
|
+
pad = 0.25 * (upper - lower)
|
|
280
|
+
|
|
281
|
+
return lower - pad, upper + pad
|
|
282
|
+
|
|
283
|
+
return cell_bounds
|
warp/fem/geometry/element.py
CHANGED
|
@@ -15,14 +15,18 @@
|
|
|
15
15
|
|
|
16
16
|
from typing import List, Tuple
|
|
17
17
|
|
|
18
|
+
import warp as wp
|
|
18
19
|
from warp.fem.polynomial import Polynomial, quadrature_1d
|
|
19
20
|
from warp.fem.types import Coords
|
|
20
21
|
|
|
22
|
+
_vec1 = wp.types.vector(length=1, dtype=float)
|
|
23
|
+
|
|
21
24
|
|
|
22
25
|
class Element:
|
|
23
26
|
dimension = 0
|
|
24
27
|
"""Intrinsic dimension of the element"""
|
|
25
28
|
|
|
29
|
+
@staticmethod
|
|
26
30
|
def measure() -> float:
|
|
27
31
|
"""Measure (area, volume, ...) of the reference element"""
|
|
28
32
|
raise NotImplementedError
|
|
@@ -32,10 +36,32 @@ class Element:
|
|
|
32
36
|
"""Returns a quadrature of a given order for a prototypical element"""
|
|
33
37
|
raise NotImplementedError
|
|
34
38
|
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
@classmethod
|
|
40
|
+
def center(cls) -> Coords:
|
|
41
|
+
"""Returns the coordinates for the center of the element"""
|
|
42
|
+
coords, _ = cls.instantiate_quadrature(order=0, family=None)
|
|
37
43
|
return coords[0]
|
|
38
44
|
|
|
45
|
+
@wp.func
|
|
46
|
+
def project(v: Coords):
|
|
47
|
+
"""project coordinates so that they belong to the element"""
|
|
48
|
+
return wp.min(wp.max(v, Coords(0.0)), Coords(1.0))
|
|
49
|
+
|
|
50
|
+
@wp.func
|
|
51
|
+
def coord_delta(ref_delta: wp.vec3):
|
|
52
|
+
"""Transform a delta in reference space to element coords"""
|
|
53
|
+
return ref_delta
|
|
54
|
+
|
|
55
|
+
@wp.func
|
|
56
|
+
def coord_delta(ref_delta: wp.vec2):
|
|
57
|
+
"""Transform a delta in reference space to element coords"""
|
|
58
|
+
return Coords(ref_delta[0], ref_delta[1], 0.0)
|
|
59
|
+
|
|
60
|
+
@wp.func
|
|
61
|
+
def coord_delta(ref_delta: _vec1):
|
|
62
|
+
"""Transform a delta in reference space to element coords"""
|
|
63
|
+
return Coords(ref_delta[0], 0.0, 0.0)
|
|
64
|
+
|
|
39
65
|
|
|
40
66
|
def _point_count_from_order(order: int, family: Polynomial):
|
|
41
67
|
if family == Polynomial.GAUSS_LEGENDRE:
|
|
@@ -454,6 +480,17 @@ class Triangle(Element):
|
|
|
454
480
|
|
|
455
481
|
return coords, weights
|
|
456
482
|
|
|
483
|
+
@wp.func
|
|
484
|
+
def project(v: Coords):
|
|
485
|
+
n = wp.max(0.0, (v[0] + v[1] - 1.0) * 0.5)
|
|
486
|
+
a = wp.clamp(v[0] - n, 0.0, 1.0)
|
|
487
|
+
b = wp.clamp(v[1] - n, 0.0, 1.0)
|
|
488
|
+
return Coords(a, b, 1.0 - (a + b))
|
|
489
|
+
|
|
490
|
+
@wp.func
|
|
491
|
+
def coord_delta(ref_delta: wp.vec2):
|
|
492
|
+
return Coords(-ref_delta[0] - ref_delta[1], ref_delta[0], ref_delta[1])
|
|
493
|
+
|
|
457
494
|
|
|
458
495
|
class Tetrahedron(Element):
|
|
459
496
|
dimension = 3
|
|
@@ -774,3 +811,20 @@ class Tetrahedron(Element):
|
|
|
774
811
|
raise NotImplementedError
|
|
775
812
|
|
|
776
813
|
return coords, weights
|
|
814
|
+
|
|
815
|
+
@wp.func
|
|
816
|
+
def project(v: Coords):
|
|
817
|
+
# project on 1-2-3 half-space
|
|
818
|
+
n = wp.max(0.0, (v[0] + v[1] + v[2] - 1.0) / 3.0)
|
|
819
|
+
c = v - Coords(n)
|
|
820
|
+
|
|
821
|
+
# project on 1-2, 2-3, 3-1 half-spaces
|
|
822
|
+
n = wp.max(0.0, (c[0] + c[1] - 1.0) * 0.5)
|
|
823
|
+
c = c - Coords(n, n, 0.0)
|
|
824
|
+
n = wp.max(0.0, (c[1] + c[2] - 1.0) * 0.5)
|
|
825
|
+
c = c - Coords(0.0, n, n)
|
|
826
|
+
n = wp.max(0.0, (c[2] + c[0] - 1.0) * 0.5)
|
|
827
|
+
c = c - Coords(n, 0.0, n)
|
|
828
|
+
|
|
829
|
+
# project on cube
|
|
830
|
+
return Element.project(c)
|