warp-lang 1.2.1__py3-none-manylinux2014_x86_64.whl → 1.3.0__py3-none-manylinux2014_x86_64.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 +8 -6
- warp/autograd.py +823 -0
- warp/bin/warp.so +0 -0
- warp/build.py +6 -2
- warp/builtins.py +1410 -886
- warp/codegen.py +503 -166
- warp/config.py +48 -18
- warp/context.py +401 -199
- warp/dlpack.py +8 -0
- warp/examples/assets/bunny.usd +0 -0
- warp/examples/benchmarks/benchmark_cloth_warp.py +1 -1
- warp/examples/benchmarks/benchmark_interop_torch.py +158 -0
- warp/examples/benchmarks/benchmark_launches.py +1 -1
- warp/examples/core/example_cupy.py +78 -0
- warp/examples/fem/example_apic_fluid.py +17 -36
- warp/examples/fem/example_burgers.py +9 -18
- warp/examples/fem/example_convection_diffusion.py +7 -17
- warp/examples/fem/example_convection_diffusion_dg.py +27 -47
- warp/examples/fem/example_deformed_geometry.py +11 -22
- warp/examples/fem/example_diffusion.py +7 -18
- warp/examples/fem/example_diffusion_3d.py +24 -28
- warp/examples/fem/example_diffusion_mgpu.py +7 -14
- warp/examples/fem/example_magnetostatics.py +190 -0
- warp/examples/fem/example_mixed_elasticity.py +111 -80
- warp/examples/fem/example_navier_stokes.py +30 -34
- warp/examples/fem/example_nonconforming_contact.py +290 -0
- warp/examples/fem/example_stokes.py +17 -32
- warp/examples/fem/example_stokes_transfer.py +12 -21
- warp/examples/fem/example_streamlines.py +350 -0
- warp/examples/fem/utils.py +936 -0
- warp/fabric.py +5 -2
- warp/fem/__init__.py +13 -3
- warp/fem/cache.py +161 -11
- warp/fem/dirichlet.py +37 -28
- warp/fem/domain.py +105 -14
- warp/fem/field/__init__.py +14 -3
- warp/fem/field/field.py +454 -11
- warp/fem/field/nodal_field.py +33 -18
- warp/fem/geometry/deformed_geometry.py +50 -15
- warp/fem/geometry/hexmesh.py +12 -24
- warp/fem/geometry/nanogrid.py +106 -31
- warp/fem/geometry/quadmesh_2d.py +6 -11
- warp/fem/geometry/tetmesh.py +103 -61
- warp/fem/geometry/trimesh_2d.py +98 -47
- warp/fem/integrate.py +231 -186
- warp/fem/operator.py +14 -9
- warp/fem/quadrature/pic_quadrature.py +35 -9
- warp/fem/quadrature/quadrature.py +119 -32
- warp/fem/space/basis_space.py +98 -22
- warp/fem/space/collocated_function_space.py +3 -1
- warp/fem/space/function_space.py +7 -2
- warp/fem/space/grid_2d_function_space.py +3 -3
- warp/fem/space/grid_3d_function_space.py +4 -4
- warp/fem/space/hexmesh_function_space.py +3 -2
- warp/fem/space/nanogrid_function_space.py +12 -14
- warp/fem/space/partition.py +45 -47
- warp/fem/space/restriction.py +19 -16
- warp/fem/space/shape/cube_shape_function.py +91 -3
- warp/fem/space/shape/shape_function.py +7 -0
- warp/fem/space/shape/square_shape_function.py +32 -0
- warp/fem/space/shape/tet_shape_function.py +11 -7
- warp/fem/space/shape/triangle_shape_function.py +10 -1
- warp/fem/space/topology.py +116 -42
- warp/fem/types.py +8 -1
- warp/fem/utils.py +301 -83
- warp/native/array.h +16 -0
- warp/native/builtin.h +0 -15
- warp/native/cuda_util.cpp +14 -6
- warp/native/exports.h +1348 -1308
- warp/native/quat.h +79 -0
- warp/native/rand.h +27 -4
- warp/native/sparse.cpp +83 -81
- warp/native/sparse.cu +381 -453
- warp/native/vec.h +64 -0
- warp/native/volume.cpp +40 -49
- warp/native/volume_builder.cu +2 -3
- warp/native/volume_builder.h +12 -17
- warp/native/warp.cu +3 -3
- warp/native/warp.h +69 -59
- warp/render/render_opengl.py +17 -9
- warp/sim/articulation.py +117 -17
- warp/sim/collide.py +35 -29
- warp/sim/model.py +123 -18
- warp/sim/render.py +3 -1
- warp/sparse.py +867 -203
- warp/stubs.py +312 -541
- warp/tape.py +29 -1
- warp/tests/disabled_kinematics.py +1 -1
- warp/tests/test_adam.py +1 -1
- warp/tests/test_arithmetic.py +1 -1
- warp/tests/test_array.py +58 -1
- warp/tests/test_array_reduce.py +1 -1
- warp/tests/test_async.py +1 -1
- warp/tests/test_atomic.py +1 -1
- warp/tests/test_bool.py +1 -1
- warp/tests/test_builtins_resolution.py +1 -1
- warp/tests/test_bvh.py +6 -1
- warp/tests/test_closest_point_edge_edge.py +1 -1
- warp/tests/test_codegen.py +66 -1
- warp/tests/test_compile_consts.py +1 -1
- warp/tests/test_conditional.py +1 -1
- warp/tests/test_copy.py +1 -1
- warp/tests/test_ctypes.py +1 -1
- warp/tests/test_dense.py +1 -1
- warp/tests/test_devices.py +1 -1
- warp/tests/test_dlpack.py +1 -1
- warp/tests/test_examples.py +33 -4
- warp/tests/test_fabricarray.py +5 -2
- warp/tests/test_fast_math.py +1 -1
- warp/tests/test_fem.py +213 -6
- warp/tests/test_fp16.py +1 -1
- warp/tests/test_func.py +1 -1
- warp/tests/test_future_annotations.py +90 -0
- warp/tests/test_generics.py +1 -1
- warp/tests/test_grad.py +1 -1
- warp/tests/test_grad_customs.py +1 -1
- warp/tests/test_grad_debug.py +247 -0
- warp/tests/test_hash_grid.py +6 -1
- warp/tests/test_implicit_init.py +354 -0
- warp/tests/test_import.py +1 -1
- warp/tests/test_indexedarray.py +1 -1
- warp/tests/test_intersect.py +1 -1
- warp/tests/test_jax.py +1 -1
- warp/tests/test_large.py +1 -1
- warp/tests/test_launch.py +1 -1
- warp/tests/test_lerp.py +1 -1
- warp/tests/test_linear_solvers.py +1 -1
- warp/tests/test_lvalue.py +1 -1
- warp/tests/test_marching_cubes.py +5 -2
- warp/tests/test_mat.py +34 -35
- warp/tests/test_mat_lite.py +2 -1
- warp/tests/test_mat_scalar_ops.py +1 -1
- warp/tests/test_math.py +1 -1
- warp/tests/test_matmul.py +20 -16
- warp/tests/test_matmul_lite.py +1 -1
- warp/tests/test_mempool.py +1 -1
- warp/tests/test_mesh.py +5 -2
- warp/tests/test_mesh_query_aabb.py +1 -1
- warp/tests/test_mesh_query_point.py +1 -1
- warp/tests/test_mesh_query_ray.py +1 -1
- warp/tests/test_mlp.py +1 -1
- warp/tests/test_model.py +1 -1
- warp/tests/test_module_hashing.py +77 -1
- warp/tests/test_modules_lite.py +1 -1
- warp/tests/test_multigpu.py +1 -1
- warp/tests/test_noise.py +1 -1
- warp/tests/test_operators.py +1 -1
- warp/tests/test_options.py +1 -1
- warp/tests/test_overwrite.py +542 -0
- warp/tests/test_peer.py +1 -1
- warp/tests/test_pinned.py +1 -1
- warp/tests/test_print.py +1 -1
- warp/tests/test_quat.py +15 -1
- warp/tests/test_rand.py +1 -1
- warp/tests/test_reload.py +1 -1
- warp/tests/test_rounding.py +1 -1
- warp/tests/test_runlength_encode.py +1 -1
- warp/tests/test_scalar_ops.py +95 -0
- warp/tests/test_sim_grad.py +1 -1
- warp/tests/test_sim_kinematics.py +1 -1
- warp/tests/test_smoothstep.py +1 -1
- warp/tests/test_sparse.py +82 -15
- warp/tests/test_spatial.py +1 -1
- warp/tests/test_special_values.py +2 -11
- warp/tests/test_streams.py +11 -1
- warp/tests/test_struct.py +1 -1
- warp/tests/test_tape.py +1 -1
- warp/tests/test_torch.py +194 -1
- warp/tests/test_transient_module.py +1 -1
- warp/tests/test_types.py +1 -1
- warp/tests/test_utils.py +1 -1
- warp/tests/test_vec.py +15 -63
- warp/tests/test_vec_lite.py +2 -1
- warp/tests/test_vec_scalar_ops.py +122 -39
- warp/tests/test_verify_fp.py +1 -1
- warp/tests/test_volume.py +28 -2
- warp/tests/test_volume_write.py +1 -1
- warp/tests/unittest_serial.py +1 -1
- warp/tests/unittest_suites.py +9 -1
- warp/tests/walkthrough_debug.py +1 -1
- warp/thirdparty/unittest_parallel.py +2 -5
- warp/torch.py +103 -41
- warp/types.py +344 -227
- warp/utils.py +11 -2
- {warp_lang-1.2.1.dist-info → warp_lang-1.3.0.dist-info}/METADATA +99 -46
- warp_lang-1.3.0.dist-info/RECORD +368 -0
- warp/examples/fem/bsr_utils.py +0 -378
- warp/examples/fem/mesh_utils.py +0 -133
- warp/examples/fem/plot_utils.py +0 -292
- warp_lang-1.2.1.dist-info/RECORD +0 -359
- {warp_lang-1.2.1.dist-info → warp_lang-1.3.0.dist-info}/LICENSE.md +0 -0
- {warp_lang-1.2.1.dist-info → warp_lang-1.3.0.dist-info}/WHEEL +0 -0
- {warp_lang-1.2.1.dist-info → warp_lang-1.3.0.dist-info}/top_level.txt +0 -0
|
@@ -10,18 +10,32 @@ _mat32 = wp.mat(shape=(3, 2), dtype=float)
|
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class DeformedGeometry(Geometry):
|
|
13
|
-
def __init__(self, field):
|
|
14
|
-
"""Constructs a Deformed Geometry from a displacement field defined over a base geometry
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
def __init__(self, field: "wp.fem.field.GeometryField", relative: bool = True):
|
|
14
|
+
"""Constructs a Deformed Geometry from a displacement or absolute position field defined over a base geometry.
|
|
15
|
+
The deformation field does not need to be isoparameteric.
|
|
16
|
+
|
|
17
|
+
See also: :meth:`warp.fem.DiscreteField.make_deformed_geometry`
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from warp.fem.field import DiscreteField, GeometryField
|
|
21
|
+
|
|
22
|
+
if isinstance(field, DiscreteField):
|
|
23
|
+
if (
|
|
24
|
+
not wp.types.type_is_vector(field.dtype)
|
|
25
|
+
or wp.types.type_length(field.dtype) != field.geometry.dimension
|
|
26
|
+
):
|
|
27
|
+
raise ValueError(
|
|
28
|
+
"Invalid value type for position field, must be vector-valued with same dimension as underlying geometry"
|
|
29
|
+
)
|
|
30
|
+
if field.eval_grad_inner is None:
|
|
31
|
+
raise ValueError("Gradient evaluation is not supported on the passed field")
|
|
32
|
+
|
|
33
|
+
self._relative = relative
|
|
34
|
+
|
|
35
|
+
self.field: GeometryField = field
|
|
36
|
+
self.base = self.field.geometry
|
|
20
37
|
self.dimension = self.base.dimension
|
|
21
38
|
|
|
22
|
-
if not wp.types.type_is_vector(field.dtype) or wp.types.type_length(field.dtype) != self.dimension:
|
|
23
|
-
raise ValueError("Invalid value type for position field")
|
|
24
|
-
|
|
25
39
|
self.CellArg = self.field.ElementEvalArg
|
|
26
40
|
|
|
27
41
|
self.field_trace = field.trace()
|
|
@@ -60,7 +74,7 @@ class DeformedGeometry(Geometry):
|
|
|
60
74
|
|
|
61
75
|
@property
|
|
62
76
|
def name(self):
|
|
63
|
-
return f"DefGeo_{self.field.name}"
|
|
77
|
+
return f"DefGeo_{self.field.name}_{'rel' if self._relative else 'abs'}"
|
|
64
78
|
|
|
65
79
|
# Geometry device interface
|
|
66
80
|
|
|
@@ -74,20 +88,28 @@ class DeformedGeometry(Geometry):
|
|
|
74
88
|
return args
|
|
75
89
|
|
|
76
90
|
def _make_cell_position(self):
|
|
91
|
+
@cache.dynamic_func(suffix=self.name)
|
|
92
|
+
def cell_position_absolute(cell_arg: self.CellArg, s: Sample):
|
|
93
|
+
return self.field.eval_inner(cell_arg, s)
|
|
94
|
+
|
|
77
95
|
@cache.dynamic_func(suffix=self.name)
|
|
78
96
|
def cell_position(cell_arg: self.CellArg, s: Sample):
|
|
79
97
|
return self.field.eval_inner(cell_arg, s) + self.base.cell_position(cell_arg.elt_arg, s)
|
|
80
98
|
|
|
81
|
-
return cell_position
|
|
99
|
+
return cell_position if self._relative else cell_position_absolute
|
|
82
100
|
|
|
83
101
|
def _make_cell_deformation_gradient(self):
|
|
102
|
+
@cache.dynamic_func(suffix=self.name)
|
|
103
|
+
def cell_deformation_gradient_absolute(cell_arg: self.CellArg, s: Sample):
|
|
104
|
+
return self.field.eval_reference_grad_inner(cell_arg, s)
|
|
105
|
+
|
|
84
106
|
@cache.dynamic_func(suffix=self.name)
|
|
85
107
|
def cell_deformation_gradient(cell_arg: self.CellArg, s: Sample):
|
|
86
108
|
return self.field.eval_reference_grad_inner(cell_arg, s) + self.base.cell_deformation_gradient(
|
|
87
109
|
cell_arg.elt_arg, s
|
|
88
110
|
)
|
|
89
111
|
|
|
90
|
-
return cell_deformation_gradient
|
|
112
|
+
return cell_deformation_gradient if self._relative else cell_deformation_gradient_absolute
|
|
91
113
|
|
|
92
114
|
def _make_cell_inverse_deformation_gradient(self):
|
|
93
115
|
@cache.dynamic_func(suffix=self.name)
|
|
@@ -129,14 +151,27 @@ class DeformedGeometry(Geometry):
|
|
|
129
151
|
return args
|
|
130
152
|
|
|
131
153
|
def _make_side_position(self):
|
|
154
|
+
@cache.dynamic_func(suffix=self.name)
|
|
155
|
+
def side_position_absolute(args: self.SideArg, s: Sample):
|
|
156
|
+
trace_arg = self.field_trace.ElementEvalArg(args.base_arg, args.trace_arg)
|
|
157
|
+
return self.field_trace.eval_inner(trace_arg, s)
|
|
158
|
+
|
|
132
159
|
@cache.dynamic_func(suffix=self.name)
|
|
133
160
|
def side_position(args: self.SideArg, s: Sample):
|
|
134
161
|
trace_arg = self.field_trace.ElementEvalArg(args.base_arg, args.trace_arg)
|
|
135
162
|
return self.field_trace.eval_inner(trace_arg, s) + self.base.side_position(args.base_arg, s)
|
|
136
163
|
|
|
137
|
-
return side_position
|
|
164
|
+
return side_position if self._relative else side_position_absolute
|
|
138
165
|
|
|
139
166
|
def _make_side_deformation_gradient(self):
|
|
167
|
+
@cache.dynamic_func(suffix=self.name)
|
|
168
|
+
def side_deformation_gradient_absolute(args: self.SideArg, s: Sample):
|
|
169
|
+
base_def_grad = self.base.side_deformation_gradient(args.base_arg, s)
|
|
170
|
+
trace_arg = self.field_trace.ElementEvalArg(args.base_arg, args.trace_arg)
|
|
171
|
+
|
|
172
|
+
Du = self.field_trace.eval_grad_inner(trace_arg, s)
|
|
173
|
+
return Du * base_def_grad
|
|
174
|
+
|
|
140
175
|
@cache.dynamic_func(suffix=self.name)
|
|
141
176
|
def side_deformation_gradient(args: self.SideArg, s: Sample):
|
|
142
177
|
base_def_grad = self.base.side_deformation_gradient(args.base_arg, s)
|
|
@@ -145,7 +180,7 @@ class DeformedGeometry(Geometry):
|
|
|
145
180
|
Du = self.field_trace.eval_grad_inner(trace_arg, s)
|
|
146
181
|
return base_def_grad + Du * base_def_grad
|
|
147
182
|
|
|
148
|
-
return side_deformation_gradient
|
|
183
|
+
return side_deformation_gradient if self._relative else side_deformation_gradient_absolute
|
|
149
184
|
|
|
150
185
|
def _make_side_inner_inverse_deformation_gradient(self):
|
|
151
186
|
@cache.dynamic_func(suffix=self.name)
|
warp/fem/geometry/hexmesh.py
CHANGED
|
@@ -65,7 +65,7 @@ EDGE_VERTEX_INDICES = wp.constant(
|
|
|
65
65
|
)
|
|
66
66
|
)
|
|
67
67
|
|
|
68
|
-
#
|
|
68
|
+
# orthogonal transform for face coordinates given first vertex + winding
|
|
69
69
|
# (two rows per entry)
|
|
70
70
|
|
|
71
71
|
FACE_ORIENTATION = [
|
|
@@ -439,12 +439,12 @@ class Hexmesh(Geometry):
|
|
|
439
439
|
return side_arg.cell_arg
|
|
440
440
|
|
|
441
441
|
def _build_topology(self, temporary_store: TemporaryStore):
|
|
442
|
-
from warp.fem.utils import compress_node_indices, masked_indices
|
|
442
|
+
from warp.fem.utils import compress_node_indices, host_read_at_index, masked_indices
|
|
443
443
|
from warp.utils import array_scan
|
|
444
444
|
|
|
445
445
|
device = self.hex_vertex_indices.device
|
|
446
446
|
|
|
447
|
-
vertex_hex_offsets, vertex_hex_indices
|
|
447
|
+
vertex_hex_offsets, vertex_hex_indices = compress_node_indices(
|
|
448
448
|
self.vertex_count(), self.hex_vertex_indices, temporary_store=temporary_store
|
|
449
449
|
)
|
|
450
450
|
self._vertex_hex_offsets = vertex_hex_offsets.detach()
|
|
@@ -492,16 +492,11 @@ class Hexmesh(Geometry):
|
|
|
492
492
|
array_scan(in_array=vertex_start_face_count.array, out_array=vertex_unique_face_offsets.array, inclusive=False)
|
|
493
493
|
|
|
494
494
|
# Get back edge count to host
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
wp.copy(
|
|
499
|
-
dest=face_count.array, src=vertex_unique_face_offsets.array, src_offset=self.vertex_count() - 1, count=1
|
|
495
|
+
face_count = int(
|
|
496
|
+
host_read_at_index(
|
|
497
|
+
vertex_unique_face_offsets.array, self.vertex_count() - 1, temporary_store=temporary_store
|
|
500
498
|
)
|
|
501
|
-
|
|
502
|
-
face_count = int(face_count.array.numpy()[0])
|
|
503
|
-
else:
|
|
504
|
-
face_count = int(vertex_unique_face_offsets.array.numpy()[self.vertex_count() - 1])
|
|
499
|
+
)
|
|
505
500
|
|
|
506
501
|
self._face_vertex_indices = wp.empty(shape=(face_count,), dtype=wp.vec4i, device=device)
|
|
507
502
|
self._face_hex_indices = wp.empty(shape=(face_count,), dtype=wp.vec2i, device=device)
|
|
@@ -557,6 +552,7 @@ class Hexmesh(Geometry):
|
|
|
557
552
|
self._boundary_face_indices = boundary_face_indices.detach()
|
|
558
553
|
|
|
559
554
|
def _compute_hex_edges(self, temporary_store: Optional[TemporaryStore] = None):
|
|
555
|
+
from warp.fem.utils import host_read_at_index
|
|
560
556
|
from warp.utils import array_scan
|
|
561
557
|
|
|
562
558
|
device = self.hex_vertex_indices.device
|
|
@@ -599,19 +595,11 @@ class Hexmesh(Geometry):
|
|
|
599
595
|
array_scan(in_array=vertex_start_edge_count.array, out_array=vertex_unique_edge_offsets.array, inclusive=False)
|
|
600
596
|
|
|
601
597
|
# Get back edge count to host
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
wp.copy(
|
|
606
|
-
dest=edge_count.array,
|
|
607
|
-
src=vertex_unique_edge_offsets.array,
|
|
608
|
-
src_offset=self.vertex_count() - 1,
|
|
609
|
-
count=1,
|
|
598
|
+
self._edge_count = int(
|
|
599
|
+
host_read_at_index(
|
|
600
|
+
vertex_unique_edge_offsets.array, self.vertex_count() - 1, temporary_store=temporary_store
|
|
610
601
|
)
|
|
611
|
-
|
|
612
|
-
self._edge_count = int(edge_count.array.numpy()[0])
|
|
613
|
-
else:
|
|
614
|
-
self._edge_count = int(vertex_unique_edge_offsets.array.numpy()[self.vertex_count() - 1])
|
|
602
|
+
)
|
|
615
603
|
|
|
616
604
|
self._hex_edge_indices = wp.empty(
|
|
617
605
|
dtype=int, device=self.hex_vertex_indices.device, shape=(self.cell_count(), 12)
|
warp/fem/geometry/nanogrid.py
CHANGED
|
@@ -60,9 +60,21 @@ class NanogridSideArg:
|
|
|
60
60
|
|
|
61
61
|
|
|
62
62
|
class Nanogrid(Geometry):
|
|
63
|
+
"""Sparse grid geometry"""
|
|
64
|
+
|
|
63
65
|
dimension = 3
|
|
64
66
|
|
|
65
67
|
def __init__(self, grid: wp.Volume, temporary_store: Optional[cache.TemporaryStore] = None):
|
|
68
|
+
"""
|
|
69
|
+
Constructs a sparse grid geometry from an in-memory NanoVDB volume.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
grid: The NanoVDB volume. Any type is accepted, but for indexing efficiency an index grid is recommended.
|
|
73
|
+
If `grid` is an 'on' index grid, cells will be created for active voxels only, otherwise cells will
|
|
74
|
+
be created for all leaf voxels.
|
|
75
|
+
temporary_store: shared pool from which to allocate temporary arrays
|
|
76
|
+
"""
|
|
77
|
+
|
|
66
78
|
self._cell_grid = grid
|
|
67
79
|
self._cell_grid_info = grid.get_grid_info()
|
|
68
80
|
|
|
@@ -77,31 +89,29 @@ class Nanogrid(Geometry):
|
|
|
77
89
|
self._node_ijk = wp.array(shape=(node_count,), dtype=wp.vec3i, device=device)
|
|
78
90
|
self._node_grid.get_voxels(out=self._node_ijk)
|
|
79
91
|
|
|
80
|
-
self._face_grid =
|
|
81
|
-
|
|
82
|
-
self._face_ijk = wp.array(shape=(face_count,), dtype=wp.vec3i, device=device)
|
|
83
|
-
self._face_grid.get_voxels(out=self._face_ijk)
|
|
84
|
-
|
|
85
|
-
self._face_flags = wp.array(shape=(face_count,), dtype=wp.uint8, device=device)
|
|
86
|
-
boundary_face_mask = cache.borrow_temporary(temporary_store, shape=(face_count,), dtype=wp.int32, device=device)
|
|
87
|
-
|
|
88
|
-
wp.launch(
|
|
89
|
-
_build_face_flags,
|
|
90
|
-
dim=face_count,
|
|
91
|
-
device=device,
|
|
92
|
-
inputs=[grid.id, self._face_ijk, self._face_flags, boundary_face_mask.array],
|
|
93
|
-
)
|
|
94
|
-
boundary_face_indices, _ = utils.masked_indices(boundary_face_mask.array)
|
|
95
|
-
self._boundary_face_indices = boundary_face_indices.detach()
|
|
92
|
+
self._face_grid = None
|
|
93
|
+
self._face_ijk = None
|
|
96
94
|
|
|
97
95
|
self._edge_grid = None
|
|
98
96
|
self._edge_ijk = None
|
|
99
97
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
98
|
+
@property
|
|
99
|
+
def cell_grid(self) -> wp.Volume:
|
|
100
|
+
return self._cell_grid
|
|
101
|
+
|
|
102
|
+
@property
|
|
103
|
+
def vertex_grid(self) -> wp.Volume:
|
|
104
|
+
return self._node_grid
|
|
105
|
+
|
|
106
|
+
@property
|
|
107
|
+
def face_grid(self) -> wp.Volume:
|
|
108
|
+
self._ensure_face_grid()
|
|
109
|
+
return self._face_grid
|
|
110
|
+
|
|
111
|
+
@property
|
|
112
|
+
def edge_grid(self) -> wp.Volume:
|
|
113
|
+
self._ensure_edge_grid()
|
|
114
|
+
return self._edge_grid
|
|
105
115
|
|
|
106
116
|
def cell_count(self):
|
|
107
117
|
return self._cell_ijk.shape[0]
|
|
@@ -110,17 +120,17 @@ class Nanogrid(Geometry):
|
|
|
110
120
|
return self._node_ijk.shape[0]
|
|
111
121
|
|
|
112
122
|
def side_count(self):
|
|
123
|
+
self._ensure_face_grid()
|
|
113
124
|
return self._face_ijk.shape[0]
|
|
114
125
|
|
|
115
|
-
def edge_count(self):
|
|
116
|
-
if self._edge_ijk is None:
|
|
117
|
-
self._build_edge_grid()
|
|
118
|
-
|
|
119
|
-
return self._edge_ijk.shape[0]
|
|
120
|
-
|
|
121
126
|
def boundary_side_count(self):
|
|
127
|
+
self._ensure_face_grid()
|
|
122
128
|
return self._boundary_face_indices.shape[0]
|
|
123
129
|
|
|
130
|
+
def edge_count(self):
|
|
131
|
+
self._ensure_edge_grid()
|
|
132
|
+
return self._edge_ijk.shape[0]
|
|
133
|
+
|
|
124
134
|
def reference_cell(self) -> Cube:
|
|
125
135
|
return Cube()
|
|
126
136
|
|
|
@@ -144,7 +154,7 @@ class Nanogrid(Geometry):
|
|
|
144
154
|
@wp.func
|
|
145
155
|
def cell_position(args: CellArg, s: Sample):
|
|
146
156
|
uvw = wp.vec3(args.cell_ijk[s.element_index]) + s.element_coords
|
|
147
|
-
return wp.volume_index_to_world(args.cell_grid, uvw)
|
|
157
|
+
return wp.volume_index_to_world(args.cell_grid, uvw - wp.vec3(0.5))
|
|
148
158
|
|
|
149
159
|
@wp.func
|
|
150
160
|
def cell_deformation_gradient(args: CellArg, s: Sample):
|
|
@@ -156,7 +166,7 @@ class Nanogrid(Geometry):
|
|
|
156
166
|
|
|
157
167
|
@wp.func
|
|
158
168
|
def cell_lookup(args: CellArg, pos: wp.vec3):
|
|
159
|
-
uvw = wp.volume_world_to_index(args.cell_grid, pos)
|
|
169
|
+
uvw = wp.volume_world_to_index(args.cell_grid, pos) + wp.vec3(0.5)
|
|
160
170
|
ijk = wp.vec3i(int(wp.floor(uvw[0])), int(wp.floor(uvw[1])), int(wp.floor(uvw[2])))
|
|
161
171
|
element_index = wp.volume_lookup_index(args.cell_grid, ijk[0], ijk[1], ijk[2])
|
|
162
172
|
|
|
@@ -166,9 +176,37 @@ class Nanogrid(Geometry):
|
|
|
166
176
|
make_free_sample(NULL_ELEMENT_INDEX, Coords(OUTSIDE)),
|
|
167
177
|
)
|
|
168
178
|
|
|
179
|
+
@wp.func
|
|
180
|
+
def _project_on_voxel_at_origin(coords: wp.vec3):
|
|
181
|
+
proj_coords = wp.min(wp.max(coords, wp.vec3(0.0)), wp.vec3(1.0))
|
|
182
|
+
return wp.length_sq(coords - proj_coords), proj_coords
|
|
183
|
+
|
|
169
184
|
@wp.func
|
|
170
185
|
def cell_lookup(args: CellArg, pos: wp.vec3, guess: Sample):
|
|
171
|
-
|
|
186
|
+
s_global = Nanogrid.cell_lookup(args, pos)
|
|
187
|
+
|
|
188
|
+
if s_global.element_index != NULL_ELEMENT_INDEX:
|
|
189
|
+
return s_global
|
|
190
|
+
|
|
191
|
+
closest_voxel = int(NULL_ELEMENT_INDEX)
|
|
192
|
+
closest_coords = Coords(OUTSIDE)
|
|
193
|
+
closest_dist = float(1.0e8)
|
|
194
|
+
|
|
195
|
+
# project to closest in stencil
|
|
196
|
+
uvw = wp.volume_world_to_index(args.cell_grid, pos) + wp.vec3(0.5)
|
|
197
|
+
cell_ijk = args.cell_ijk[guess.element_index]
|
|
198
|
+
for ni in range(-1, 2):
|
|
199
|
+
for nj in range(-1, 2):
|
|
200
|
+
for nk in range(-1, 2):
|
|
201
|
+
nijk = cell_ijk + wp.vec3i(ni, nj, nk)
|
|
202
|
+
cell_idx = wp.volume_lookup_index(args.cell_grid, nijk[0], nijk[1], nijk[2])
|
|
203
|
+
dist, coords = Nanogrid._project_on_voxel_at_origin(uvw - wp.vec3(nijk))
|
|
204
|
+
if cell_idx != -1 and dist <= closest_dist:
|
|
205
|
+
closest_dist = dist
|
|
206
|
+
closest_voxel = cell_idx
|
|
207
|
+
closest_coords = coords
|
|
208
|
+
|
|
209
|
+
return make_free_sample(closest_voxel, closest_coords)
|
|
172
210
|
|
|
173
211
|
@wp.func
|
|
174
212
|
def cell_measure(args: CellArg, s: Sample):
|
|
@@ -182,6 +220,8 @@ class Nanogrid(Geometry):
|
|
|
182
220
|
|
|
183
221
|
@cache.cached_arg_value
|
|
184
222
|
def side_arg_value(self, device) -> SideArg:
|
|
223
|
+
self._ensure_face_grid()
|
|
224
|
+
|
|
185
225
|
args = self.SideArg()
|
|
186
226
|
args.cell_arg = self.cell_arg_value(device)
|
|
187
227
|
args.face_ijk = self._face_ijk.to(device)
|
|
@@ -199,6 +239,8 @@ class Nanogrid(Geometry):
|
|
|
199
239
|
|
|
200
240
|
@cache.cached_arg_value
|
|
201
241
|
def side_index_arg_value(self, device) -> SideIndexArg:
|
|
242
|
+
self._ensure_face_grid()
|
|
243
|
+
|
|
202
244
|
args = self.SideIndexArg()
|
|
203
245
|
args.boundary_face_indices = self._boundary_face_indices.to(device)
|
|
204
246
|
return args
|
|
@@ -235,7 +277,7 @@ class Nanogrid(Geometry):
|
|
|
235
277
|
uvw = wp.vec3(ijk) + Nanogrid._side_to_cell_coords(axis, 0.0, s.element_coords)
|
|
236
278
|
|
|
237
279
|
cell_grid = args.cell_arg.cell_grid
|
|
238
|
-
return wp.volume_index_to_world(cell_grid, uvw)
|
|
280
|
+
return wp.volume_index_to_world(cell_grid, uvw - wp.vec3(0.5))
|
|
239
281
|
|
|
240
282
|
@wp.func
|
|
241
283
|
def _face_tangent_vecs(args: SideArg, axis: int, flip: int):
|
|
@@ -342,6 +384,39 @@ class Nanogrid(Geometry):
|
|
|
342
384
|
def side_to_cell_arg(side_arg: SideArg):
|
|
343
385
|
return side_arg.cell_arg
|
|
344
386
|
|
|
387
|
+
def _build_face_grid(self, temporary_store: Optional[cache.TemporaryStore] = None):
|
|
388
|
+
device = self._cell_grid.device
|
|
389
|
+
self._face_grid = _build_face_grid(self._cell_ijk, self._cell_grid, temporary_store)
|
|
390
|
+
face_count = self._face_grid.get_voxel_count()
|
|
391
|
+
self._face_ijk = wp.array(shape=(face_count,), dtype=wp.vec3i, device=device)
|
|
392
|
+
self._face_grid.get_voxels(out=self._face_ijk)
|
|
393
|
+
|
|
394
|
+
self._face_flags = wp.array(shape=(face_count,), dtype=wp.uint8, device=device)
|
|
395
|
+
boundary_face_mask = cache.borrow_temporary(temporary_store, shape=(face_count,), dtype=wp.int32, device=device)
|
|
396
|
+
|
|
397
|
+
wp.launch(
|
|
398
|
+
_build_face_flags,
|
|
399
|
+
dim=face_count,
|
|
400
|
+
device=device,
|
|
401
|
+
inputs=[self._cell_grid.id, self._face_ijk, self._face_flags, boundary_face_mask.array],
|
|
402
|
+
)
|
|
403
|
+
boundary_face_indices, _ = utils.masked_indices(boundary_face_mask.array)
|
|
404
|
+
self._boundary_face_indices = boundary_face_indices.detach()
|
|
405
|
+
|
|
406
|
+
def _build_edge_grid(self, temporary_store: Optional[cache.TemporaryStore] = None):
|
|
407
|
+
self._edge_grid = _build_edge_grid(self._cell_ijk, self._cell_grid, temporary_store)
|
|
408
|
+
edge_count = self._edge_grid.get_voxel_count()
|
|
409
|
+
self._edge_ijk = wp.array(shape=(edge_count,), dtype=wp.vec3i, device=self._edge_grid.device)
|
|
410
|
+
self._edge_grid.get_voxels(out=self._edge_ijk)
|
|
411
|
+
|
|
412
|
+
def _ensure_face_grid(self):
|
|
413
|
+
if self._face_ijk is None:
|
|
414
|
+
self._build_face_grid()
|
|
415
|
+
|
|
416
|
+
def _ensure_edge_grid(self):
|
|
417
|
+
if self._edge_ijk is None:
|
|
418
|
+
self._build_edge_grid()
|
|
419
|
+
|
|
345
420
|
|
|
346
421
|
@wp.kernel
|
|
347
422
|
def _cell_node_indices(
|
warp/fem/geometry/quadmesh_2d.py
CHANGED
|
@@ -299,12 +299,12 @@ class Quadmesh2D(Geometry):
|
|
|
299
299
|
return side_arg.cell_arg
|
|
300
300
|
|
|
301
301
|
def _build_topology(self, temporary_store: TemporaryStore):
|
|
302
|
-
from warp.fem.utils import compress_node_indices, masked_indices
|
|
302
|
+
from warp.fem.utils import compress_node_indices, host_read_at_index, masked_indices
|
|
303
303
|
from warp.utils import array_scan
|
|
304
304
|
|
|
305
305
|
device = self.quad_vertex_indices.device
|
|
306
306
|
|
|
307
|
-
vertex_quad_offsets, vertex_quad_indices
|
|
307
|
+
vertex_quad_offsets, vertex_quad_indices = compress_node_indices(
|
|
308
308
|
self.vertex_count(), self.quad_vertex_indices, temporary_store=temporary_store
|
|
309
309
|
)
|
|
310
310
|
self._vertex_quad_offsets = vertex_quad_offsets.detach()
|
|
@@ -350,16 +350,11 @@ class Quadmesh2D(Geometry):
|
|
|
350
350
|
array_scan(in_array=vertex_start_edge_count.array, out_array=vertex_unique_edge_offsets.array, inclusive=False)
|
|
351
351
|
|
|
352
352
|
# Get back edge count to host
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
wp.copy(
|
|
357
|
-
dest=edge_count.array, src=vertex_unique_edge_offsets.array, src_offset=self.vertex_count() - 1, count=1
|
|
353
|
+
edge_count = int(
|
|
354
|
+
host_read_at_index(
|
|
355
|
+
vertex_unique_edge_offsets.array, self.vertex_count() - 1, temporary_store=temporary_store
|
|
358
356
|
)
|
|
359
|
-
|
|
360
|
-
edge_count = int(edge_count.array.numpy()[0])
|
|
361
|
-
else:
|
|
362
|
-
edge_count = int(vertex_unique_edge_offsets.array.numpy()[self.vertex_count() - 1])
|
|
357
|
+
)
|
|
363
358
|
|
|
364
359
|
self._edge_vertex_indices = wp.empty(shape=(edge_count,), dtype=wp.vec2i, device=device)
|
|
365
360
|
self._edge_quad_indices = wp.empty(shape=(edge_count,), dtype=wp.vec2i, device=device)
|