Skip to content

Commit

Permalink
use affine root coords as geom if possible (#855)
Browse files Browse the repository at this point in the history
Before 5034398 the geometry of a rectilinear mesh with uniform vertices was
an affine transformation of the root coordinates. In patch 5034398 this
special case was removed due to a pending change in the transform chains for
structured topologies: the replacement of the transformation that places an
element in the root space with an index, thereby giving every element unit
square root coordinates.

The effect of this change is a suboptimal gradient of the geometry to the root
coordinates. Since the geometry is now always the inner product of a linear
basis with vertices, the gradient of the geometry does not simplify to a
constant if the vertices are evenly spaced.

This PR restores the special cased geometry for rectilinear meshes defined
by numbers of elements by creating a reference geometry out of the (unit
square) root coordinates and the element index.
  • Loading branch information
joostvanzwieten committed Mar 1, 2024
2 parents 58cfd7d + 162f670 commit 9d7cc65
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 7 deletions.
2 changes: 1 addition & 1 deletion nutils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
'Numerical Utilities for Finite Element Analysis'

__version__ = version = '9a18'
__version__ = version = '9a19'
version_name = 'jook-sing'
23 changes: 17 additions & 6 deletions nutils/mesh.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,18 @@ def rectilinear(richshape: Sequence[Union[int, Sequence[float]]], periodic: Sequ
axes = [transformseq.DimAxis(i=0, j=n, mod=n if idim in periodic else 0, isperiodic=idim in periodic) for idim, n in enumerate(shape)]
topo = topology.StructuredTopology(space, root, axes)

funcsp = topo.basis('spline', degree=1, periodic=())
coords = numeric.meshgrid(*verts).reshape(ndims, -1)
geom = (funcsp * coords).sum(-1)
if all(map(numeric.isint, richshape)):
flat_index = topo.f_index
rev_unraveled_index = []
for n in shape[:0:-1]:
rev_unraveled_index.append(flat_index % n)
flat_index //= n
rev_unraveled_index.append(flat_index)
geom = topo.f_coords + numpy.stack(rev_unraveled_index[::-1])
else:
funcsp = topo.basis('spline', degree=1, periodic=())
coords = numeric.meshgrid(*verts).reshape(ndims, -1)
geom = (funcsp * coords).sum(-1)

return topo, geom

Expand All @@ -52,10 +61,12 @@ def rectilinear(richshape: Sequence[Union[int, Sequence[float]]], periodic: Sequ
def line(nodes: Union[int, Sequence[float]], periodic: bool = False, bnames: Optional[Tuple[str, str]] = None, *, space: str = 'X', root: Optional[TransformItem] = None) -> Tuple[Topology, function.Array]:
if root is None:
root = transform.Index(1, 0)
nelems = nodes if isinstance(nodes, int) else len(nodes) - 1
domain = topology.StructuredLine(space, root, 0, nelems, periodic=periodic, bnames=bnames)
if isinstance(nodes, int):
nodes = numpy.arange(nodes + 1)
domain = topology.StructuredLine(space, root, 0, len(nodes) - 1, periodic=periodic, bnames=bnames)
geom = domain.basis('std', degree=1, periodic=[]).dot(nodes)
geom = domain.f_coords[0] + domain.f_index
else:
geom = domain.basis('std', degree=1, periodic=[]).dot(nodes)
return domain, geom


Expand Down

0 comments on commit 9d7cc65

Please sign in to comment.