warp-lang 1.7.2rc1__py3-none-win_amd64.whl → 1.8.1__py3-none-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of warp-lang might be problematic. Click here for more details.
- warp/__init__.py +3 -1
- warp/__init__.pyi +3489 -1
- warp/autograd.py +45 -122
- warp/bin/warp-clang.dll +0 -0
- warp/bin/warp.dll +0 -0
- warp/build.py +241 -252
- warp/build_dll.py +130 -26
- warp/builtins.py +1907 -384
- warp/codegen.py +272 -104
- warp/config.py +12 -1
- warp/constants.py +1 -1
- warp/context.py +770 -238
- 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_callable.py +34 -4
- warp/examples/interop/example_jax_ffi_callback.py +2 -2
- warp/examples/interop/example_jax_kernel.py +27 -1
- 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 +99 -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 +181 -95
- 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 +210 -67
- warp/jax_experimental/xla_ffi.py +37 -24
- warp/math.py +171 -1
- warp/native/array.h +103 -4
- warp/native/builtin.h +182 -35
- warp/native/coloring.cpp +6 -2
- warp/native/cuda_util.cpp +1 -1
- warp/native/exports.h +118 -63
- warp/native/intersect.h +5 -5
- warp/native/mat.h +8 -13
- warp/native/mathdx.cpp +11 -5
- warp/native/matnn.h +1 -123
- warp/native/mesh.h +1 -1
- warp/native/quat.h +34 -6
- warp/native/rand.h +7 -7
- warp/native/sparse.cpp +121 -258
- warp/native/sparse.cu +181 -274
- warp/native/spatial.h +305 -17
- warp/native/svd.h +23 -8
- warp/native/tile.h +603 -73
- warp/native/tile_radix_sort.h +1112 -0
- warp/native/tile_reduce.h +239 -13
- warp/native/tile_scan.h +240 -0
- warp/native/tuple.h +189 -0
- warp/native/vec.h +10 -20
- warp/native/warp.cpp +36 -4
- warp/native/warp.cu +588 -52
- 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 +110 -80
- warp/render/render_usd.py +124 -62
- warp/sim/__init__.py +9 -0
- warp/sim/collide.py +253 -80
- 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 +761 -322
- 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 +54 -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} +378 -112
- warp/tests/sim/test_collision.py +159 -51
- warp/tests/sim/test_coloring.py +91 -2
- warp/tests/test_array.py +254 -2
- warp/tests/test_array_reduce.py +2 -2
- warp/tests/test_assert.py +53 -0
- warp/tests/test_atomic_cas.py +312 -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 +23 -24
- warp/tests/test_quat.py +28 -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 +83 -2
- warp/tests/test_spatial.py +507 -1
- warp/tests/test_static.py +48 -0
- warp/tests/test_struct.py +2 -2
- warp/tests/test_tape.py +38 -0
- warp/tests/test_tuple.py +265 -0
- warp/tests/test_types.py +2 -2
- warp/tests/test_utils.py +24 -18
- warp/tests/test_vec.py +38 -408
- warp/tests/test_vec_constructors.py +325 -0
- warp/tests/tile/test_tile.py +438 -131
- warp/tests/tile/test_tile_mathdx.py +518 -14
- warp/tests/tile/test_tile_matmul.py +179 -0
- warp/tests/tile/test_tile_reduce.py +307 -5
- warp/tests/tile/test_tile_shared_memory.py +136 -7
- warp/tests/tile/test_tile_sort.py +121 -0
- warp/tests/unittest_suites.py +14 -6
- warp/types.py +462 -308
- warp/utils.py +647 -86
- {warp_lang-1.7.2rc1.dist-info → warp_lang-1.8.1.dist-info}/METADATA +20 -6
- {warp_lang-1.7.2rc1.dist-info → warp_lang-1.8.1.dist-info}/RECORD +190 -176
- warp/stubs.py +0 -3381
- warp/tests/sim/test_xpbd.py +0 -399
- warp/tests/test_mlp.py +0 -282
- {warp_lang-1.7.2rc1.dist-info → warp_lang-1.8.1.dist-info}/WHEEL +0 -0
- {warp_lang-1.7.2rc1.dist-info → warp_lang-1.8.1.dist-info}/licenses/LICENSE.md +0 -0
- {warp_lang-1.7.2rc1.dist-info → warp_lang-1.8.1.dist-info}/top_level.txt +0 -0
warp/fem/field/virtual.py
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
# See the License for the specific language governing permissions and
|
|
14
14
|
# limitations under the License.
|
|
15
15
|
|
|
16
|
-
from typing import Any, Set
|
|
16
|
+
from typing import Any, ClassVar, Dict, Set
|
|
17
17
|
|
|
18
18
|
import warp as wp
|
|
19
19
|
import warp.fem.operator as operator
|
|
@@ -23,6 +23,7 @@ from warp.fem.linalg import basis_coefficient, generalized_inner, generalized_ou
|
|
|
23
23
|
from warp.fem.quadrature import Quadrature
|
|
24
24
|
from warp.fem.space import FunctionSpace, SpacePartition, SpaceRestriction
|
|
25
25
|
from warp.fem.types import NULL_NODE_INDEX, DofIndex, Sample, get_node_coord, get_node_index_in_element
|
|
26
|
+
from warp.fem.utils import type_zero_element
|
|
26
27
|
|
|
27
28
|
from .field import SpaceField
|
|
28
29
|
|
|
@@ -30,33 +31,52 @@ from .field import SpaceField
|
|
|
30
31
|
class AdjointField(SpaceField):
|
|
31
32
|
"""Adjoint of a discrete field with respect to its degrees of freedom"""
|
|
32
33
|
|
|
33
|
-
|
|
34
|
+
_dynamic_attribute_constructors: ClassVar = {
|
|
35
|
+
"EvalArg": lambda obj: obj._make_eval_arg(),
|
|
36
|
+
"ElementEvalArg": lambda obj: obj._make_element_eval_arg(),
|
|
37
|
+
"eval_degree": lambda obj: obj._make_eval_degree(),
|
|
38
|
+
"eval_inner": lambda obj: obj._make_eval_inner(),
|
|
39
|
+
"eval_grad_inner": lambda obj: obj._make_eval_grad_inner(),
|
|
40
|
+
"eval_div_inner": lambda obj: obj._make_eval_div_inner(),
|
|
41
|
+
"eval_outer": lambda obj: obj._make_eval_outer(),
|
|
42
|
+
"eval_grad_outer": lambda obj: obj._make_eval_grad_outer(),
|
|
43
|
+
"eval_div_outer": lambda obj: obj._make_eval_div_outer(),
|
|
44
|
+
"node_count": lambda obj: obj._make_node_count(),
|
|
45
|
+
"at_node": lambda obj: obj._make_at_node(),
|
|
46
|
+
"node_index": lambda obj: obj._make_node_index(),
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
def __init__(self, space: FunctionSpace, space_partition: SpacePartition):
|
|
34
50
|
super().__init__(space, space_partition=space_partition)
|
|
35
51
|
|
|
36
52
|
self.node_dof_count = self.space.NODE_DOF_COUNT
|
|
37
53
|
self.value_dof_count = self.space.VALUE_DOF_COUNT
|
|
38
54
|
|
|
39
|
-
|
|
40
|
-
self.ElementEvalArg = self._make_element_eval_arg()
|
|
41
|
-
|
|
42
|
-
self.eval_arg_value = self.space.space_arg_value
|
|
43
|
-
|
|
44
|
-
self.eval_degree = self._make_eval_degree()
|
|
45
|
-
self.eval_inner = self._make_eval_inner()
|
|
46
|
-
self.eval_grad_inner = self._make_eval_grad_inner()
|
|
47
|
-
self.eval_div_inner = self._make_eval_div_inner()
|
|
48
|
-
self.eval_outer = self._make_eval_outer()
|
|
49
|
-
self.eval_grad_outer = self._make_eval_grad_outer()
|
|
50
|
-
self.eval_div_outer = self._make_eval_div_outer()
|
|
51
|
-
self.at_node = self._make_at_node()
|
|
55
|
+
cache.setup_dynamic_attributes(self)
|
|
52
56
|
|
|
53
57
|
@property
|
|
54
58
|
def name(self) -> str:
|
|
55
59
|
return f"{self.__class__.__name__}{self.space.name}{self._space_partition.name}"
|
|
56
60
|
|
|
57
|
-
|
|
58
|
-
|
|
61
|
+
@cache.cached_arg_value
|
|
62
|
+
def eval_arg_value(self, device):
|
|
63
|
+
arg = self.EvalArg()
|
|
64
|
+
self.fill_eval_arg(arg, device)
|
|
65
|
+
return arg
|
|
66
|
+
|
|
67
|
+
def fill_eval_arg(self, arg, device):
|
|
68
|
+
self.space.fill_space_arg(arg.space_arg, device)
|
|
69
|
+
self.space.topology.fill_topo_arg(arg.topo_arg, device)
|
|
59
70
|
|
|
71
|
+
def _make_eval_arg(self):
|
|
72
|
+
@cache.dynamic_struct(suffix=self.name)
|
|
73
|
+
class EvalArg:
|
|
74
|
+
space_arg: self.space.SpaceArg
|
|
75
|
+
topo_arg: self.space.topology.TopologyArg
|
|
76
|
+
|
|
77
|
+
return EvalArg
|
|
78
|
+
|
|
79
|
+
def _make_element_eval_arg(self):
|
|
60
80
|
@cache.dynamic_struct(suffix=self.name)
|
|
61
81
|
class ElementEvalArg:
|
|
62
82
|
elt_arg: self.space.topology.ElementArg
|
|
@@ -70,7 +90,7 @@ class AdjointField(SpaceField):
|
|
|
70
90
|
dof = self._get_dof(s)
|
|
71
91
|
node_weight = self.space.element_inner_weight(
|
|
72
92
|
args.elt_arg,
|
|
73
|
-
args.eval_arg,
|
|
93
|
+
args.eval_arg.space_arg,
|
|
74
94
|
s.element_index,
|
|
75
95
|
s.element_coords,
|
|
76
96
|
get_node_index_in_element(dof),
|
|
@@ -91,7 +111,7 @@ class AdjointField(SpaceField):
|
|
|
91
111
|
dof = self._get_dof(s)
|
|
92
112
|
nabla_weight = self.space.element_inner_weight_gradient(
|
|
93
113
|
args.elt_arg,
|
|
94
|
-
args.eval_arg,
|
|
114
|
+
args.eval_arg.space_arg,
|
|
95
115
|
s.element_index,
|
|
96
116
|
s.element_coords,
|
|
97
117
|
get_node_index_in_element(dof),
|
|
@@ -113,7 +133,7 @@ class AdjointField(SpaceField):
|
|
|
113
133
|
dof = self._get_dof(s)
|
|
114
134
|
nabla_weight = self.space.element_inner_weight_gradient(
|
|
115
135
|
args.elt_arg,
|
|
116
|
-
args.eval_arg,
|
|
136
|
+
args.eval_arg.space_arg,
|
|
117
137
|
s.element_index,
|
|
118
138
|
s.element_coords,
|
|
119
139
|
get_node_index_in_element(dof),
|
|
@@ -132,7 +152,7 @@ class AdjointField(SpaceField):
|
|
|
132
152
|
dof = self._get_dof(s)
|
|
133
153
|
node_weight = self.space.element_outer_weight(
|
|
134
154
|
args.elt_arg,
|
|
135
|
-
args.eval_arg,
|
|
155
|
+
args.eval_arg.space_arg,
|
|
136
156
|
s.element_index,
|
|
137
157
|
s.element_coords,
|
|
138
158
|
get_node_index_in_element(dof),
|
|
@@ -153,7 +173,7 @@ class AdjointField(SpaceField):
|
|
|
153
173
|
dof = self._get_dof(s)
|
|
154
174
|
nabla_weight = self.space.element_outer_weight_gradient(
|
|
155
175
|
args.elt_arg,
|
|
156
|
-
args.eval_arg,
|
|
176
|
+
args.eval_arg.space_arg,
|
|
157
177
|
s.element_index,
|
|
158
178
|
s.element_coords,
|
|
159
179
|
get_node_index_in_element(dof),
|
|
@@ -175,7 +195,7 @@ class AdjointField(SpaceField):
|
|
|
175
195
|
dof = self._get_dof(s)
|
|
176
196
|
nabla_weight = self.space.element_outer_weight_gradient(
|
|
177
197
|
args.elt_arg,
|
|
178
|
-
args.eval_arg,
|
|
198
|
+
args.eval_arg.space_arg,
|
|
179
199
|
s.element_index,
|
|
180
200
|
s.element_coords,
|
|
181
201
|
get_node_index_in_element(dof),
|
|
@@ -193,12 +213,30 @@ class AdjointField(SpaceField):
|
|
|
193
213
|
def at_node(args: self.ElementEvalArg, s: Sample):
|
|
194
214
|
dof = self._get_dof(s)
|
|
195
215
|
node_coords = self.space.node_coords_in_element(
|
|
196
|
-
args.elt_arg, args.eval_arg, s.element_index, get_node_index_in_element(dof)
|
|
216
|
+
args.elt_arg, args.eval_arg.space_arg, s.element_index, get_node_index_in_element(dof)
|
|
197
217
|
)
|
|
198
218
|
return Sample(s.element_index, node_coords, s.qp_index, s.qp_weight, s.test_dof, s.trial_dof)
|
|
199
219
|
|
|
200
220
|
return at_node
|
|
201
221
|
|
|
222
|
+
def _make_node_index(self):
|
|
223
|
+
@cache.dynamic_func(suffix=self.name)
|
|
224
|
+
def node_index(args: self.ElementEvalArg, s: Sample):
|
|
225
|
+
dof = self._get_dof(s)
|
|
226
|
+
node_idx = self.space.topology.element_node_index(
|
|
227
|
+
args.elt_arg, args.eval_arg.topo_arg, s.element_index, get_node_index_in_element(dof)
|
|
228
|
+
)
|
|
229
|
+
return node_idx
|
|
230
|
+
|
|
231
|
+
return node_index
|
|
232
|
+
|
|
233
|
+
def _make_node_count(self):
|
|
234
|
+
@cache.dynamic_func(suffix=self.name)
|
|
235
|
+
def node_count(args: self.ElementEvalArg, s: Sample):
|
|
236
|
+
return self.space.topology.element_node_count(args.elt_arg, args.eval_arg.topo_arg, s.element_index)
|
|
237
|
+
|
|
238
|
+
return node_count
|
|
239
|
+
|
|
202
240
|
|
|
203
241
|
class TestField(AdjointField):
|
|
204
242
|
"""Field defined over a space restriction that can be used as a test function.
|
|
@@ -269,16 +307,16 @@ class LocalAdjointField(SpaceField):
|
|
|
269
307
|
OUTER_GRAD_DOF = wp.constant(3)
|
|
270
308
|
DOF_TYPE_COUNT = wp.constant(4)
|
|
271
309
|
|
|
272
|
-
_OP_DOF_MAP_CONTINUOUS = {
|
|
310
|
+
_OP_DOF_MAP_CONTINUOUS: ClassVar[Dict[operator.Operator, int]] = {
|
|
273
311
|
operator.inner: INNER_DOF,
|
|
274
312
|
operator.outer: INNER_DOF,
|
|
275
313
|
operator.grad: INNER_GRAD_DOF,
|
|
276
|
-
operator.grad_outer:
|
|
314
|
+
operator.grad_outer: OUTER_GRAD_DOF,
|
|
277
315
|
operator.div: INNER_GRAD_DOF,
|
|
278
|
-
operator.div_outer:
|
|
316
|
+
operator.div_outer: OUTER_GRAD_DOF,
|
|
279
317
|
}
|
|
280
318
|
|
|
281
|
-
_OP_DOF_MAP_DISCONTINUOUS = {
|
|
319
|
+
_OP_DOF_MAP_DISCONTINUOUS: ClassVar[Dict[operator.Operator, int]] = {
|
|
282
320
|
operator.inner: INNER_DOF,
|
|
283
321
|
operator.outer: OUTER_DOF,
|
|
284
322
|
operator.grad: INNER_GRAD_DOF,
|
|
@@ -293,6 +331,18 @@ class LocalAdjointField(SpaceField):
|
|
|
293
331
|
class EvalArg:
|
|
294
332
|
pass
|
|
295
333
|
|
|
334
|
+
_dynamic_attribute_constructors: ClassVar = {
|
|
335
|
+
"ElementEvalArg": lambda obj: obj._make_element_eval_arg(),
|
|
336
|
+
"eval_degree": lambda obj: obj._make_eval_degree(),
|
|
337
|
+
"_split_dof": lambda obj: obj._make_split_dof(),
|
|
338
|
+
"eval_inner": lambda obj: obj._make_eval_inner(),
|
|
339
|
+
"eval_grad_inner": lambda obj: obj._make_eval_grad_inner(),
|
|
340
|
+
"eval_div_inner": lambda obj: obj._make_eval_div_inner(),
|
|
341
|
+
"eval_outer": lambda obj: obj._make_eval_outer(),
|
|
342
|
+
"eval_grad_outer": lambda obj: obj._make_eval_grad_outer(),
|
|
343
|
+
"eval_div_outer": lambda obj: obj._make_eval_div_outer(),
|
|
344
|
+
}
|
|
345
|
+
|
|
296
346
|
def __init__(self, field: AdjointField):
|
|
297
347
|
# if not isinstance(field.space, CollocatedFunctionSpace):
|
|
298
348
|
# raise NotImplementedError("Local assembly only implemented for collocated function spaces")
|
|
@@ -305,9 +355,6 @@ class LocalAdjointField(SpaceField):
|
|
|
305
355
|
self.value_dof_count = self.space.VALUE_DOF_COUNT
|
|
306
356
|
|
|
307
357
|
self._dof_suffix = ""
|
|
308
|
-
|
|
309
|
-
self.ElementEvalArg = self._make_element_eval_arg()
|
|
310
|
-
self.eval_degree = self._make_eval_degree()
|
|
311
358
|
self.at_node = None
|
|
312
359
|
|
|
313
360
|
self._is_discontinuous = (self.space.element_inner_weight != self.space.element_outer_weight) or (
|
|
@@ -318,6 +365,8 @@ class LocalAdjointField(SpaceField):
|
|
|
318
365
|
self._TAYLOR_DOF_COUNTS = LocalAdjointField.DofOffsets(0)
|
|
319
366
|
self.TAYLOR_DOF_COUNT = 0
|
|
320
367
|
|
|
368
|
+
cache.setup_dynamic_attributes(self)
|
|
369
|
+
|
|
321
370
|
def notify_operator_usage(self, ops: Set[operator.Operator]):
|
|
322
371
|
# Rebuild degrees-of-freedom offsets based on used operators
|
|
323
372
|
|
|
@@ -346,21 +395,7 @@ class LocalAdjointField(SpaceField):
|
|
|
346
395
|
self._TAYLOR_DOF_COUNTS = dof_counts
|
|
347
396
|
|
|
348
397
|
self._dof_suffix = "".join(str(c) for c in dof_counts)
|
|
349
|
-
|
|
350
|
-
self._split_dof = self._make_split_dof()
|
|
351
|
-
|
|
352
|
-
self.eval_inner = self._make_eval_inner()
|
|
353
|
-
self.eval_grad_inner = self._make_eval_grad_inner()
|
|
354
|
-
self.eval_div_inner = self._make_eval_div_inner()
|
|
355
|
-
|
|
356
|
-
if self._is_discontinuous:
|
|
357
|
-
self.eval_outer = self._make_eval_outer()
|
|
358
|
-
self.eval_grad_outer = self._make_eval_grad_outer()
|
|
359
|
-
self.eval_div_outer = self._make_eval_div_outer()
|
|
360
|
-
else:
|
|
361
|
-
self.eval_outer = self.eval_inner
|
|
362
|
-
self.eval_grad_outer = self.eval_grad_inner
|
|
363
|
-
self.eval_div_outer = self.eval_div_inner
|
|
398
|
+
cache.setup_dynamic_attributes(self)
|
|
364
399
|
|
|
365
400
|
@property
|
|
366
401
|
def name(self) -> str:
|
|
@@ -369,6 +404,9 @@ class LocalAdjointField(SpaceField):
|
|
|
369
404
|
def eval_arg_value(self, device):
|
|
370
405
|
return LocalAdjointField.EvalArg()
|
|
371
406
|
|
|
407
|
+
def fill_eval_arg(self, arg, device):
|
|
408
|
+
pass
|
|
409
|
+
|
|
372
410
|
def _make_element_eval_arg(self):
|
|
373
411
|
from warp.fem import cache
|
|
374
412
|
|
|
@@ -392,6 +430,7 @@ class LocalAdjointField(SpaceField):
|
|
|
392
430
|
|
|
393
431
|
def _make_eval_inner(self):
|
|
394
432
|
DOF_BEGIN = wp.constant(self._TAYLOR_DOF_OFFSETS[LocalAdjointField.INNER_DOF])
|
|
433
|
+
zero_element = type_zero_element(self.dtype)
|
|
395
434
|
|
|
396
435
|
@cache.dynamic_func(suffix=self.name)
|
|
397
436
|
def eval_test_inner(args: self.ElementEvalArg, s: Sample):
|
|
@@ -399,7 +438,7 @@ class LocalAdjointField(SpaceField):
|
|
|
399
438
|
|
|
400
439
|
local_value_map = self.space.local_value_map_inner(args.elt_arg, s.element_index, s.element_coords)
|
|
401
440
|
dof_value = self.space.value_basis_element(value_dof, local_value_map)
|
|
402
|
-
return wp.where(taylor_dof == 0, dof_value,
|
|
441
|
+
return wp.where(taylor_dof == 0, dof_value, zero_element())
|
|
403
442
|
|
|
404
443
|
return eval_test_inner
|
|
405
444
|
|
|
@@ -409,13 +448,14 @@ class LocalAdjointField(SpaceField):
|
|
|
409
448
|
|
|
410
449
|
DOF_BEGIN = wp.constant(self._TAYLOR_DOF_OFFSETS[LocalAdjointField.INNER_GRAD_DOF])
|
|
411
450
|
DOF_COUNT = wp.constant(self._TAYLOR_DOF_COUNTS[LocalAdjointField.INNER_GRAD_DOF])
|
|
451
|
+
zero_element = type_zero_element(self.gradient_dtype)
|
|
412
452
|
|
|
413
453
|
@cache.dynamic_func(suffix=self.name)
|
|
414
454
|
def eval_nabla_test_inner(args: self.ElementEvalArg, s: Sample):
|
|
415
455
|
value_dof, taylor_dof = self._split_dof(self._get_dof(s), DOF_BEGIN)
|
|
416
456
|
|
|
417
457
|
if taylor_dof < 0 or taylor_dof >= DOF_COUNT:
|
|
418
|
-
return
|
|
458
|
+
return zero_element()
|
|
419
459
|
|
|
420
460
|
grad_transform = self.space.element_inner_reference_gradient_transform(args.elt_arg, s)
|
|
421
461
|
local_value_map = self.space.local_value_map_inner(args.elt_arg, s.element_index, s.element_coords)
|
|
@@ -430,13 +470,14 @@ class LocalAdjointField(SpaceField):
|
|
|
430
470
|
|
|
431
471
|
DOF_BEGIN = wp.constant(self._TAYLOR_DOF_OFFSETS[LocalAdjointField.INNER_GRAD_DOF])
|
|
432
472
|
DOF_COUNT = wp.constant(self._TAYLOR_DOF_COUNTS[LocalAdjointField.INNER_GRAD_DOF])
|
|
473
|
+
zero_element = type_zero_element(self.divergence_dtype)
|
|
433
474
|
|
|
434
475
|
@cache.dynamic_func(suffix=self.name)
|
|
435
476
|
def eval_div_test_inner(args: self.ElementEvalArg, s: Sample):
|
|
436
477
|
value_dof, taylor_dof = self._split_dof(self._get_dof(s), DOF_BEGIN)
|
|
437
478
|
|
|
438
479
|
if taylor_dof < 0 or taylor_dof >= DOF_COUNT:
|
|
439
|
-
return
|
|
480
|
+
return zero_element()
|
|
440
481
|
|
|
441
482
|
grad_transform = self.space.element_inner_reference_gradient_transform(args.elt_arg, s)
|
|
442
483
|
local_value_map = self.space.local_value_map_inner(args.elt_arg, s.element_index, s.element_coords)
|
|
@@ -446,7 +487,11 @@ class LocalAdjointField(SpaceField):
|
|
|
446
487
|
return eval_div_test_inner
|
|
447
488
|
|
|
448
489
|
def _make_eval_outer(self):
|
|
490
|
+
if not self._is_discontinuous:
|
|
491
|
+
return self.eval_inner
|
|
492
|
+
|
|
449
493
|
DOF_BEGIN = wp.constant(self._TAYLOR_DOF_OFFSETS[LocalAdjointField.OUTER_DOF])
|
|
494
|
+
zero_element = type_zero_element(self.dtype)
|
|
450
495
|
|
|
451
496
|
@cache.dynamic_func(suffix=self.name)
|
|
452
497
|
def eval_test_outer(args: self.ElementEvalArg, s: Sample):
|
|
@@ -454,7 +499,7 @@ class LocalAdjointField(SpaceField):
|
|
|
454
499
|
|
|
455
500
|
local_value_map = self.space.local_value_map_outer(args.elt_arg, s.element_index, s.element_coords)
|
|
456
501
|
dof_value = self.space.value_basis_element(value_dof, local_value_map)
|
|
457
|
-
return wp.where(taylor_dof == 0, dof_value,
|
|
502
|
+
return wp.where(taylor_dof == 0, dof_value, zero_element())
|
|
458
503
|
|
|
459
504
|
return eval_test_outer
|
|
460
505
|
|
|
@@ -464,13 +509,14 @@ class LocalAdjointField(SpaceField):
|
|
|
464
509
|
|
|
465
510
|
DOF_BEGIN = wp.constant(self._TAYLOR_DOF_OFFSETS[LocalAdjointField.OUTER_GRAD_DOF])
|
|
466
511
|
DOF_COUNT = wp.constant(self._TAYLOR_DOF_COUNTS[LocalAdjointField.OUTER_GRAD_DOF])
|
|
512
|
+
zero_element = type_zero_element(self.gradient_dtype)
|
|
467
513
|
|
|
468
514
|
@cache.dynamic_func(suffix=self.name)
|
|
469
515
|
def eval_nabla_test_outer(args: self.ElementEvalArg, s: Sample):
|
|
470
516
|
value_dof, taylor_dof = self._split_dof(self._get_dof(s), DOF_BEGIN)
|
|
471
517
|
|
|
472
518
|
if taylor_dof < 0 or taylor_dof >= DOF_COUNT:
|
|
473
|
-
return
|
|
519
|
+
return zero_element()
|
|
474
520
|
|
|
475
521
|
grad_transform = self.space.element_outer_reference_gradient_transform(args.elt_arg, s)
|
|
476
522
|
local_value_map = self.space.local_value_map_outer(args.elt_arg, s.element_index, s.element_coords)
|
|
@@ -485,13 +531,14 @@ class LocalAdjointField(SpaceField):
|
|
|
485
531
|
|
|
486
532
|
DOF_BEGIN = wp.constant(self._TAYLOR_DOF_OFFSETS[LocalAdjointField.OUTER_GRAD_DOF])
|
|
487
533
|
DOF_COUNT = wp.constant(self._TAYLOR_DOF_COUNTS[LocalAdjointField.OUTER_GRAD_DOF])
|
|
534
|
+
zero_element = type_zero_element(self.divergence_dtype)
|
|
488
535
|
|
|
489
536
|
@cache.dynamic_func(suffix=self.name)
|
|
490
537
|
def eval_div_test_outer(args: self.ElementEvalArg, s: Sample):
|
|
491
538
|
value_dof, taylor_dof = self._split_dof(self._get_dof(s), DOF_BEGIN)
|
|
492
539
|
|
|
493
540
|
if taylor_dof < 0 or taylor_dof >= DOF_COUNT:
|
|
494
|
-
return
|
|
541
|
+
return zero_element()
|
|
495
542
|
|
|
496
543
|
grad_transform = self.space.element_outer_reference_gradient_transform(args.elt_arg, s)
|
|
497
544
|
local_value_map = self.space.local_value_map_outer(args.elt_arg, s.element_index, s.element_coords)
|
|
@@ -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)
|