warp-lang 1.1.0__py3-none-macosx_10_13_universal2.whl → 1.2.1__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/bin/libwarp-clang.dylib +0 -0
- warp/bin/libwarp.dylib +0 -0
- warp/build.py +10 -37
- warp/build_dll.py +2 -2
- warp/builtins.py +274 -6
- warp/codegen.py +51 -4
- warp/config.py +2 -2
- warp/constants.py +4 -0
- warp/context.py +422 -203
- warp/examples/benchmarks/benchmark_api.py +0 -2
- warp/examples/benchmarks/benchmark_cloth_warp.py +0 -1
- warp/examples/benchmarks/benchmark_launches.py +0 -2
- warp/examples/core/example_dem.py +0 -2
- warp/examples/core/example_fluid.py +0 -2
- warp/examples/core/example_graph_capture.py +0 -2
- warp/examples/core/example_marching_cubes.py +0 -2
- warp/examples/core/example_mesh.py +0 -2
- warp/examples/core/example_mesh_intersect.py +0 -2
- warp/examples/core/example_nvdb.py +0 -2
- warp/examples/core/example_raycast.py +0 -2
- warp/examples/core/example_raymarch.py +0 -2
- warp/examples/core/example_render_opengl.py +0 -2
- warp/examples/core/example_sph.py +0 -2
- warp/examples/core/example_torch.py +0 -3
- warp/examples/core/example_wave.py +0 -2
- warp/examples/fem/example_apic_fluid.py +140 -115
- warp/examples/fem/example_burgers.py +262 -0
- warp/examples/fem/example_convection_diffusion.py +0 -2
- warp/examples/fem/example_convection_diffusion_dg.py +0 -2
- warp/examples/fem/example_deformed_geometry.py +0 -2
- warp/examples/fem/example_diffusion.py +0 -2
- warp/examples/fem/example_diffusion_3d.py +5 -4
- warp/examples/fem/example_diffusion_mgpu.py +0 -2
- warp/examples/fem/example_mixed_elasticity.py +0 -2
- warp/examples/fem/example_navier_stokes.py +0 -2
- warp/examples/fem/example_stokes.py +0 -2
- warp/examples/fem/example_stokes_transfer.py +0 -2
- warp/examples/optim/example_bounce.py +0 -2
- warp/examples/optim/example_cloth_throw.py +0 -2
- warp/examples/optim/example_diffray.py +0 -2
- warp/examples/optim/example_drone.py +0 -2
- warp/examples/optim/example_inverse_kinematics.py +0 -2
- warp/examples/optim/example_inverse_kinematics_torch.py +0 -2
- warp/examples/optim/example_spring_cage.py +0 -2
- warp/examples/optim/example_trajectory.py +0 -2
- warp/examples/optim/example_walker.py +0 -2
- warp/examples/sim/example_cartpole.py +0 -2
- warp/examples/sim/example_cloth.py +0 -2
- warp/examples/sim/example_granular.py +0 -2
- warp/examples/sim/example_granular_collision_sdf.py +0 -2
- warp/examples/sim/example_jacobian_ik.py +0 -2
- warp/examples/sim/example_particle_chain.py +0 -2
- warp/examples/sim/example_quadruped.py +0 -2
- warp/examples/sim/example_rigid_chain.py +0 -2
- warp/examples/sim/example_rigid_contact.py +0 -2
- warp/examples/sim/example_rigid_force.py +0 -2
- warp/examples/sim/example_rigid_gyroscopic.py +0 -2
- warp/examples/sim/example_rigid_soft_contact.py +0 -2
- warp/examples/sim/example_soft_body.py +0 -2
- warp/fem/__init__.py +1 -0
- warp/fem/cache.py +3 -1
- warp/fem/geometry/__init__.py +1 -0
- warp/fem/geometry/element.py +4 -0
- warp/fem/geometry/grid_3d.py +0 -4
- warp/fem/geometry/nanogrid.py +455 -0
- warp/fem/integrate.py +63 -9
- warp/fem/space/__init__.py +43 -158
- warp/fem/space/basis_space.py +34 -0
- warp/fem/space/collocated_function_space.py +1 -1
- warp/fem/space/grid_2d_function_space.py +13 -132
- warp/fem/space/grid_3d_function_space.py +16 -154
- warp/fem/space/hexmesh_function_space.py +37 -134
- warp/fem/space/nanogrid_function_space.py +202 -0
- warp/fem/space/quadmesh_2d_function_space.py +12 -119
- warp/fem/space/restriction.py +4 -1
- warp/fem/space/shape/__init__.py +77 -0
- warp/fem/space/shape/cube_shape_function.py +5 -15
- warp/fem/space/tetmesh_function_space.py +6 -76
- warp/fem/space/trimesh_2d_function_space.py +6 -76
- warp/native/array.h +12 -3
- warp/native/builtin.h +48 -5
- warp/native/bvh.cpp +14 -10
- warp/native/bvh.cu +23 -15
- warp/native/bvh.h +1 -0
- warp/native/clang/clang.cpp +2 -1
- warp/native/crt.cpp +11 -1
- warp/native/crt.h +18 -1
- warp/native/exports.h +187 -0
- warp/native/mat.h +47 -0
- warp/native/mesh.cpp +1 -1
- warp/native/mesh.cu +1 -2
- warp/native/nanovdb/GridHandle.h +366 -0
- warp/native/nanovdb/HostBuffer.h +590 -0
- warp/native/nanovdb/NanoVDB.h +3999 -2157
- warp/native/nanovdb/PNanoVDB.h +936 -99
- warp/native/quat.h +28 -1
- warp/native/rand.h +5 -1
- warp/native/vec.h +45 -1
- warp/native/volume.cpp +335 -103
- warp/native/volume.cu +39 -13
- warp/native/volume.h +725 -303
- warp/native/volume_builder.cu +381 -360
- warp/native/volume_builder.h +16 -1
- warp/native/volume_impl.h +61 -0
- warp/native/warp.cu +8 -2
- warp/native/warp.h +15 -7
- warp/render/render_opengl.py +191 -52
- warp/sim/integrator_featherstone.py +10 -3
- warp/sim/integrator_xpbd.py +16 -22
- warp/sparse.py +89 -27
- warp/stubs.py +83 -0
- warp/tests/assets/test_index_grid.nvdb +0 -0
- warp/tests/aux_test_dependent.py +0 -2
- warp/tests/aux_test_grad_customs.py +0 -2
- warp/tests/aux_test_reference.py +0 -2
- warp/tests/aux_test_reference_reference.py +0 -2
- warp/tests/aux_test_square.py +0 -2
- warp/tests/disabled_kinematics.py +0 -2
- warp/tests/test_adam.py +0 -2
- warp/tests/test_arithmetic.py +0 -36
- warp/tests/test_array.py +9 -11
- warp/tests/test_array_reduce.py +0 -2
- warp/tests/test_async.py +0 -2
- warp/tests/test_atomic.py +0 -2
- warp/tests/test_bool.py +58 -50
- warp/tests/test_builtins_resolution.py +0 -2
- warp/tests/test_bvh.py +0 -2
- warp/tests/test_closest_point_edge_edge.py +0 -1
- warp/tests/test_codegen.py +0 -4
- warp/tests/test_compile_consts.py +130 -10
- warp/tests/test_conditional.py +0 -2
- warp/tests/test_copy.py +0 -2
- warp/tests/test_ctypes.py +6 -8
- warp/tests/test_dense.py +0 -2
- warp/tests/test_devices.py +0 -2
- warp/tests/test_dlpack.py +9 -11
- warp/tests/test_examples.py +42 -39
- warp/tests/test_fabricarray.py +0 -3
- warp/tests/test_fast_math.py +0 -2
- warp/tests/test_fem.py +75 -54
- warp/tests/test_fp16.py +0 -2
- warp/tests/test_func.py +0 -2
- warp/tests/test_generics.py +27 -2
- warp/tests/test_grad.py +147 -8
- warp/tests/test_grad_customs.py +0 -2
- warp/tests/test_hash_grid.py +1 -3
- warp/tests/test_import.py +0 -2
- warp/tests/test_indexedarray.py +0 -2
- warp/tests/test_intersect.py +0 -2
- warp/tests/test_jax.py +0 -2
- warp/tests/test_large.py +11 -9
- warp/tests/test_launch.py +0 -2
- warp/tests/test_lerp.py +10 -54
- warp/tests/test_linear_solvers.py +3 -5
- warp/tests/test_lvalue.py +0 -2
- warp/tests/test_marching_cubes.py +0 -2
- warp/tests/test_mat.py +0 -2
- warp/tests/test_mat_lite.py +0 -2
- warp/tests/test_mat_scalar_ops.py +0 -2
- warp/tests/test_math.py +0 -2
- warp/tests/test_matmul.py +35 -37
- warp/tests/test_matmul_lite.py +29 -31
- warp/tests/test_mempool.py +0 -2
- warp/tests/test_mesh.py +0 -3
- warp/tests/test_mesh_query_aabb.py +0 -2
- warp/tests/test_mesh_query_point.py +0 -2
- warp/tests/test_mesh_query_ray.py +0 -2
- warp/tests/test_mlp.py +0 -2
- warp/tests/test_model.py +0 -2
- warp/tests/test_module_hashing.py +111 -0
- warp/tests/test_modules_lite.py +0 -3
- warp/tests/test_multigpu.py +0 -2
- warp/tests/test_noise.py +0 -4
- warp/tests/test_operators.py +0 -2
- warp/tests/test_options.py +0 -2
- warp/tests/test_peer.py +0 -2
- warp/tests/test_pinned.py +0 -2
- warp/tests/test_print.py +0 -2
- warp/tests/test_quat.py +0 -2
- warp/tests/test_rand.py +41 -5
- warp/tests/test_reload.py +0 -10
- warp/tests/test_rounding.py +0 -2
- warp/tests/test_runlength_encode.py +0 -2
- warp/tests/test_sim_grad.py +0 -2
- warp/tests/test_sim_kinematics.py +0 -2
- warp/tests/test_smoothstep.py +0 -2
- warp/tests/test_snippet.py +0 -2
- warp/tests/test_sparse.py +0 -2
- warp/tests/test_spatial.py +0 -2
- warp/tests/test_special_values.py +362 -0
- warp/tests/test_streams.py +0 -2
- warp/tests/test_struct.py +0 -2
- warp/tests/test_tape.py +0 -2
- warp/tests/test_torch.py +0 -2
- warp/tests/test_transient_module.py +0 -2
- warp/tests/test_types.py +0 -2
- warp/tests/test_utils.py +0 -2
- warp/tests/test_vec.py +0 -2
- warp/tests/test_vec_lite.py +0 -2
- warp/tests/test_vec_scalar_ops.py +0 -2
- warp/tests/test_verify_fp.py +0 -2
- warp/tests/test_volume.py +237 -13
- warp/tests/test_volume_write.py +86 -3
- warp/tests/unittest_serial.py +10 -9
- warp/tests/unittest_suites.py +6 -2
- warp/tests/unittest_utils.py +2 -171
- warp/tests/unused_test_misc.py +0 -2
- warp/tests/walkthrough_debug.py +1 -1
- warp/thirdparty/unittest_parallel.py +37 -40
- warp/types.py +526 -85
- {warp_lang-1.1.0.dist-info → warp_lang-1.2.1.dist-info}/METADATA +61 -31
- warp_lang-1.2.1.dist-info/RECORD +359 -0
- warp/examples/fem/example_convection_diffusion_dg0.py +0 -204
- warp/native/nanovdb/PNanoVDBWrite.h +0 -295
- warp_lang-1.1.0.dist-info/RECORD +0 -352
- {warp_lang-1.1.0.dist-info → warp_lang-1.2.1.dist-info}/LICENSE.md +0 -0
- {warp_lang-1.1.0.dist-info → warp_lang-1.2.1.dist-info}/WHEEL +0 -0
- {warp_lang-1.1.0.dist-info → warp_lang-1.2.1.dist-info}/top_level.txt +0 -0
|
@@ -6,23 +6,24 @@ from warp.fem.geometry.hexmesh import (
|
|
|
6
6
|
FACE_ORIENTATION,
|
|
7
7
|
FACE_TRANSLATION,
|
|
8
8
|
)
|
|
9
|
-
from warp.fem.polynomial import
|
|
10
|
-
from warp.fem.types import
|
|
9
|
+
from warp.fem.polynomial import is_closed
|
|
10
|
+
from warp.fem.types import ElementIndex
|
|
11
11
|
|
|
12
|
-
from .basis_space import ShapeBasisSpace, TraceBasisSpace
|
|
13
12
|
from .shape import (
|
|
14
|
-
ConstantShapeFunction,
|
|
15
|
-
CubeNonConformingPolynomialShapeFunctions,
|
|
16
13
|
CubeSerendipityShapeFunctions,
|
|
17
14
|
CubeTripolynomialShapeFunctions,
|
|
18
15
|
ShapeFunction,
|
|
19
16
|
)
|
|
20
|
-
from .topology import
|
|
17
|
+
from .topology import SpaceTopology, forward_base_topology
|
|
21
18
|
|
|
22
19
|
_FACE_ORIENTATION_I = wp.constant(wp.mat(shape=(16, 2), dtype=int)(FACE_ORIENTATION))
|
|
23
20
|
_FACE_TRANSLATION_I = wp.constant(wp.mat(shape=(4, 2), dtype=int)(FACE_TRANSLATION))
|
|
24
21
|
|
|
25
|
-
|
|
22
|
+
# map from shape function vertex indexing to hexmesh vertex indexing
|
|
23
|
+
_CUBE_TO_HEX_VERTEX = wp.constant(wp.vec(length=8, dtype=int)([0, 4, 3, 7, 1, 5, 2, 6]))
|
|
24
|
+
|
|
25
|
+
# map from shape function edge indexing to hexmesh edge indexing
|
|
26
|
+
_CUBE_TO_HEX_EDGE = wp.constant(wp.vec(length=12, dtype=int)([0, 4, 2, 6, 3, 1, 7, 5, 8, 11, 9, 10]))
|
|
26
27
|
|
|
27
28
|
|
|
28
29
|
@wp.struct
|
|
@@ -45,9 +46,12 @@ class HexmeshSpaceTopology(SpaceTopology):
|
|
|
45
46
|
need_hex_edge_indices: bool = True,
|
|
46
47
|
need_hex_face_indices: bool = True,
|
|
47
48
|
):
|
|
49
|
+
if not is_closed(shape.family):
|
|
50
|
+
raise ValueError("A closed polynomial family is required to define a continuous function space")
|
|
51
|
+
|
|
48
52
|
super().__init__(mesh, shape.NODES_PER_ELEMENT)
|
|
49
53
|
self._mesh = mesh
|
|
50
|
-
self.
|
|
54
|
+
self.shape = shape
|
|
51
55
|
|
|
52
56
|
if need_hex_edge_indices:
|
|
53
57
|
self._hex_edge_indices = self._mesh.hex_edge_indices
|
|
@@ -111,44 +115,6 @@ class HexmeshSpaceTopology(SpaceTopology):
|
|
|
111
115
|
hex_face_indices[hx1, local_face_1] = wp.vec2i(f, ori_1)
|
|
112
116
|
|
|
113
117
|
|
|
114
|
-
class HexmeshDiscontinuousSpaceTopology(
|
|
115
|
-
DiscontinuousSpaceTopologyMixin,
|
|
116
|
-
SpaceTopology,
|
|
117
|
-
):
|
|
118
|
-
def __init__(self, mesh: Hexmesh, shape: ShapeFunction):
|
|
119
|
-
super().__init__(mesh, shape.NODES_PER_ELEMENT)
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
class HexmeshBasisSpace(ShapeBasisSpace):
|
|
123
|
-
def __init__(self, topology: HexmeshSpaceTopology, shape: ShapeFunction):
|
|
124
|
-
super().__init__(topology, shape)
|
|
125
|
-
|
|
126
|
-
self._mesh: Hexmesh = topology.geometry
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
class HexmeshPiecewiseConstantBasis(HexmeshBasisSpace):
|
|
130
|
-
def __init__(self, mesh: Hexmesh):
|
|
131
|
-
shape = ConstantShapeFunction(mesh.reference_cell(), space_dimension=3)
|
|
132
|
-
topology = HexmeshDiscontinuousSpaceTopology(mesh, shape)
|
|
133
|
-
super().__init__(shape=shape, topology=topology)
|
|
134
|
-
|
|
135
|
-
class Trace(TraceBasisSpace):
|
|
136
|
-
@wp.func
|
|
137
|
-
def _node_coords_in_element(
|
|
138
|
-
side_arg: Hexmesh.SideArg,
|
|
139
|
-
basis_arg: HexmeshBasisSpace.BasisArg,
|
|
140
|
-
element_index: ElementIndex,
|
|
141
|
-
node_index_in_element: int,
|
|
142
|
-
):
|
|
143
|
-
return Coords(0.5, 0.5, 0.0)
|
|
144
|
-
|
|
145
|
-
def make_node_coords_in_element(self):
|
|
146
|
-
return self._node_coords_in_element
|
|
147
|
-
|
|
148
|
-
def trace(self):
|
|
149
|
-
return HexmeshPiecewiseConstantBasis.Trace(self)
|
|
150
|
-
|
|
151
|
-
|
|
152
118
|
class HexmeshTripolynomialSpaceTopology(HexmeshSpaceTopology):
|
|
153
119
|
def __init__(self, mesh: Hexmesh, shape: CubeTripolynomialShapeFunctions):
|
|
154
120
|
super().__init__(mesh, shape, need_hex_edge_indices=shape.ORDER >= 2, need_hex_face_indices=shape.ORDER >= 2)
|
|
@@ -156,7 +122,7 @@ class HexmeshTripolynomialSpaceTopology(HexmeshSpaceTopology):
|
|
|
156
122
|
self.element_node_index = self._make_element_node_index()
|
|
157
123
|
|
|
158
124
|
def node_count(self) -> int:
|
|
159
|
-
ORDER = self.
|
|
125
|
+
ORDER = self.shape.ORDER
|
|
160
126
|
INTERIOR_NODES_PER_EDGE = max(0, ORDER - 1)
|
|
161
127
|
INTERIOR_NODES_PER_FACE = INTERIOR_NODES_PER_EDGE**2
|
|
162
128
|
INTERIOR_NODES_PER_CELL = INTERIOR_NODES_PER_EDGE**3
|
|
@@ -182,7 +148,7 @@ class HexmeshTripolynomialSpaceTopology(HexmeshSpaceTopology):
|
|
|
182
148
|
return rot_i * size + rot_j
|
|
183
149
|
|
|
184
150
|
def _make_element_node_index(self):
|
|
185
|
-
ORDER = self.
|
|
151
|
+
ORDER = self.shape.ORDER
|
|
186
152
|
INTERIOR_NODES_PER_EDGE = wp.constant(max(0, ORDER - 1))
|
|
187
153
|
INTERIOR_NODES_PER_FACE = wp.constant(INTERIOR_NODES_PER_EDGE**2)
|
|
188
154
|
INTERIOR_NODES_PER_CELL = wp.constant(INTERIOR_NODES_PER_EDGE**3)
|
|
@@ -194,18 +160,19 @@ class HexmeshTripolynomialSpaceTopology(HexmeshSpaceTopology):
|
|
|
194
160
|
element_index: ElementIndex,
|
|
195
161
|
node_index_in_elt: int,
|
|
196
162
|
):
|
|
197
|
-
node_type, type_instance, type_index = self.
|
|
163
|
+
node_type, type_instance, type_index = self.shape.node_type_and_type_index(node_index_in_elt)
|
|
198
164
|
|
|
199
165
|
if node_type == CubeTripolynomialShapeFunctions.VERTEX:
|
|
200
|
-
return geo_arg.hex_vertex_indices[element_index,
|
|
166
|
+
return geo_arg.hex_vertex_indices[element_index, _CUBE_TO_HEX_VERTEX[type_instance]]
|
|
201
167
|
|
|
202
168
|
offset = topo_arg.vertex_count
|
|
203
169
|
|
|
204
170
|
if node_type == CubeTripolynomialShapeFunctions.EDGE:
|
|
205
|
-
|
|
171
|
+
hex_edge = _CUBE_TO_HEX_EDGE[type_instance]
|
|
172
|
+
edge_index = topo_arg.hex_edge_indices[element_index, hex_edge]
|
|
206
173
|
|
|
207
|
-
v0 = geo_arg.hex_vertex_indices[element_index, EDGE_VERTEX_INDICES[
|
|
208
|
-
v1 = geo_arg.hex_vertex_indices[element_index, EDGE_VERTEX_INDICES[
|
|
174
|
+
v0 = geo_arg.hex_vertex_indices[element_index, EDGE_VERTEX_INDICES[hex_edge, 0]]
|
|
175
|
+
v1 = geo_arg.hex_vertex_indices[element_index, EDGE_VERTEX_INDICES[hex_edge, 1]]
|
|
209
176
|
|
|
210
177
|
if v0 > v1:
|
|
211
178
|
type_index = ORDER - 1 - type_index
|
|
@@ -232,52 +199,21 @@ class HexmeshTripolynomialSpaceTopology(HexmeshSpaceTopology):
|
|
|
232
199
|
return element_node_index
|
|
233
200
|
|
|
234
201
|
|
|
235
|
-
class
|
|
236
|
-
def __init__(
|
|
237
|
-
self,
|
|
238
|
-
mesh: Hexmesh,
|
|
239
|
-
degree: int,
|
|
240
|
-
family: Polynomial,
|
|
241
|
-
):
|
|
242
|
-
if family is None:
|
|
243
|
-
family = Polynomial.LOBATTO_GAUSS_LEGENDRE
|
|
244
|
-
|
|
245
|
-
if not is_closed(family):
|
|
246
|
-
raise ValueError("A closed polynomial family is required to define a continuous function space")
|
|
247
|
-
|
|
248
|
-
shape = CubeTripolynomialShapeFunctions(degree, family=family)
|
|
249
|
-
topology = forward_base_topology(HexmeshTripolynomialSpaceTopology, mesh, shape)
|
|
250
|
-
|
|
251
|
-
super().__init__(topology, shape)
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
class HexmeshDGTripolynomialBasisSpace(HexmeshBasisSpace):
|
|
202
|
+
class HexmeshSerendipitySpaceTopology(HexmeshSpaceTopology):
|
|
255
203
|
def __init__(
|
|
256
204
|
self,
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
family: Polynomial,
|
|
205
|
+
grid: Hexmesh,
|
|
206
|
+
shape: CubeSerendipityShapeFunctions,
|
|
260
207
|
):
|
|
261
|
-
if family is None:
|
|
262
|
-
family = Polynomial.LOBATTO_GAUSS_LEGENDRE
|
|
263
|
-
|
|
264
|
-
shape = CubeTripolynomialShapeFunctions(degree, family=family)
|
|
265
|
-
topology = HexmeshDiscontinuousSpaceTopology(mesh, shape)
|
|
266
|
-
|
|
267
|
-
super().__init__(topology, shape)
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
class HexmeshSerendipitySpaceTopology(HexmeshSpaceTopology):
|
|
271
|
-
def __init__(self, grid: Hexmesh, shape: CubeSerendipityShapeFunctions):
|
|
272
208
|
super().__init__(grid, shape, need_hex_edge_indices=True, need_hex_face_indices=False)
|
|
273
209
|
|
|
274
210
|
self.element_node_index = self._make_element_node_index()
|
|
275
211
|
|
|
276
212
|
def node_count(self) -> int:
|
|
277
|
-
return self.geometry.vertex_count() + (self.
|
|
213
|
+
return self.geometry.vertex_count() + (self.shape.ORDER - 1) * self.geometry.edge_count()
|
|
278
214
|
|
|
279
215
|
def _make_element_node_index(self):
|
|
280
|
-
ORDER = self.
|
|
216
|
+
ORDER = self.shape.ORDER
|
|
281
217
|
|
|
282
218
|
@cache.dynamic_func(suffix=self.name)
|
|
283
219
|
def element_node_index(
|
|
@@ -286,17 +222,18 @@ class HexmeshSerendipitySpaceTopology(HexmeshSpaceTopology):
|
|
|
286
222
|
element_index: ElementIndex,
|
|
287
223
|
node_index_in_elt: int,
|
|
288
224
|
):
|
|
289
|
-
node_type, type_index = self.
|
|
225
|
+
node_type, type_index = self.shape.node_type_and_type_index(node_index_in_elt)
|
|
290
226
|
|
|
291
227
|
if node_type == CubeSerendipityShapeFunctions.VERTEX:
|
|
292
|
-
return cell_arg.hex_vertex_indices[element_index,
|
|
228
|
+
return cell_arg.hex_vertex_indices[element_index, _CUBE_TO_HEX_VERTEX[type_index]]
|
|
293
229
|
|
|
294
230
|
type_instance, index_in_edge = CubeSerendipityShapeFunctions._cube_edge_index(node_type, type_index)
|
|
231
|
+
hex_edge = _CUBE_TO_HEX_EDGE[type_instance]
|
|
295
232
|
|
|
296
|
-
edge_index = topo_arg.hex_edge_indices[element_index,
|
|
233
|
+
edge_index = topo_arg.hex_edge_indices[element_index, hex_edge]
|
|
297
234
|
|
|
298
|
-
v0 = cell_arg.hex_vertex_indices[element_index, EDGE_VERTEX_INDICES[
|
|
299
|
-
v1 = cell_arg.hex_vertex_indices[element_index, EDGE_VERTEX_INDICES[
|
|
235
|
+
v0 = cell_arg.hex_vertex_indices[element_index, EDGE_VERTEX_INDICES[hex_edge, 0]]
|
|
236
|
+
v1 = cell_arg.hex_vertex_indices[element_index, EDGE_VERTEX_INDICES[hex_edge, 1]]
|
|
300
237
|
|
|
301
238
|
if v0 > v1:
|
|
302
239
|
index_in_edge = ORDER - 1 - index_in_edge
|
|
@@ -306,45 +243,11 @@ class HexmeshSerendipitySpaceTopology(HexmeshSpaceTopology):
|
|
|
306
243
|
return element_node_index
|
|
307
244
|
|
|
308
245
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
mesh: Hexmesh,
|
|
313
|
-
degree: int,
|
|
314
|
-
family: Polynomial,
|
|
315
|
-
):
|
|
316
|
-
if family is None:
|
|
317
|
-
family = Polynomial.LOBATTO_GAUSS_LEGENDRE
|
|
318
|
-
|
|
319
|
-
shape = CubeSerendipityShapeFunctions(degree, family=family)
|
|
320
|
-
topology = forward_base_topology(HexmeshSerendipitySpaceTopology, mesh, shape=shape)
|
|
321
|
-
|
|
322
|
-
super().__init__(topology=topology, shape=shape)
|
|
246
|
+
def make_hexmesh_space_topology(mesh: Hexmesh, shape: ShapeFunction):
|
|
247
|
+
if isinstance(shape, CubeSerendipityShapeFunctions):
|
|
248
|
+
return forward_base_topology(HexmeshSerendipitySpaceTopology, mesh, shape)
|
|
323
249
|
|
|
250
|
+
if isinstance(shape, CubeTripolynomialShapeFunctions):
|
|
251
|
+
return forward_base_topology(HexmeshTripolynomialSpaceTopology, mesh, shape)
|
|
324
252
|
|
|
325
|
-
|
|
326
|
-
def __init__(
|
|
327
|
-
self,
|
|
328
|
-
mesh: Hexmesh,
|
|
329
|
-
degree: int,
|
|
330
|
-
family: Polynomial,
|
|
331
|
-
):
|
|
332
|
-
if family is None:
|
|
333
|
-
family = Polynomial.LOBATTO_GAUSS_LEGENDRE
|
|
334
|
-
|
|
335
|
-
shape = CubeSerendipityShapeFunctions(degree, family=family)
|
|
336
|
-
topology = HexmeshDiscontinuousSpaceTopology(mesh, shape=shape)
|
|
337
|
-
|
|
338
|
-
super().__init__(topology=topology, shape=shape)
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
class HexmeshPolynomialBasisSpace(HexmeshBasisSpace):
|
|
342
|
-
def __init__(
|
|
343
|
-
self,
|
|
344
|
-
mesh: Hexmesh,
|
|
345
|
-
degree: int,
|
|
346
|
-
):
|
|
347
|
-
shape = CubeNonConformingPolynomialShapeFunctions(degree)
|
|
348
|
-
topology = HexmeshDiscontinuousSpaceTopology(mesh, shape)
|
|
349
|
-
|
|
350
|
-
super().__init__(topology, shape)
|
|
253
|
+
raise ValueError(f"Unsupported shape function {shape.name}")
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import warp as wp
|
|
2
|
+
from warp.fem import cache
|
|
3
|
+
from warp.fem.geometry import Nanogrid
|
|
4
|
+
from warp.fem.geometry.nanogrid import _add_axis_flag
|
|
5
|
+
from warp.fem.polynomial import is_closed
|
|
6
|
+
from warp.fem.types import ElementIndex
|
|
7
|
+
|
|
8
|
+
from .shape import (
|
|
9
|
+
CubeSerendipityShapeFunctions,
|
|
10
|
+
CubeTripolynomialShapeFunctions,
|
|
11
|
+
ShapeFunction,
|
|
12
|
+
)
|
|
13
|
+
from .topology import SpaceTopology, forward_base_topology
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@wp.struct
|
|
17
|
+
class NanogridTopologyArg:
|
|
18
|
+
vertex_grid: wp.uint64
|
|
19
|
+
face_grid: wp.uint64
|
|
20
|
+
edge_grid: wp.uint64
|
|
21
|
+
|
|
22
|
+
vertex_count: int
|
|
23
|
+
edge_count: int
|
|
24
|
+
face_count: int
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class NanogridSpaceTopology(SpaceTopology):
|
|
28
|
+
TopologyArg = NanogridTopologyArg
|
|
29
|
+
|
|
30
|
+
def __init__(
|
|
31
|
+
self,
|
|
32
|
+
grid: Nanogrid,
|
|
33
|
+
shape: ShapeFunction,
|
|
34
|
+
need_edge_indices: bool = True,
|
|
35
|
+
need_face_indices: bool = True,
|
|
36
|
+
):
|
|
37
|
+
if not is_closed(shape.family):
|
|
38
|
+
raise ValueError("A closed polynomial family is required to define a continuous function space")
|
|
39
|
+
|
|
40
|
+
super().__init__(grid, shape.NODES_PER_ELEMENT)
|
|
41
|
+
self._grid = grid
|
|
42
|
+
self._shape = shape
|
|
43
|
+
|
|
44
|
+
if need_edge_indices:
|
|
45
|
+
self._edge_count = self._grid.edge_count()
|
|
46
|
+
else:
|
|
47
|
+
self._edge_count = 0
|
|
48
|
+
|
|
49
|
+
self._vertex_grid = grid._node_grid
|
|
50
|
+
self._face_grid = grid._face_grid
|
|
51
|
+
self._edge_grid = grid._edge_grid
|
|
52
|
+
|
|
53
|
+
@cache.cached_arg_value
|
|
54
|
+
def topo_arg_value(self, device):
|
|
55
|
+
arg = NanogridTopologyArg()
|
|
56
|
+
|
|
57
|
+
arg.vertex_grid = self._vertex_grid.id
|
|
58
|
+
arg.face_grid = self._face_grid.id
|
|
59
|
+
arg.edge_grid = -1 if self._edge_grid is None else self._edge_grid.id
|
|
60
|
+
|
|
61
|
+
arg.vertex_count = self._grid.vertex_count()
|
|
62
|
+
arg.face_count = self._grid.side_count()
|
|
63
|
+
arg.edge_count = self._edge_count
|
|
64
|
+
return arg
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
@wp.func
|
|
68
|
+
def _cell_vertex_coord(cell_ijk: wp.vec3i, n: int):
|
|
69
|
+
return cell_ijk + wp.vec3i((n & 4) >> 2, (n & 2) >> 1, n & 1)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@wp.func
|
|
73
|
+
def _cell_edge_coord(cell_ijk: wp.vec3i, axis: int, offset: int):
|
|
74
|
+
e_ijk = cell_ijk
|
|
75
|
+
e_ijk[(axis + 1) % 3] += offset >> 1
|
|
76
|
+
e_ijk[(axis + 2) % 3] += offset & 1
|
|
77
|
+
return _add_axis_flag(e_ijk, axis)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
@wp.func
|
|
81
|
+
def _cell_face_coord(cell_ijk: wp.vec3i, axis: int, offset: int):
|
|
82
|
+
f_ijk = cell_ijk
|
|
83
|
+
f_ijk[axis] += offset
|
|
84
|
+
return _add_axis_flag(f_ijk, axis)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
class NanogridTripolynomialSpaceTopology(NanogridSpaceTopology):
|
|
88
|
+
def __init__(self, grid: Nanogrid, shape: CubeTripolynomialShapeFunctions):
|
|
89
|
+
super().__init__(grid, shape, need_edge_indices=shape.ORDER >= 2, need_face_indices=shape.ORDER >= 2)
|
|
90
|
+
|
|
91
|
+
self.element_node_index = self._make_element_node_index()
|
|
92
|
+
|
|
93
|
+
def node_count(self) -> int:
|
|
94
|
+
ORDER = self._shape.ORDER
|
|
95
|
+
INTERIOR_NODES_PER_EDGE = max(0, ORDER - 1)
|
|
96
|
+
INTERIOR_NODES_PER_FACE = INTERIOR_NODES_PER_EDGE**2
|
|
97
|
+
INTERIOR_NODES_PER_CELL = INTERIOR_NODES_PER_EDGE**3
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
self._grid.vertex_count()
|
|
101
|
+
+ self._grid.edge_count() * INTERIOR_NODES_PER_EDGE
|
|
102
|
+
+ self._grid.side_count() * INTERIOR_NODES_PER_FACE
|
|
103
|
+
+ self._grid.cell_count() * INTERIOR_NODES_PER_CELL
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
def _make_element_node_index(self):
|
|
107
|
+
ORDER = self._shape.ORDER
|
|
108
|
+
INTERIOR_NODES_PER_EDGE = wp.constant(max(0, ORDER - 1))
|
|
109
|
+
INTERIOR_NODES_PER_FACE = wp.constant(INTERIOR_NODES_PER_EDGE**2)
|
|
110
|
+
INTERIOR_NODES_PER_CELL = wp.constant(INTERIOR_NODES_PER_EDGE**3)
|
|
111
|
+
|
|
112
|
+
@cache.dynamic_func(suffix=self.name)
|
|
113
|
+
def element_node_index(
|
|
114
|
+
geo_arg: Nanogrid.CellArg,
|
|
115
|
+
topo_arg: NanogridTopologyArg,
|
|
116
|
+
element_index: ElementIndex,
|
|
117
|
+
node_index_in_elt: int,
|
|
118
|
+
):
|
|
119
|
+
node_type, type_instance, type_index = self._shape.node_type_and_type_index(node_index_in_elt)
|
|
120
|
+
|
|
121
|
+
ijk = geo_arg.cell_ijk[element_index]
|
|
122
|
+
|
|
123
|
+
if node_type == CubeTripolynomialShapeFunctions.VERTEX:
|
|
124
|
+
n_ijk = _cell_vertex_coord(ijk, type_instance)
|
|
125
|
+
return wp.volume_lookup_index(topo_arg.vertex_grid, n_ijk[0], n_ijk[1], n_ijk[2])
|
|
126
|
+
|
|
127
|
+
offset = topo_arg.vertex_count
|
|
128
|
+
|
|
129
|
+
if node_type == CubeTripolynomialShapeFunctions.EDGE:
|
|
130
|
+
axis = type_instance >> 2
|
|
131
|
+
node_offset = type_instance & 3
|
|
132
|
+
|
|
133
|
+
n_ijk = _cell_edge_coord(ijk, axis, node_offset)
|
|
134
|
+
|
|
135
|
+
edge_index = wp.volume_lookup_index(topo_arg.edge_grid, n_ijk[0], n_ijk[1], n_ijk[2])
|
|
136
|
+
return offset + INTERIOR_NODES_PER_EDGE * edge_index + type_index
|
|
137
|
+
|
|
138
|
+
offset += INTERIOR_NODES_PER_EDGE * topo_arg.edge_count
|
|
139
|
+
|
|
140
|
+
if node_type == CubeTripolynomialShapeFunctions.FACE:
|
|
141
|
+
axis = type_instance >> 1
|
|
142
|
+
node_offset = type_instance & 1
|
|
143
|
+
|
|
144
|
+
n_ijk = _cell_face_coord(ijk, axis, node_offset)
|
|
145
|
+
|
|
146
|
+
face_index = wp.volume_lookup_index(topo_arg.face_grid, n_ijk[0], n_ijk[1], n_ijk[2])
|
|
147
|
+
return offset + INTERIOR_NODES_PER_FACE * face_index + type_index
|
|
148
|
+
|
|
149
|
+
offset += INTERIOR_NODES_PER_FACE * topo_arg.face_count
|
|
150
|
+
|
|
151
|
+
return offset + INTERIOR_NODES_PER_CELL * element_index + type_index
|
|
152
|
+
|
|
153
|
+
return element_node_index
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
class NanogridSerendipitySpaceTopology(NanogridSpaceTopology):
|
|
157
|
+
def __init__(self, grid: Nanogrid, shape: CubeSerendipityShapeFunctions):
|
|
158
|
+
super().__init__(grid, shape, need_edge_indices=True, need_face_indices=False)
|
|
159
|
+
|
|
160
|
+
self.element_node_index = self._make_element_node_index()
|
|
161
|
+
|
|
162
|
+
def node_count(self) -> int:
|
|
163
|
+
return self.geometry.vertex_count() + (self._shape.ORDER - 1) * self.geometry.edge_count()
|
|
164
|
+
|
|
165
|
+
def _make_element_node_index(self):
|
|
166
|
+
ORDER = self._shape.ORDER
|
|
167
|
+
|
|
168
|
+
@cache.dynamic_func(suffix=self.name)
|
|
169
|
+
def element_node_index(
|
|
170
|
+
cell_arg: Nanogrid.CellArg,
|
|
171
|
+
topo_arg: NanogridSpaceTopology.TopologyArg,
|
|
172
|
+
element_index: ElementIndex,
|
|
173
|
+
node_index_in_elt: int,
|
|
174
|
+
):
|
|
175
|
+
node_type, type_index = self._shape.node_type_and_type_index(node_index_in_elt)
|
|
176
|
+
|
|
177
|
+
ijk = cell_arg.cell_ijk[element_index]
|
|
178
|
+
|
|
179
|
+
if node_type == CubeSerendipityShapeFunctions.VERTEX:
|
|
180
|
+
n_ijk = _cell_vertex_coord(ijk, type_index)
|
|
181
|
+
return wp.volume_lookup_index(topo_arg.vertex_grid, n_ijk[0], n_ijk[1], n_ijk[2])
|
|
182
|
+
|
|
183
|
+
type_instance, index_in_edge = CubeSerendipityShapeFunctions._cube_edge_index(node_type, type_index)
|
|
184
|
+
axis = type_instance >> 2
|
|
185
|
+
node_offset = type_instance & 3
|
|
186
|
+
|
|
187
|
+
n_ijk = _cell_edge_coord(ijk, axis, node_offset)
|
|
188
|
+
|
|
189
|
+
edge_index = wp.volume_lookup_index(topo_arg.edge_grid, n_ijk[0], n_ijk[1], n_ijk[2])
|
|
190
|
+
return topo_arg.vertex_count + (ORDER - 1) * edge_index + index_in_edge
|
|
191
|
+
|
|
192
|
+
return element_node_index
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def make_nanogrid_space_topology(grid: Nanogrid, shape: ShapeFunction):
|
|
196
|
+
if isinstance(shape, CubeSerendipityShapeFunctions):
|
|
197
|
+
return forward_base_topology(NanogridSerendipitySpaceTopology, grid, shape)
|
|
198
|
+
|
|
199
|
+
if isinstance(shape, CubeTripolynomialShapeFunctions):
|
|
200
|
+
return forward_base_topology(NanogridTripolynomialSpaceTopology, grid, shape)
|
|
201
|
+
|
|
202
|
+
raise ValueError(f"Unsupported shape function {shape.name}")
|
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
import warp as wp
|
|
2
2
|
from warp.fem import cache
|
|
3
3
|
from warp.fem.geometry import Quadmesh2D
|
|
4
|
-
from warp.fem.polynomial import
|
|
5
|
-
from warp.fem.types import
|
|
4
|
+
from warp.fem.polynomial import is_closed
|
|
5
|
+
from warp.fem.types import ElementIndex
|
|
6
6
|
|
|
7
|
-
from .basis_space import ShapeBasisSpace, TraceBasisSpace
|
|
8
7
|
from .shape import (
|
|
9
|
-
ConstantShapeFunction,
|
|
10
8
|
ShapeFunction,
|
|
11
9
|
SquareBipolynomialShapeFunctions,
|
|
12
|
-
SquareNonConformingPolynomialShapeFunctions,
|
|
13
10
|
SquareSerendipityShapeFunctions,
|
|
14
11
|
)
|
|
15
|
-
from .topology import
|
|
12
|
+
from .topology import SpaceTopology, forward_base_topology
|
|
16
13
|
|
|
17
14
|
|
|
18
15
|
@wp.struct
|
|
@@ -28,6 +25,9 @@ class Quadmesh2DSpaceTopology(SpaceTopology):
|
|
|
28
25
|
TopologyArg = Quadmesh2DTopologyArg
|
|
29
26
|
|
|
30
27
|
def __init__(self, mesh: Quadmesh2D, shape: ShapeFunction):
|
|
28
|
+
if not is_closed(shape.family):
|
|
29
|
+
raise ValueError("A closed polynomial family is required to define a continuous function space")
|
|
30
|
+
|
|
31
31
|
super().__init__(mesh, shape.NODES_PER_ELEMENT)
|
|
32
32
|
self._mesh = mesh
|
|
33
33
|
self._shape = shape
|
|
@@ -107,44 +107,6 @@ class Quadmesh2DSpaceTopology(SpaceTopology):
|
|
|
107
107
|
quad_edge_indices[q1, t1_edge] = e
|
|
108
108
|
|
|
109
109
|
|
|
110
|
-
class Quadmesh2DDiscontinuousSpaceTopology(
|
|
111
|
-
DiscontinuousSpaceTopologyMixin,
|
|
112
|
-
SpaceTopology,
|
|
113
|
-
):
|
|
114
|
-
def __init__(self, mesh: Quadmesh2D, shape: ShapeFunction):
|
|
115
|
-
super().__init__(mesh, shape.NODES_PER_ELEMENT)
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
class Quadmesh2DBasisSpace(ShapeBasisSpace):
|
|
119
|
-
def __init__(self, topology: Quadmesh2DSpaceTopology, shape: ShapeFunction):
|
|
120
|
-
super().__init__(topology, shape)
|
|
121
|
-
|
|
122
|
-
self._mesh: Quadmesh2D = topology.geometry
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
class Quadmesh2DPiecewiseConstantBasis(Quadmesh2DBasisSpace):
|
|
126
|
-
def __init__(self, mesh: Quadmesh2D):
|
|
127
|
-
shape = ConstantShapeFunction(mesh.reference_cell(), space_dimension=2)
|
|
128
|
-
topology = Quadmesh2DDiscontinuousSpaceTopology(mesh, shape)
|
|
129
|
-
super().__init__(shape=shape, topology=topology)
|
|
130
|
-
|
|
131
|
-
class Trace(TraceBasisSpace):
|
|
132
|
-
@wp.func
|
|
133
|
-
def _node_coords_in_element(
|
|
134
|
-
side_arg: Quadmesh2D.SideArg,
|
|
135
|
-
basis_arg: Quadmesh2DBasisSpace.BasisArg,
|
|
136
|
-
element_index: ElementIndex,
|
|
137
|
-
node_index_in_element: int,
|
|
138
|
-
):
|
|
139
|
-
return Coords(0.5, 0.0, 0.0)
|
|
140
|
-
|
|
141
|
-
def make_node_coords_in_element(self):
|
|
142
|
-
return self._node_coords_in_element
|
|
143
|
-
|
|
144
|
-
def trace(self):
|
|
145
|
-
return Quadmesh2DPiecewiseConstantBasis.Trace(self)
|
|
146
|
-
|
|
147
|
-
|
|
148
110
|
class Quadmesh2DBipolynomialSpaceTopology(Quadmesh2DSpaceTopology):
|
|
149
111
|
def __init__(self, mesh: Quadmesh2D, shape: SquareBipolynomialShapeFunctions):
|
|
150
112
|
super().__init__(mesh, shape)
|
|
@@ -236,41 +198,6 @@ class Quadmesh2DBipolynomialSpaceTopology(Quadmesh2DSpaceTopology):
|
|
|
236
198
|
return element_node_index
|
|
237
199
|
|
|
238
200
|
|
|
239
|
-
class Quadmesh2DBipolynomialBasisSpace(Quadmesh2DBasisSpace):
|
|
240
|
-
def __init__(
|
|
241
|
-
self,
|
|
242
|
-
mesh: Quadmesh2D,
|
|
243
|
-
degree: int,
|
|
244
|
-
family: Polynomial,
|
|
245
|
-
):
|
|
246
|
-
if family is None:
|
|
247
|
-
family = Polynomial.LOBATTO_GAUSS_LEGENDRE
|
|
248
|
-
|
|
249
|
-
if not is_closed(family):
|
|
250
|
-
raise ValueError("A closed polynomial family is required to define a continuous function space")
|
|
251
|
-
|
|
252
|
-
shape = SquareBipolynomialShapeFunctions(degree, family=family)
|
|
253
|
-
topology = forward_base_topology(Quadmesh2DBipolynomialSpaceTopology, mesh, shape)
|
|
254
|
-
|
|
255
|
-
super().__init__(topology, shape)
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
class Quadmesh2DDGBipolynomialBasisSpace(Quadmesh2DBasisSpace):
|
|
259
|
-
def __init__(
|
|
260
|
-
self,
|
|
261
|
-
mesh: Quadmesh2D,
|
|
262
|
-
degree: int,
|
|
263
|
-
family: Polynomial,
|
|
264
|
-
):
|
|
265
|
-
if family is None:
|
|
266
|
-
family = Polynomial.LOBATTO_GAUSS_LEGENDRE
|
|
267
|
-
|
|
268
|
-
shape = SquareBipolynomialShapeFunctions(degree, family=family)
|
|
269
|
-
topology = Quadmesh2DDiscontinuousSpaceTopology(mesh, shape)
|
|
270
|
-
|
|
271
|
-
super().__init__(topology, shape)
|
|
272
|
-
|
|
273
|
-
|
|
274
201
|
class Quadmesh2DSerendipitySpaceTopology(Quadmesh2DSpaceTopology):
|
|
275
202
|
def __init__(self, grid: Quadmesh2D, shape: SquareSerendipityShapeFunctions):
|
|
276
203
|
super().__init__(grid, shape)
|
|
@@ -324,45 +251,11 @@ class Quadmesh2DSerendipitySpaceTopology(Quadmesh2DSpaceTopology):
|
|
|
324
251
|
return element_node_index
|
|
325
252
|
|
|
326
253
|
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
mesh: Quadmesh2D,
|
|
331
|
-
degree: int,
|
|
332
|
-
family: Polynomial,
|
|
333
|
-
):
|
|
334
|
-
if family is None:
|
|
335
|
-
family = Polynomial.LOBATTO_GAUSS_LEGENDRE
|
|
254
|
+
def make_quadmesh_2d_space_topology(mesh: Quadmesh2D, shape: ShapeFunction):
|
|
255
|
+
if isinstance(shape, SquareSerendipityShapeFunctions):
|
|
256
|
+
return forward_base_topology(Quadmesh2DSerendipitySpaceTopology, mesh, shape)
|
|
336
257
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
super().__init__(topology=topology, shape=shape)
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
class Quadmesh2DDGSerendipityBasisSpace(Quadmesh2DBasisSpace):
|
|
344
|
-
def __init__(
|
|
345
|
-
self,
|
|
346
|
-
mesh: Quadmesh2D,
|
|
347
|
-
degree: int,
|
|
348
|
-
family: Polynomial,
|
|
349
|
-
):
|
|
350
|
-
if family is None:
|
|
351
|
-
family = Polynomial.LOBATTO_GAUSS_LEGENDRE
|
|
352
|
-
|
|
353
|
-
shape = SquareSerendipityShapeFunctions(degree, family=family)
|
|
354
|
-
topology = Quadmesh2DDiscontinuousSpaceTopology(mesh, shape=shape)
|
|
355
|
-
|
|
356
|
-
super().__init__(topology=topology, shape=shape)
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
class Quadmesh2DPolynomialBasisSpace(Quadmesh2DBasisSpace):
|
|
360
|
-
def __init__(
|
|
361
|
-
self,
|
|
362
|
-
mesh: Quadmesh2D,
|
|
363
|
-
degree: int,
|
|
364
|
-
):
|
|
365
|
-
shape = SquareNonConformingPolynomialShapeFunctions(degree)
|
|
366
|
-
topology = Quadmesh2DDiscontinuousSpaceTopology(mesh, shape)
|
|
258
|
+
if isinstance(shape, SquareBipolynomialShapeFunctions):
|
|
259
|
+
return forward_base_topology(Quadmesh2DBipolynomialSpaceTopology, mesh, shape)
|
|
367
260
|
|
|
368
|
-
|
|
261
|
+
raise ValueError(f"Unsupported shape function {shape.name}")
|
warp/fem/space/restriction.py
CHANGED
|
@@ -38,7 +38,10 @@ class SpaceRestriction:
|
|
|
38
38
|
|
|
39
39
|
NODES_PER_ELEMENT = self.space_topology.NODES_PER_ELEMENT
|
|
40
40
|
|
|
41
|
-
@cache.dynamic_kernel(
|
|
41
|
+
@cache.dynamic_kernel(
|
|
42
|
+
suffix=f"{self.domain.name}_{self.space_topology.name}_{self.space_partition.name}",
|
|
43
|
+
kernel_options={"max_unroll": 8},
|
|
44
|
+
)
|
|
42
45
|
def fill_element_node_indices(
|
|
43
46
|
element_arg: self.domain.ElementArg,
|
|
44
47
|
domain_index_arg: self.domain.ElementIndexArg,
|