Run this tutorial
Click here to run this tutorial on mybinder.org:Example: the ALU cube grid (3d hexahedra)¶
Historically the Python bindings instantiated exactly one cube and one simplex grid per
dimension – the structured YaspGrid for cubes and the conforming ALUGrid for simplices.
As part of #320 the bindings add the
unstructured, nonconforming ALU cube grid in 3d (hexahedra), reached through a
Nonconforming() selector:
make_cube_grid(Dim(3), Cube()) # structured YaspGrid (default)
make_cube_grid(Dim(3), Cube(), Nonconforming()) # unstructured ALU hexahedral grid
Existing make_cube_grid calls are unchanged; pybind11 dispatches on the extra tag.
Why only the 3d cube?
The bindings register spaces, operators and boundary infos keyed on the grid’s leaf view
type, and dune-alugrid expresses that view through the legacy ALU3dGrid<tetra|hexa> /
ALU2dGrid – the conforming/nonconforming refinement policy is not part of the view type.
So the conforming and nonconforming ALU simplex grids share one leaf-view type and cannot both
be registered, and there is no distinct 2d cube ALUGrid at all. Only the 3d hexahedral grid has a
leaf view (ALU3dGrid<hexa>) distinct from the tetrahedral simplex and structured YASP views, so
it is the one new grid this work package can expose. Closing the nonconforming-simplex gap needs
a binding-layer change (keying on the grid rather than the view) and is tracked in #320.
# wurlitzer: display dune's output in the notebook
%load_ext wurlitzer
from dune.xt.grid import Dim, Cube, Nonconforming, make_cube_grid, visualize_grid
Structured YASP vs. unstructured ALU cube¶
Both grids start from the same structured 2 x 2 x 2 box, so the macro grids agree on element and
vertex counts:
domain = dict(lower_left=[0, 0, 0], upper_right=[1, 1, 1], num_elements=[2, 2, 2])
yasp = make_cube_grid(Dim(3), Cube(), **domain)
alu = make_cube_grid(Dim(3), Cube(), Nonconforming(), **domain)
for name, grid in (("YASP (structured)", yasp), ("ALU (unstructured)", alu)):
print(f"{name:20s}: {grid.size(0)} elements, {grid.size(3)} vertices")
YASP (structured) : 8 elements, 27 vertices
ALU (unstructured) : 8 elements, 27 vertices
One global refinement splits every hexahedron into 2^d = 8 children, for both implementations:
for name, grid in (("YASP (structured)", yasp), ("ALU (unstructured)", alu)):
before = grid.size(0)
grid.global_refine(1)
print(f"{name:20s}: {before} -> {grid.size(0)} elements (x{grid.size(0) // before})")
YASP (structured) : 8 -> 64 elements (x8)
ALU (unstructured) : 8 -> 64 elements (x8)
A finite-element space on the ALU cube grid¶
The FEM stack works on the new grid like on any other: we can build a ContinuousLagrangeSpace,
a DiscreteFunction, and visualise the hexahedral grid.
from dune.gdt import ContinuousLagrangeSpace, DiscreteFunction
grid = make_cube_grid(Dim(3), Cube(), Nonconforming(),
lower_left=[0, 0, 0], upper_right=[1, 1, 1], num_elements=[4, 4, 4])
V_h = ContinuousLagrangeSpace(grid, order=1)
u_h = DiscreteFunction(V_h, name="u_h")
print(f"ALU cube grid: {grid.size(0)} elements, {V_h.num_DoFs} DoFs (Q1)")
_ = visualize_grid(grid)
ALU cube grid: 64 elements, 125 DoFs (Q1)
Local adaptation is simplex-only for now
The ALU cube grid supports local, nonconforming refinement in principle, but AdaptationHelper
(and the marking/adapt machinery) is currently bound only for the simplex grids – see the
grid adaptation example, which marks and adapts a 2d
simplex grid. Extending the adaptation bindings to cube grids is a separate binding gap, tracked
in #320.
How this reaches the property-test suite¶
The GridProvider* classes that dune.xt.grid exposes encode every bound grid combination as
GridProvider<dim>d<Element><Impl>. The shared dune.xt.test.hypothesis_strategies module
discovers the bound grids by parsing exactly these names (see
#320 WP0), so the new GridProvider3dCubeAlunonconformgrid
is drawn by the property tests automatically – no strategy edit was needed to start exercising it:
import dune.xt.grid as xtgrid
for name in sorted(n for n in dir(xtgrid) if n.startswith("GridProvider")):
print(name)
GridProvider1dCubeYaspgrid
GridProvider1dSimplexOnedgrid
GridProvider2dCubeYaspgrid
GridProvider2dSimplexAluconformgrid
GridProvider3dCubeAlunonconformgrid
GridProvider3dCubeYaspgrid
GridProvider3dSimplexAluconformgrid