warp-lang 1.0.0b2__py3-none-win_amd64.whl → 1.0.0b6__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.
- docs/conf.py +17 -5
- examples/env/env_ant.py +1 -1
- examples/env/env_cartpole.py +1 -1
- examples/env/env_humanoid.py +1 -1
- examples/env/env_usd.py +4 -1
- examples/env/environment.py +8 -9
- examples/example_dem.py +34 -33
- examples/example_diffray.py +364 -337
- examples/example_fluid.py +32 -23
- examples/example_jacobian_ik.py +97 -93
- examples/example_marching_cubes.py +6 -16
- examples/example_mesh.py +6 -16
- examples/example_mesh_intersect.py +16 -14
- examples/example_nvdb.py +14 -16
- examples/example_raycast.py +14 -13
- examples/example_raymarch.py +16 -23
- examples/example_render_opengl.py +19 -10
- examples/example_sim_cartpole.py +82 -78
- examples/example_sim_cloth.py +45 -48
- examples/example_sim_fk_grad.py +51 -44
- examples/example_sim_fk_grad_torch.py +47 -40
- examples/example_sim_grad_bounce.py +108 -133
- examples/example_sim_grad_cloth.py +99 -113
- examples/example_sim_granular.py +5 -6
- examples/{example_sim_sdf_shape.py → example_sim_granular_collision_sdf.py} +37 -26
- examples/example_sim_neo_hookean.py +51 -55
- examples/example_sim_particle_chain.py +4 -4
- examples/example_sim_quadruped.py +126 -81
- examples/example_sim_rigid_chain.py +54 -61
- examples/example_sim_rigid_contact.py +66 -70
- examples/example_sim_rigid_fem.py +3 -3
- examples/example_sim_rigid_force.py +1 -1
- examples/example_sim_rigid_gyroscopic.py +3 -4
- examples/example_sim_rigid_kinematics.py +28 -39
- examples/example_sim_trajopt.py +112 -110
- examples/example_sph.py +9 -8
- examples/example_wave.py +7 -7
- examples/fem/bsr_utils.py +30 -17
- examples/fem/example_apic_fluid.py +85 -69
- examples/fem/example_convection_diffusion.py +97 -93
- examples/fem/example_convection_diffusion_dg.py +142 -149
- examples/fem/example_convection_diffusion_dg0.py +141 -136
- examples/fem/example_deformed_geometry.py +146 -0
- examples/fem/example_diffusion.py +115 -84
- examples/fem/example_diffusion_3d.py +116 -86
- examples/fem/example_diffusion_mgpu.py +102 -79
- examples/fem/example_mixed_elasticity.py +139 -100
- examples/fem/example_navier_stokes.py +175 -162
- examples/fem/example_stokes.py +143 -111
- examples/fem/example_stokes_transfer.py +186 -157
- examples/fem/mesh_utils.py +59 -97
- examples/fem/plot_utils.py +138 -17
- tools/ci/publishing/build_nodes_info.py +54 -0
- warp/__init__.py +4 -3
- warp/__init__.pyi +1 -0
- warp/bin/warp-clang.dll +0 -0
- warp/bin/warp.dll +0 -0
- warp/build.py +5 -3
- warp/build_dll.py +29 -9
- warp/builtins.py +836 -492
- warp/codegen.py +864 -553
- warp/config.py +3 -1
- warp/context.py +389 -172
- warp/fem/__init__.py +24 -6
- warp/fem/cache.py +318 -25
- warp/fem/dirichlet.py +7 -3
- warp/fem/domain.py +14 -0
- warp/fem/field/__init__.py +30 -38
- warp/fem/field/field.py +149 -0
- warp/fem/field/nodal_field.py +244 -138
- warp/fem/field/restriction.py +8 -6
- warp/fem/field/test.py +127 -59
- warp/fem/field/trial.py +117 -60
- warp/fem/geometry/__init__.py +5 -1
- warp/fem/geometry/deformed_geometry.py +271 -0
- warp/fem/geometry/element.py +24 -1
- warp/fem/geometry/geometry.py +86 -14
- warp/fem/geometry/grid_2d.py +112 -54
- warp/fem/geometry/grid_3d.py +134 -65
- warp/fem/geometry/hexmesh.py +953 -0
- warp/fem/geometry/partition.py +85 -33
- warp/fem/geometry/quadmesh_2d.py +532 -0
- warp/fem/geometry/tetmesh.py +451 -115
- warp/fem/geometry/trimesh_2d.py +197 -92
- warp/fem/integrate.py +534 -268
- warp/fem/operator.py +58 -31
- warp/fem/polynomial.py +11 -0
- warp/fem/quadrature/__init__.py +1 -1
- warp/fem/quadrature/pic_quadrature.py +150 -58
- warp/fem/quadrature/quadrature.py +209 -57
- warp/fem/space/__init__.py +230 -53
- warp/fem/space/basis_space.py +489 -0
- warp/fem/space/collocated_function_space.py +105 -0
- warp/fem/space/dof_mapper.py +49 -2
- warp/fem/space/function_space.py +90 -39
- warp/fem/space/grid_2d_function_space.py +149 -496
- warp/fem/space/grid_3d_function_space.py +173 -538
- warp/fem/space/hexmesh_function_space.py +352 -0
- warp/fem/space/partition.py +129 -76
- warp/fem/space/quadmesh_2d_function_space.py +369 -0
- warp/fem/space/restriction.py +46 -34
- warp/fem/space/shape/__init__.py +15 -0
- warp/fem/space/shape/cube_shape_function.py +738 -0
- warp/fem/space/shape/shape_function.py +103 -0
- warp/fem/space/shape/square_shape_function.py +611 -0
- warp/fem/space/shape/tet_shape_function.py +567 -0
- warp/fem/space/shape/triangle_shape_function.py +429 -0
- warp/fem/space/tetmesh_function_space.py +132 -1039
- warp/fem/space/topology.py +295 -0
- warp/fem/space/trimesh_2d_function_space.py +104 -742
- warp/fem/types.py +13 -11
- warp/fem/utils.py +335 -60
- warp/native/array.h +120 -34
- warp/native/builtin.h +101 -72
- warp/native/bvh.cpp +73 -325
- warp/native/bvh.cu +406 -23
- warp/native/bvh.h +22 -40
- warp/native/clang/clang.cpp +1 -0
- warp/native/crt.h +2 -0
- warp/native/cuda_util.cpp +8 -3
- warp/native/cuda_util.h +1 -0
- warp/native/exports.h +1522 -1243
- warp/native/intersect.h +19 -4
- warp/native/intersect_adj.h +8 -8
- warp/native/mat.h +76 -17
- warp/native/mesh.cpp +33 -108
- warp/native/mesh.cu +114 -18
- warp/native/mesh.h +395 -40
- warp/native/noise.h +272 -329
- warp/native/quat.h +51 -8
- warp/native/rand.h +44 -34
- warp/native/reduce.cpp +1 -1
- warp/native/sparse.cpp +4 -4
- warp/native/sparse.cu +163 -155
- warp/native/spatial.h +2 -2
- warp/native/temp_buffer.h +18 -14
- warp/native/vec.h +103 -21
- warp/native/warp.cpp +2 -1
- warp/native/warp.cu +28 -3
- warp/native/warp.h +4 -3
- warp/render/render_opengl.py +261 -109
- warp/sim/__init__.py +1 -2
- warp/sim/articulation.py +385 -185
- warp/sim/import_mjcf.py +59 -48
- warp/sim/import_urdf.py +15 -15
- warp/sim/import_usd.py +174 -102
- warp/sim/inertia.py +17 -18
- warp/sim/integrator_xpbd.py +4 -3
- warp/sim/model.py +330 -250
- warp/sim/render.py +1 -1
- warp/sparse.py +625 -152
- warp/stubs.py +341 -309
- warp/tape.py +9 -6
- warp/tests/__main__.py +3 -6
- warp/tests/assets/curlnoise_golden.npy +0 -0
- warp/tests/assets/pnoise_golden.npy +0 -0
- warp/tests/{test_class_kernel.py → aux_test_class_kernel.py} +9 -1
- warp/tests/aux_test_conditional_unequal_types_kernels.py +21 -0
- warp/tests/{test_dependent.py → aux_test_dependent.py} +2 -2
- warp/tests/{test_reference.py → aux_test_reference.py} +1 -1
- warp/tests/aux_test_unresolved_func.py +14 -0
- warp/tests/aux_test_unresolved_symbol.py +14 -0
- warp/tests/disabled_kinematics.py +239 -0
- warp/tests/run_coverage_serial.py +31 -0
- warp/tests/test_adam.py +103 -106
- warp/tests/test_arithmetic.py +94 -74
- warp/tests/test_array.py +82 -101
- warp/tests/test_array_reduce.py +57 -23
- warp/tests/test_atomic.py +64 -28
- warp/tests/test_bool.py +22 -12
- warp/tests/test_builtins_resolution.py +1292 -0
- warp/tests/test_bvh.py +18 -18
- warp/tests/test_closest_point_edge_edge.py +54 -57
- warp/tests/test_codegen.py +165 -134
- warp/tests/test_compile_consts.py +28 -20
- warp/tests/test_conditional.py +108 -24
- warp/tests/test_copy.py +10 -12
- warp/tests/test_ctypes.py +112 -88
- warp/tests/test_dense.py +21 -14
- warp/tests/test_devices.py +98 -0
- warp/tests/test_dlpack.py +75 -75
- warp/tests/test_examples.py +237 -0
- warp/tests/test_fabricarray.py +22 -24
- warp/tests/test_fast_math.py +15 -11
- warp/tests/test_fem.py +1034 -124
- warp/tests/test_fp16.py +23 -16
- warp/tests/test_func.py +187 -86
- warp/tests/test_generics.py +194 -49
- warp/tests/test_grad.py +123 -181
- warp/tests/test_grad_customs.py +176 -0
- warp/tests/test_hash_grid.py +35 -34
- warp/tests/test_import.py +10 -23
- warp/tests/test_indexedarray.py +24 -25
- warp/tests/test_intersect.py +18 -9
- warp/tests/test_large.py +141 -0
- warp/tests/test_launch.py +14 -41
- warp/tests/test_lerp.py +64 -65
- warp/tests/test_lvalue.py +493 -0
- warp/tests/test_marching_cubes.py +12 -13
- warp/tests/test_mat.py +517 -2898
- warp/tests/test_mat_lite.py +115 -0
- warp/tests/test_mat_scalar_ops.py +2889 -0
- warp/tests/test_math.py +103 -9
- warp/tests/test_matmul.py +304 -69
- warp/tests/test_matmul_lite.py +410 -0
- warp/tests/test_mesh.py +60 -22
- warp/tests/test_mesh_query_aabb.py +21 -25
- warp/tests/test_mesh_query_point.py +111 -22
- warp/tests/test_mesh_query_ray.py +12 -24
- warp/tests/test_mlp.py +30 -22
- warp/tests/test_model.py +92 -89
- warp/tests/test_modules_lite.py +39 -0
- warp/tests/test_multigpu.py +88 -114
- warp/tests/test_noise.py +12 -11
- warp/tests/test_operators.py +16 -20
- warp/tests/test_options.py +11 -11
- warp/tests/test_pinned.py +17 -18
- warp/tests/test_print.py +32 -11
- warp/tests/test_quat.py +275 -129
- warp/tests/test_rand.py +18 -16
- warp/tests/test_reload.py +38 -34
- warp/tests/test_rounding.py +50 -43
- warp/tests/test_runlength_encode.py +168 -20
- warp/tests/test_smoothstep.py +9 -11
- warp/tests/test_snippet.py +143 -0
- warp/tests/test_sparse.py +261 -63
- warp/tests/test_spatial.py +276 -243
- warp/tests/test_streams.py +110 -85
- warp/tests/test_struct.py +268 -63
- warp/tests/test_tape.py +39 -21
- warp/tests/test_torch.py +90 -86
- warp/tests/test_transient_module.py +10 -12
- warp/tests/test_types.py +363 -0
- warp/tests/test_utils.py +451 -0
- warp/tests/test_vec.py +354 -2050
- warp/tests/test_vec_lite.py +73 -0
- warp/tests/test_vec_scalar_ops.py +2099 -0
- warp/tests/test_volume.py +418 -376
- warp/tests/test_volume_write.py +124 -134
- warp/tests/unittest_serial.py +35 -0
- warp/tests/unittest_suites.py +291 -0
- warp/tests/unittest_utils.py +342 -0
- warp/tests/{test_misc.py → unused_test_misc.py} +13 -5
- warp/tests/{test_debug.py → walkthough_debug.py} +3 -17
- warp/thirdparty/appdirs.py +36 -45
- warp/thirdparty/unittest_parallel.py +589 -0
- warp/types.py +622 -211
- warp/utils.py +54 -393
- warp_lang-1.0.0b6.dist-info/METADATA +238 -0
- warp_lang-1.0.0b6.dist-info/RECORD +409 -0
- {warp_lang-1.0.0b2.dist-info → warp_lang-1.0.0b6.dist-info}/WHEEL +1 -1
- examples/example_cache_management.py +0 -40
- examples/example_multigpu.py +0 -54
- examples/example_struct.py +0 -65
- examples/fem/example_stokes_transfer_3d.py +0 -210
- warp/bin/warp-clang.so +0 -0
- warp/bin/warp.so +0 -0
- warp/fem/field/discrete_field.py +0 -80
- warp/fem/space/nodal_function_space.py +0 -233
- warp/tests/test_all.py +0 -223
- warp/tests/test_array_scan.py +0 -60
- warp/tests/test_base.py +0 -208
- warp/tests/test_unresolved_func.py +0 -7
- warp/tests/test_unresolved_symbol.py +0 -7
- warp_lang-1.0.0b2.dist-info/METADATA +0 -26
- warp_lang-1.0.0b2.dist-info/RECORD +0 -380
- /warp/tests/{test_compile_consts_dummy.py → aux_test_compile_consts_dummy.py} +0 -0
- /warp/tests/{test_reference_reference.py → aux_test_reference_reference.py} +0 -0
- /warp/tests/{test_square.py → aux_test_square.py} +0 -0
- {warp_lang-1.0.0b2.dist-info → warp_lang-1.0.0b6.dist-info}/LICENSE.md +0 -0
- {warp_lang-1.0.0b2.dist-info → warp_lang-1.0.0b6.dist-info}/top_level.txt +0 -0
|
@@ -1,487 +1,147 @@
|
|
|
1
1
|
import warp as wp
|
|
2
2
|
import numpy as np
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
from warp.fem.
|
|
6
|
-
from warp.fem.types import vec2i
|
|
7
|
-
from warp.fem.polynomial import Polynomial, lagrange_scales, quadrature_1d, is_closed
|
|
4
|
+
from warp.fem.types import ElementIndex, Coords
|
|
5
|
+
from warp.fem.polynomial import Polynomial, is_closed
|
|
8
6
|
from warp.fem.geometry import Grid2D
|
|
7
|
+
from warp.fem import cache
|
|
9
8
|
|
|
10
|
-
from .
|
|
11
|
-
from .
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class Grid2DFunctionSpace(NodalFunctionSpace):
|
|
15
|
-
DIMENSION = wp.constant(2)
|
|
16
|
-
|
|
17
|
-
@wp.struct
|
|
18
|
-
class SpaceArg:
|
|
19
|
-
geo_arg: Grid2D.SideArg
|
|
20
|
-
inv_cell_size: wp.vec2
|
|
21
|
-
|
|
22
|
-
def __init__(self, grid: Grid2D, dtype: type = float, dof_mapper: DofMapper = None):
|
|
23
|
-
super().__init__(dtype, dof_mapper)
|
|
24
|
-
self._grid = grid
|
|
25
|
-
|
|
26
|
-
@property
|
|
27
|
-
def geometry(self) -> Grid2D:
|
|
28
|
-
return self._grid
|
|
29
|
-
|
|
30
|
-
def space_arg_value(self, device):
|
|
31
|
-
arg = self.SpaceArg()
|
|
32
|
-
arg.geo_arg = self.geometry.side_arg_value(device)
|
|
33
|
-
arg.inv_cell_size = wp.vec2(
|
|
34
|
-
1.0 / self.geometry.cell_size[0],
|
|
35
|
-
1.0 / self.geometry.cell_size[1],
|
|
36
|
-
)
|
|
37
|
-
|
|
38
|
-
return arg
|
|
9
|
+
from .topology import SpaceTopology, DiscontinuousSpaceTopologyMixin, forward_base_topology
|
|
10
|
+
from .basis_space import ShapeBasisSpace, TraceBasisSpace
|
|
39
11
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
12
|
+
from .shape import ShapeFunction, ConstantShapeFunction
|
|
13
|
+
from .shape import (
|
|
14
|
+
SquareBipolynomialShapeFunctions,
|
|
15
|
+
SquareSerendipityShapeFunctions,
|
|
16
|
+
SquareNonConformingPolynomialShapeFunctions,
|
|
17
|
+
)
|
|
44
18
|
|
|
45
|
-
@wp.func
|
|
46
|
-
def _inner_cell_index(args: SpaceArg, side_index: ElementIndex):
|
|
47
|
-
return Grid2D.side_inner_cell_index(args.geo_arg, side_index)
|
|
48
19
|
|
|
49
|
-
|
|
50
|
-
def
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
@wp.func
|
|
54
|
-
def _inner_cell_coords(args: SpaceArg, side_index: ElementIndex, side_coords: Coords):
|
|
55
|
-
side = Grid2D.get_side(args.geo_arg, side_index)
|
|
56
|
-
|
|
57
|
-
if side.origin[0] == 0:
|
|
58
|
-
inner_alt = 0.0
|
|
59
|
-
else:
|
|
60
|
-
inner_alt = 1.0
|
|
61
|
-
|
|
62
|
-
coords = Grid2D._rotate(side.axis, wp.vec2(inner_alt, side_coords[0]))
|
|
63
|
-
return Coords(coords[0], coords[1], 0.0)
|
|
64
|
-
|
|
65
|
-
@wp.func
|
|
66
|
-
def _outer_cell_coords(args: SpaceArg, side_index: ElementIndex, side_coords: Coords):
|
|
67
|
-
side = Grid2D.get_side(args.geo_arg, side_index)
|
|
68
|
-
|
|
69
|
-
alt_axis = Grid2D.ROTATION[side.axis, 0]
|
|
70
|
-
if side.origin[0] == args.geo_arg.cell_arg.res[alt_axis]:
|
|
71
|
-
outer_alt = 1.0
|
|
72
|
-
else:
|
|
73
|
-
outer_alt = 0.0
|
|
74
|
-
|
|
75
|
-
coords = Grid2D._rotate(side.axis, wp.vec2(outer_alt, side_coords[0]))
|
|
76
|
-
return Coords(coords[0], coords[1], 0.0)
|
|
77
|
-
|
|
78
|
-
@wp.func
|
|
79
|
-
def _cell_to_side_coords(
|
|
80
|
-
args: SpaceArg,
|
|
81
|
-
side_index: ElementIndex,
|
|
82
|
-
element_index: ElementIndex,
|
|
83
|
-
element_coords: Coords,
|
|
84
|
-
):
|
|
85
|
-
side = Grid2D.get_side(args.geo_arg, side_index)
|
|
86
|
-
cell = Grid2D.get_cell(args.geo_arg.cell_arg.res, element_index)
|
|
87
|
-
|
|
88
|
-
if float(side.origin[0] - cell[side.axis]) == element_coords[side.axis]:
|
|
89
|
-
long_axis = Grid2D.ROTATION[side.axis, 1]
|
|
90
|
-
return Coords(element_coords[long_axis], 0.0, 0.0)
|
|
91
|
-
|
|
92
|
-
return Coords(OUTSIDE)
|
|
20
|
+
class Grid2DSpaceTopology(SpaceTopology):
|
|
21
|
+
def __init__(self, grid: Grid2D, shape: ShapeFunction):
|
|
22
|
+
super().__init__(grid, shape.NODES_PER_ELEMENT)
|
|
23
|
+
self._shape = shape
|
|
93
24
|
|
|
94
25
|
@wp.func
|
|
95
26
|
def _vertex_coords(vidx_in_cell: int):
|
|
96
27
|
x = vidx_in_cell // 2
|
|
97
28
|
y = vidx_in_cell - 2 * x
|
|
98
|
-
return vec2i(x, y)
|
|
29
|
+
return wp.vec2i(x, y)
|
|
99
30
|
|
|
100
31
|
@wp.func
|
|
101
|
-
def
|
|
102
|
-
|
|
103
|
-
y = vidx_in_cell - 2 * x
|
|
104
|
-
return wp.vec2(float(x), float(y))
|
|
105
|
-
|
|
106
|
-
@wp.func
|
|
107
|
-
def _vertex_index(args: SpaceArg, cell_index: ElementIndex, vidx_in_cell: int):
|
|
108
|
-
res = args.geo_arg.cell_arg.res
|
|
32
|
+
def _vertex_index(cell_arg: Grid2D.CellArg, cell_index: ElementIndex, vidx_in_cell: int):
|
|
33
|
+
res = cell_arg.res
|
|
109
34
|
x_stride = res[1] + 1
|
|
110
35
|
|
|
111
|
-
corner = Grid2D.get_cell(res, cell_index) +
|
|
36
|
+
corner = Grid2D.get_cell(res, cell_index) + Grid2DSpaceTopology._vertex_coords(vidx_in_cell)
|
|
112
37
|
return Grid2D._from_2d_index(x_stride, corner)
|
|
113
38
|
|
|
114
39
|
|
|
115
|
-
class
|
|
116
|
-
|
|
117
|
-
|
|
40
|
+
class Grid2DDiscontinuousSpaceTopology(
|
|
41
|
+
DiscontinuousSpaceTopologyMixin,
|
|
42
|
+
Grid2DSpaceTopology,
|
|
43
|
+
):
|
|
44
|
+
pass
|
|
118
45
|
|
|
119
|
-
def __init__(self, grid: Grid2D, dtype: type = float, dof_mapper: DofMapper = None):
|
|
120
|
-
super().__init__(grid, dtype, dof_mapper)
|
|
121
46
|
|
|
122
|
-
|
|
123
|
-
|
|
47
|
+
class Grid2DBasisSpace(ShapeBasisSpace):
|
|
48
|
+
def __init__(self, topology: Grid2DSpaceTopology, shape: ShapeFunction):
|
|
49
|
+
super().__init__(topology, shape)
|
|
124
50
|
|
|
125
|
-
|
|
126
|
-
|
|
51
|
+
self._grid: Grid2D = topology.geometry
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class GridPiecewiseConstantBasis(Grid2DBasisSpace):
|
|
55
|
+
def __init__(self, grid: Grid2D):
|
|
56
|
+
shape = ConstantShapeFunction(grid.reference_cell(), space_dimension=2)
|
|
57
|
+
topology = Grid2DDiscontinuousSpaceTopology(grid, shape)
|
|
58
|
+
super().__init__(shape=shape, topology=topology)
|
|
127
59
|
|
|
128
|
-
|
|
60
|
+
if isinstance(grid, Grid2D):
|
|
61
|
+
self.node_grid = self._node_grid
|
|
62
|
+
|
|
63
|
+
def _node_grid(self):
|
|
129
64
|
res = self._grid.res
|
|
130
65
|
|
|
131
66
|
X = (np.arange(0, res[0], dtype=float) + 0.5) * self._grid.cell_size[0] + self._grid.origin[0]
|
|
132
67
|
Y = (np.arange(0, res[1], dtype=float) + 0.5) * self._grid.cell_size[1] + self._grid.origin[1]
|
|
133
68
|
return np.meshgrid(X, Y, indexing="ij")
|
|
134
69
|
|
|
135
|
-
|
|
136
|
-
def element_node_index(
|
|
137
|
-
args: Grid2DFunctionSpace.SpaceArg,
|
|
138
|
-
element_index: ElementIndex,
|
|
139
|
-
node_index_in_elt: int,
|
|
140
|
-
):
|
|
141
|
-
return element_index
|
|
142
|
-
|
|
143
|
-
@wp.func
|
|
144
|
-
def node_coords_in_element(
|
|
145
|
-
args: Grid2DFunctionSpace.SpaceArg,
|
|
146
|
-
element_index: ElementIndex,
|
|
147
|
-
node_index_in_elt: int,
|
|
148
|
-
):
|
|
149
|
-
if node_index_in_elt == 0:
|
|
150
|
-
return Coords(0.5, 0.5, 0.0)
|
|
151
|
-
|
|
152
|
-
return Coords(OUTSIDE)
|
|
153
|
-
|
|
154
|
-
@wp.func
|
|
155
|
-
def node_quadrature_weight(
|
|
156
|
-
args: Grid2DFunctionSpace.SpaceArg,
|
|
157
|
-
element_index: ElementIndex,
|
|
158
|
-
node_index_in_elt: int,
|
|
159
|
-
):
|
|
160
|
-
return 1.0
|
|
161
|
-
|
|
162
|
-
@wp.func
|
|
163
|
-
def element_inner_weight(
|
|
164
|
-
args: Grid2DFunctionSpace.SpaceArg,
|
|
165
|
-
element_index: ElementIndex,
|
|
166
|
-
coords: Coords,
|
|
167
|
-
node_index_in_elt: int,
|
|
168
|
-
):
|
|
169
|
-
if node_index_in_elt == 0:
|
|
170
|
-
return 1.0
|
|
171
|
-
return 0.0
|
|
172
|
-
|
|
173
|
-
@wp.func
|
|
174
|
-
def element_inner_weight_gradient(
|
|
175
|
-
args: Grid2DFunctionSpace.SpaceArg,
|
|
176
|
-
element_index: ElementIndex,
|
|
177
|
-
coords: Coords,
|
|
178
|
-
node_index_in_elt: int,
|
|
179
|
-
):
|
|
180
|
-
return wp.vec2(0.0)
|
|
181
|
-
|
|
182
|
-
class Trace(Grid2DFunctionSpace.Trace):
|
|
183
|
-
NODES_PER_ELEMENT = wp.constant(2)
|
|
184
|
-
ORDER = wp.constant(0)
|
|
185
|
-
|
|
186
|
-
def __init__(self, space: "GridPiecewiseConstantSpace"):
|
|
187
|
-
super().__init__(space)
|
|
188
|
-
|
|
189
|
-
self.element_node_index = self._make_element_node_index(space)
|
|
190
|
-
|
|
191
|
-
self.element_inner_weight = self._make_element_inner_weight(space)
|
|
192
|
-
self.element_inner_weight_gradient = self._make_element_inner_weight_gradient(space)
|
|
193
|
-
|
|
194
|
-
self.element_outer_weight = self._make_element_outer_weight(space)
|
|
195
|
-
self.element_outer_weight_gradient = self._make_element_outer_weight_gradient(space)
|
|
196
|
-
|
|
70
|
+
class Trace(TraceBasisSpace):
|
|
197
71
|
@wp.func
|
|
198
|
-
def
|
|
199
|
-
|
|
72
|
+
def _node_coords_in_element(
|
|
73
|
+
side_arg: Grid2D.SideArg,
|
|
74
|
+
basis_arg: Grid2DBasisSpace.BasisArg,
|
|
200
75
|
element_index: ElementIndex,
|
|
201
76
|
node_index_in_element: int,
|
|
202
77
|
):
|
|
203
|
-
|
|
204
|
-
return Coords(0.5, 0.0, 0.0)
|
|
205
|
-
elif node_index_in_element == 1:
|
|
206
|
-
return Coords(0.5, 0.0, 0.0)
|
|
78
|
+
return Coords(0.5, 0.0, 0.0)
|
|
207
79
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
@wp.func
|
|
211
|
-
def node_quadrature_weight(
|
|
212
|
-
args: Grid2DFunctionSpace.SpaceArg,
|
|
213
|
-
element_index: ElementIndex,
|
|
214
|
-
node_index_in_elt: int,
|
|
215
|
-
):
|
|
216
|
-
return 1.0
|
|
80
|
+
def make_node_coords_in_element(self):
|
|
81
|
+
return self._node_coords_in_element
|
|
217
82
|
|
|
218
83
|
def trace(self):
|
|
219
|
-
return
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
class GridBipolynomialShapeFunctions:
|
|
223
|
-
def __init__(self, degree: int, family: Polynomial):
|
|
224
|
-
self.family = family
|
|
225
|
-
|
|
226
|
-
self.ORDER = wp.constant(degree)
|
|
227
|
-
self.NODES_PER_ELEMENT = wp.constant((degree + 1) * (degree + 1))
|
|
228
|
-
self.NODES_PER_SIDE = wp.constant(degree + 1)
|
|
229
|
-
|
|
230
|
-
lobatto_coords, lobatto_weight = quadrature_1d(point_count=degree + 1, family=family)
|
|
231
|
-
lagrange_scale = lagrange_scales(lobatto_coords)
|
|
232
|
-
|
|
233
|
-
NodeVec = wp.types.vector(length=degree + 1, dtype=wp.float32)
|
|
234
|
-
self.LOBATTO_COORDS = wp.constant(NodeVec(lobatto_coords))
|
|
235
|
-
self.LOBATTO_WEIGHT = wp.constant(NodeVec(lobatto_weight))
|
|
236
|
-
self.LAGRANGE_SCALE = wp.constant(NodeVec(lagrange_scale))
|
|
237
|
-
|
|
238
|
-
@property
|
|
239
|
-
def name(self) -> str:
|
|
240
|
-
return f"{self.family}_{self.ORDER}"
|
|
241
|
-
|
|
242
|
-
def make_node_coords_in_element(self):
|
|
243
|
-
ORDER = self.ORDER
|
|
244
|
-
LOBATTO_COORDS = self.LOBATTO_COORDS
|
|
245
|
-
|
|
246
|
-
def node_coords_in_element(
|
|
247
|
-
args: Grid2DFunctionSpace.SpaceArg,
|
|
248
|
-
element_index: ElementIndex,
|
|
249
|
-
node_index_in_elt: int,
|
|
250
|
-
):
|
|
251
|
-
node_i = node_index_in_elt // (ORDER + 1)
|
|
252
|
-
node_j = node_index_in_elt - (ORDER + 1) * node_i
|
|
253
|
-
return Coords(LOBATTO_COORDS[node_i], LOBATTO_COORDS[node_j], 0.0)
|
|
254
|
-
|
|
255
|
-
from warp.fem import cache
|
|
256
|
-
|
|
257
|
-
return cache.get_func(node_coords_in_element, self.name)
|
|
258
|
-
|
|
259
|
-
def make_node_quadrature_weight(self):
|
|
260
|
-
ORDER = self.ORDER
|
|
261
|
-
LOBATTO_WEIGHT = self.LOBATTO_WEIGHT
|
|
262
|
-
|
|
263
|
-
def node_quadrature_weight(
|
|
264
|
-
args: Grid2DFunctionSpace.SpaceArg,
|
|
265
|
-
element_index: ElementIndex,
|
|
266
|
-
node_index_in_elt: int,
|
|
267
|
-
):
|
|
268
|
-
node_i = node_index_in_elt // (ORDER + 1)
|
|
269
|
-
node_j = node_index_in_elt - (ORDER + 1) * node_i
|
|
270
|
-
return LOBATTO_WEIGHT[node_i] * LOBATTO_WEIGHT[node_j]
|
|
271
|
-
|
|
272
|
-
def node_quadrature_weight_linear(
|
|
273
|
-
args: Grid2DFunctionSpace.SpaceArg,
|
|
274
|
-
element_index: ElementIndex,
|
|
275
|
-
node_index_in_elt: int,
|
|
276
|
-
):
|
|
277
|
-
return 0.25
|
|
278
|
-
|
|
279
|
-
from warp.fem import cache
|
|
280
|
-
|
|
281
|
-
if ORDER == 1:
|
|
282
|
-
return cache.get_func(node_quadrature_weight_linear, self.name)
|
|
283
|
-
|
|
284
|
-
return cache.get_func(node_quadrature_weight, self.name)
|
|
285
|
-
|
|
286
|
-
def make_trace_node_quadrature_weight(self):
|
|
287
|
-
ORDER = self.ORDER
|
|
288
|
-
NODES_PER_ELEMENT = self.NODES_PER_ELEMENT
|
|
289
|
-
LOBATTO_WEIGHT = self.LOBATTO_WEIGHT
|
|
290
|
-
|
|
291
|
-
def trace_node_quadrature_weight(
|
|
292
|
-
args: Grid2DFunctionSpace.SpaceArg,
|
|
293
|
-
element_index: ElementIndex,
|
|
294
|
-
node_index_in_elt: int,
|
|
295
|
-
):
|
|
296
|
-
if node_index_in_elt >= NODES_PER_ELEMENT:
|
|
297
|
-
node_index_in_cell = node_index_in_elt - NODES_PER_ELEMENT
|
|
298
|
-
else:
|
|
299
|
-
node_index_in_cell = node_index_in_elt
|
|
300
|
-
|
|
301
|
-
# We're either on a side interior or at a vertex
|
|
302
|
-
# I.e., either both indices are at extrema, or only one is
|
|
303
|
-
# Pick the interior one if possible, if both are at extrema pick any one
|
|
304
|
-
node_i = node_index_in_cell // (ORDER + 1)
|
|
305
|
-
if node_i > 0 and node_i < ORDER:
|
|
306
|
-
return LOBATTO_WEIGHT[node_i]
|
|
307
|
-
|
|
308
|
-
node_j = node_index_in_cell - (ORDER + 1) * node_i
|
|
309
|
-
return LOBATTO_WEIGHT[node_j]
|
|
310
|
-
|
|
311
|
-
def trace_node_quadrature_weight_linear(
|
|
312
|
-
args: Grid2DFunctionSpace.SpaceArg,
|
|
313
|
-
element_index: ElementIndex,
|
|
314
|
-
node_index_in_elt: int,
|
|
315
|
-
):
|
|
316
|
-
return 0.5
|
|
317
|
-
|
|
318
|
-
from warp.fem import cache
|
|
319
|
-
|
|
320
|
-
if ORDER == 1:
|
|
321
|
-
return cache.get_func(trace_node_quadrature_weight_linear, self.name)
|
|
322
|
-
|
|
323
|
-
return cache.get_func(trace_node_quadrature_weight, self.name)
|
|
324
|
-
|
|
325
|
-
def make_element_inner_weight(self):
|
|
326
|
-
ORDER = self.ORDER
|
|
327
|
-
NODES_PER_ELEMENT = self.NODES_PER_ELEMENT
|
|
328
|
-
LOBATTO_COORDS = self.LOBATTO_COORDS
|
|
329
|
-
LAGRANGE_SCALE = self.LAGRANGE_SCALE
|
|
84
|
+
return GridPiecewiseConstantBasis.Trace(self)
|
|
330
85
|
|
|
331
|
-
def element_inner_weight(
|
|
332
|
-
args: Grid2DFunctionSpace.SpaceArg,
|
|
333
|
-
element_index: ElementIndex,
|
|
334
|
-
coords: Coords,
|
|
335
|
-
node_index_in_elt: int,
|
|
336
|
-
):
|
|
337
|
-
if node_index_in_elt < 0 or node_index_in_elt >= NODES_PER_ELEMENT:
|
|
338
|
-
return 0.0
|
|
339
|
-
|
|
340
|
-
node_i = node_index_in_elt // (ORDER + 1)
|
|
341
|
-
node_j = node_index_in_elt - (ORDER + 1) * node_i
|
|
342
86
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
w *= coords[0] - LOBATTO_COORDS[k]
|
|
347
|
-
if k != node_j:
|
|
348
|
-
w *= coords[1] - LOBATTO_COORDS[k]
|
|
87
|
+
class GridBipolynomialSpaceTopology(Grid2DSpaceTopology):
|
|
88
|
+
def __init__(self, grid: Grid2D, shape: SquareBipolynomialShapeFunctions):
|
|
89
|
+
super().__init__(grid, shape)
|
|
349
90
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
return w
|
|
353
|
-
|
|
354
|
-
def element_inner_weight_linear(
|
|
355
|
-
args: Grid2DFunctionSpace.SpaceArg,
|
|
356
|
-
element_index: ElementIndex,
|
|
357
|
-
coords: Coords,
|
|
358
|
-
node_index_in_elt: int,
|
|
359
|
-
):
|
|
360
|
-
if node_index_in_elt < 0 or node_index_in_elt >= 4:
|
|
361
|
-
return 0.0
|
|
362
|
-
|
|
363
|
-
v = Grid2DFunctionSpace._vertex_coords_f(node_index_in_elt)
|
|
364
|
-
|
|
365
|
-
wx = (1.0 - coords[0]) * (1.0 - v[0]) + v[0] * coords[0]
|
|
366
|
-
wy = (1.0 - coords[1]) * (1.0 - v[1]) + v[1] * coords[1]
|
|
367
|
-
return wx * wy
|
|
368
|
-
|
|
369
|
-
from warp.fem import cache
|
|
370
|
-
|
|
371
|
-
if ORDER == 1:
|
|
372
|
-
return cache.get_func(element_inner_weight_linear, self.name)
|
|
91
|
+
self.element_node_index = self._make_element_node_index()
|
|
373
92
|
|
|
374
|
-
|
|
93
|
+
def node_count(self) -> int:
|
|
94
|
+
return (self.geometry.res[0] * self._shape.ORDER + 1) * (self.geometry.res[1] * self._shape.ORDER + 1)
|
|
375
95
|
|
|
376
|
-
def
|
|
377
|
-
ORDER = self.ORDER
|
|
378
|
-
NODES_PER_ELEMENT = self.NODES_PER_ELEMENT
|
|
379
|
-
LOBATTO_COORDS = self.LOBATTO_COORDS
|
|
380
|
-
LAGRANGE_SCALE = self.LAGRANGE_SCALE
|
|
96
|
+
def _make_element_node_index(self):
|
|
97
|
+
ORDER = self._shape.ORDER
|
|
381
98
|
|
|
382
|
-
|
|
383
|
-
|
|
99
|
+
@cache.dynamic_func(suffix=self.name)
|
|
100
|
+
def element_node_index(
|
|
101
|
+
cell_arg: Grid2D.CellArg,
|
|
102
|
+
topo_arg: Grid2DSpaceTopology.TopologyArg,
|
|
384
103
|
element_index: ElementIndex,
|
|
385
|
-
coords: Coords,
|
|
386
104
|
node_index_in_elt: int,
|
|
387
105
|
):
|
|
388
|
-
|
|
389
|
-
|
|
106
|
+
res = cell_arg.res
|
|
107
|
+
cell = Grid2D.get_cell(res, element_index)
|
|
390
108
|
|
|
391
109
|
node_i = node_index_in_elt // (ORDER + 1)
|
|
392
110
|
node_j = node_index_in_elt - (ORDER + 1) * node_i
|
|
393
111
|
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
for k in range(ORDER + 1):
|
|
397
|
-
if k != node_i:
|
|
398
|
-
prefix_y *= coords[0] - LOBATTO_COORDS[k]
|
|
399
|
-
if k != node_j:
|
|
400
|
-
prefix_x *= coords[1] - LOBATTO_COORDS[k]
|
|
401
|
-
|
|
402
|
-
grad_x = float(0.0)
|
|
403
|
-
grad_y = float(0.0)
|
|
404
|
-
|
|
405
|
-
for k in range(ORDER + 1):
|
|
406
|
-
if k != node_i:
|
|
407
|
-
delta_x = coords[0] - LOBATTO_COORDS[k]
|
|
408
|
-
grad_x = grad_x * delta_x + prefix_x
|
|
409
|
-
prefix_x *= delta_x
|
|
410
|
-
if k != node_j:
|
|
411
|
-
delta_y = coords[1] - LOBATTO_COORDS[k]
|
|
412
|
-
grad_y = grad_y * delta_y + prefix_y
|
|
413
|
-
prefix_y *= delta_y
|
|
414
|
-
|
|
415
|
-
grad = (
|
|
416
|
-
LAGRANGE_SCALE[node_i]
|
|
417
|
-
* LAGRANGE_SCALE[node_j]
|
|
418
|
-
* wp.vec2(grad_x * args.inv_cell_size[0], grad_y * args.inv_cell_size[1])
|
|
419
|
-
)
|
|
420
|
-
|
|
421
|
-
return grad
|
|
422
|
-
|
|
423
|
-
def element_inner_weight_gradient_linear(
|
|
424
|
-
args: Grid2DFunctionSpace.SpaceArg,
|
|
425
|
-
element_index: ElementIndex,
|
|
426
|
-
coords: Coords,
|
|
427
|
-
node_index_in_elt: int,
|
|
428
|
-
):
|
|
429
|
-
if node_index_in_elt < 0 or node_index_in_elt >= 4:
|
|
430
|
-
return wp.vec2(0.0)
|
|
431
|
-
|
|
432
|
-
v = Grid2DFunctionSpace._vertex_coords_f(node_index_in_elt)
|
|
433
|
-
|
|
434
|
-
wx = (1.0 - coords[0]) * (1.0 - v[0]) + v[0] * coords[0]
|
|
435
|
-
wy = (1.0 - coords[1]) * (1.0 - v[1]) + v[1] * coords[1]
|
|
436
|
-
|
|
437
|
-
dx = (2.0 * v[0] - 1.0) * args.inv_cell_size[0]
|
|
438
|
-
dy = (2.0 * v[1] - 1.0) * args.inv_cell_size[1]
|
|
439
|
-
|
|
440
|
-
return wp.vec2(dx * wy, dy * wx)
|
|
112
|
+
node_x = ORDER * cell[0] + node_i
|
|
113
|
+
node_y = ORDER * cell[1] + node_j
|
|
441
114
|
|
|
442
|
-
|
|
115
|
+
node_pitch = (res[1] * ORDER) + 1
|
|
116
|
+
node_index = node_pitch * node_x + node_y
|
|
443
117
|
|
|
444
|
-
|
|
445
|
-
return cache.get_func(element_inner_weight_gradient_linear, self.name)
|
|
118
|
+
return node_index
|
|
446
119
|
|
|
447
|
-
return
|
|
120
|
+
return element_node_index
|
|
448
121
|
|
|
449
122
|
|
|
450
|
-
class
|
|
123
|
+
class GridBipolynomialBasisSpace(Grid2DBasisSpace):
|
|
451
124
|
def __init__(
|
|
452
125
|
self,
|
|
453
126
|
grid: Grid2D,
|
|
454
127
|
degree: int,
|
|
455
|
-
family:
|
|
456
|
-
dtype: type = float,
|
|
457
|
-
dof_mapper: DofMapper = None,
|
|
128
|
+
family: Polynomial,
|
|
458
129
|
):
|
|
459
|
-
super().__init__(grid, dtype, dof_mapper)
|
|
460
|
-
|
|
461
130
|
if family is None:
|
|
462
131
|
family = Polynomial.LOBATTO_GAUSS_LEGENDRE
|
|
463
132
|
|
|
464
133
|
if not is_closed(family):
|
|
465
|
-
raise ValueError("A closed polynomial family is required to
|
|
134
|
+
raise ValueError("A closed polynomial family is required to define a continuous function space")
|
|
466
135
|
|
|
467
|
-
|
|
136
|
+
shape = SquareBipolynomialShapeFunctions(degree, family=family)
|
|
137
|
+
topology = forward_base_topology(GridBipolynomialSpaceTopology, grid, shape)
|
|
468
138
|
|
|
469
|
-
|
|
470
|
-
self.NODES_PER_ELEMENT = self._shape.NODES_PER_ELEMENT
|
|
471
|
-
|
|
472
|
-
self.element_node_index = self._make_element_node_index()
|
|
473
|
-
self.node_coords_in_element = self._shape.make_node_coords_in_element()
|
|
474
|
-
self.node_quadrature_weight = self._shape.make_node_quadrature_weight()
|
|
475
|
-
self.element_inner_weight = self._shape.make_element_inner_weight()
|
|
476
|
-
self.element_inner_weight_gradient = self._shape.make_element_inner_weight_gradient()
|
|
139
|
+
super().__init__(topology, shape)
|
|
477
140
|
|
|
478
|
-
|
|
479
|
-
|
|
141
|
+
if isinstance(grid, Grid2D):
|
|
142
|
+
self.node_grid = self._node_grid
|
|
480
143
|
|
|
481
|
-
def
|
|
482
|
-
return (self._grid.res[0] * self.ORDER + 1) * (self._grid.res[1] * self.ORDER + 1)
|
|
483
|
-
|
|
484
|
-
def node_positions(self):
|
|
144
|
+
def _node_grid(self):
|
|
485
145
|
res = self._grid.res
|
|
486
146
|
|
|
487
147
|
cell_coords = np.array(self._shape.LOBATTO_COORDS)[:-1]
|
|
@@ -500,115 +160,108 @@ class GridBipolynomialSpace(Grid2DFunctionSpace):
|
|
|
500
160
|
|
|
501
161
|
return np.meshgrid(X, Y, indexing="ij")
|
|
502
162
|
|
|
163
|
+
|
|
164
|
+
class GridDGBipolynomialBasisSpace(Grid2DBasisSpace):
|
|
165
|
+
def __init__(
|
|
166
|
+
self,
|
|
167
|
+
grid: Grid2D,
|
|
168
|
+
degree: int,
|
|
169
|
+
family: Polynomial,
|
|
170
|
+
):
|
|
171
|
+
if family is None:
|
|
172
|
+
family = Polynomial.LOBATTO_GAUSS_LEGENDRE
|
|
173
|
+
|
|
174
|
+
shape = SquareBipolynomialShapeFunctions(degree, family=family)
|
|
175
|
+
topology = Grid2DDiscontinuousSpaceTopology(grid, shape)
|
|
176
|
+
|
|
177
|
+
super().__init__(shape=shape, topology=topology)
|
|
178
|
+
|
|
179
|
+
|
|
180
|
+
class GridSerendipitySpaceTopology(Grid2DSpaceTopology):
|
|
181
|
+
def __init__(self, grid: Grid2D, shape: SquareSerendipityShapeFunctions):
|
|
182
|
+
super().__init__(grid, shape)
|
|
183
|
+
|
|
184
|
+
self.element_node_index = self._make_element_node_index()
|
|
185
|
+
|
|
186
|
+
TopologyArg = Grid2D.SideArg
|
|
187
|
+
|
|
188
|
+
def topo_arg_value(self, device):
|
|
189
|
+
return self.geometry.side_arg_value(device)
|
|
190
|
+
|
|
191
|
+
def node_count(self) -> int:
|
|
192
|
+
return self.geometry.vertex_count() + (self._shape.ORDER - 1) * self.geometry.side_count()
|
|
193
|
+
|
|
503
194
|
def _make_element_node_index(self):
|
|
504
|
-
ORDER = self.ORDER
|
|
195
|
+
ORDER = self._shape.ORDER
|
|
505
196
|
|
|
197
|
+
@cache.dynamic_func(suffix=self.name)
|
|
506
198
|
def element_node_index(
|
|
507
|
-
|
|
199
|
+
cell_arg: Grid2D.CellArg,
|
|
200
|
+
topo_arg: Grid2D.SideArg,
|
|
508
201
|
element_index: ElementIndex,
|
|
509
202
|
node_index_in_elt: int,
|
|
510
203
|
):
|
|
511
|
-
|
|
512
|
-
cell = Grid2D.get_cell(res, element_index)
|
|
204
|
+
node_type, type_index = self._shape.node_type_and_type_index(node_index_in_elt)
|
|
513
205
|
|
|
514
|
-
|
|
515
|
-
|
|
206
|
+
if node_type == SquareSerendipityShapeFunctions.VERTEX:
|
|
207
|
+
return Grid2DSpaceTopology._vertex_index(cell_arg, element_index, type_index)
|
|
516
208
|
|
|
517
|
-
|
|
518
|
-
|
|
209
|
+
side_offset, index_in_side = SquareSerendipityShapeFunctions.side_offset_and_index(type_index)
|
|
210
|
+
axis = 1 - (node_type - SquareSerendipityShapeFunctions.EDGE_X)
|
|
519
211
|
|
|
520
|
-
|
|
521
|
-
|
|
212
|
+
cell = Grid2D.get_cell(cell_arg.res, element_index)
|
|
213
|
+
origin = wp.vec2i(cell[Grid2D.ROTATION[axis, 0]] + side_offset, cell[Grid2D.ROTATION[axis, 1]])
|
|
522
214
|
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
from warp.fem import cache
|
|
526
|
-
|
|
527
|
-
return cache.get_func(element_node_index, f"{self.name}_{ORDER}")
|
|
215
|
+
side = Grid2D.Side(axis, origin)
|
|
216
|
+
side_index = Grid2D.side_index(topo_arg, side)
|
|
528
217
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
super().__init__(space)
|
|
218
|
+
res = cell_arg.res
|
|
219
|
+
vertex_count = (res[0] + 1) * (res[1] + 1)
|
|
532
220
|
|
|
533
|
-
|
|
534
|
-
self.node_coords_in_element = self._make_node_coords_in_element(space)
|
|
535
|
-
self.node_quadrature_weight = space._shape.make_trace_node_quadrature_weight()
|
|
221
|
+
return vertex_count + (ORDER - 1) * side_index + index_in_side
|
|
536
222
|
|
|
537
|
-
|
|
538
|
-
self.element_inner_weight_gradient = self._make_element_inner_weight_gradient(space)
|
|
539
|
-
|
|
540
|
-
self.element_outer_weight = self._make_element_outer_weight(space)
|
|
541
|
-
self.element_outer_weight_gradient = self._make_element_outer_weight_gradient(space)
|
|
542
|
-
|
|
543
|
-
def trace(self):
|
|
544
|
-
return GridBipolynomialSpace.Trace(self)
|
|
223
|
+
return element_node_index
|
|
545
224
|
|
|
546
225
|
|
|
547
|
-
class
|
|
226
|
+
class GridSerendipityBasisSpace(Grid2DBasisSpace):
|
|
548
227
|
def __init__(
|
|
549
228
|
self,
|
|
550
229
|
grid: Grid2D,
|
|
551
230
|
degree: int,
|
|
552
231
|
family: Polynomial,
|
|
553
|
-
dtype: type = float,
|
|
554
|
-
dof_mapper: DofMapper = None,
|
|
555
232
|
):
|
|
556
|
-
super().__init__(grid, dtype, dof_mapper)
|
|
557
|
-
|
|
558
233
|
if family is None:
|
|
559
234
|
family = Polynomial.LOBATTO_GAUSS_LEGENDRE
|
|
560
235
|
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
self.ORDER = self._shape.ORDER
|
|
564
|
-
self.NODES_PER_ELEMENT = self._shape.NODES_PER_ELEMENT
|
|
565
|
-
|
|
566
|
-
self.element_node_index = self._make_element_node_index()
|
|
567
|
-
self.node_coords_in_element = self._shape.make_node_coords_in_element()
|
|
568
|
-
self.node_quadrature_weight = self._shape.make_node_quadrature_weight()
|
|
569
|
-
self.element_inner_weight = self._shape.make_element_inner_weight()
|
|
570
|
-
self.element_inner_weight_gradient = self._shape.make_element_inner_weight_gradient()
|
|
571
|
-
|
|
572
|
-
self.element_outer_weight = self.element_inner_weight
|
|
573
|
-
self.element_outer_weight_gradient = self.element_inner_weight_gradient
|
|
574
|
-
|
|
575
|
-
def node_count(self) -> int:
|
|
576
|
-
return self._grid.cell_count() * (self.ORDER + 1) ** 2
|
|
577
|
-
|
|
578
|
-
def node_positions(self):
|
|
579
|
-
res = self._grid.res
|
|
580
|
-
|
|
581
|
-
cell_coords = np.array(self._shape.LOBATTO_COORDS)
|
|
582
|
-
|
|
583
|
-
grid_coords_x = np.repeat(np.arange(0, res[0], dtype=float), len(cell_coords)) + np.tile(
|
|
584
|
-
cell_coords, reps=res[0]
|
|
585
|
-
)
|
|
586
|
-
X = grid_coords_x * self._grid.cell_size[0] + self._grid.origin[0]
|
|
236
|
+
shape = SquareSerendipityShapeFunctions(degree, family=family)
|
|
237
|
+
topology = forward_base_topology(GridSerendipitySpaceTopology, grid, shape=shape)
|
|
587
238
|
|
|
588
|
-
|
|
589
|
-
cell_coords, reps=res[1]
|
|
590
|
-
)
|
|
591
|
-
Y = grid_coords_y * self._grid.cell_size[1] + self._grid.origin[1]
|
|
239
|
+
super().__init__(topology=topology, shape=shape)
|
|
592
240
|
|
|
593
|
-
return np.meshgrid(X, Y, indexing="ij")
|
|
594
241
|
|
|
595
|
-
|
|
596
|
-
|
|
242
|
+
class GridDGSerendipityBasisSpace(Grid2DBasisSpace):
|
|
243
|
+
def __init__(
|
|
244
|
+
self,
|
|
245
|
+
grid: Grid2D,
|
|
246
|
+
degree: int,
|
|
247
|
+
family: Polynomial,
|
|
248
|
+
):
|
|
249
|
+
if family is None:
|
|
250
|
+
family = Polynomial.LOBATTO_GAUSS_LEGENDRE
|
|
597
251
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
element_index: ElementIndex,
|
|
601
|
-
node_index_in_elt: int,
|
|
602
|
-
):
|
|
603
|
-
return element_index * NODES_PER_ELEMENT + node_index_in_elt
|
|
252
|
+
shape = SquareSerendipityShapeFunctions(degree, family=family)
|
|
253
|
+
topology = Grid2DDiscontinuousSpaceTopology(grid, shape=shape)
|
|
604
254
|
|
|
605
|
-
|
|
255
|
+
super().__init__(topology=topology, shape=shape)
|
|
606
256
|
|
|
607
|
-
return cache.get_func(element_node_index, f"{self.name}_{self.ORDER}")
|
|
608
257
|
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
258
|
+
class GridDGPolynomialBasisSpace(Grid2DBasisSpace):
|
|
259
|
+
def __init__(
|
|
260
|
+
self,
|
|
261
|
+
grid: Grid2D,
|
|
262
|
+
degree: int,
|
|
263
|
+
):
|
|
264
|
+
shape = SquareNonConformingPolynomialShapeFunctions(degree)
|
|
265
|
+
topology = Grid2DDiscontinuousSpaceTopology(grid, shape=shape)
|
|
612
266
|
|
|
613
|
-
|
|
614
|
-
return GridDGBipolynomialSpace.Trace(self)
|
|
267
|
+
super().__init__(topology=topology, shape=shape)
|