diff --git a/nutils/function.py b/nutils/function.py index b01bbeaa3..bb3de996b 100644 --- a/nutils/function.py +++ b/nutils/function.py @@ -4216,7 +4216,7 @@ def sum(arg: IntoArray, axis: Optional[Union[int, Sequence[int]]] = None) -> Arr return summed @implements(numpy.product) - def product(arg: IntoArray, axis: int) -> Array: + def product(arg: IntoArray, axis: Optional[Union[int, Sequence[int]]] = None) -> Array: arg = Array.cast(arg) if arg.dtype == bool: arg = arg.astype(int) diff --git a/nutils/mesh.py b/nutils/mesh.py index 45ac4d921..08fa5690d 100644 --- a/nutils/mesh.py +++ b/nutils/mesh.py @@ -734,6 +734,8 @@ def unitcircle(nelems: int, variant: str) -> Tuple[Topology, function.Array]: the same topological structure as :func:`unitsquare` with ``etype='multipatch'``. + * ``"triangle"``: unstructured mesh of triangles. + Returns ------- :class:`nutils.topology.TransformChainsTopology`: @@ -750,6 +752,20 @@ def unitcircle(nelems: int, variant: str) -> Tuple[Topology, function.Array]: topo, geom = unitsquare(nelems, 'multipatch') return topo, _square_to_circle(geom) + elif variant == 'triangle': + transforms = transformseq.IndexTransforms(ndims=2, length=6) + nodes = numpy.zeros((6, 3), dtype=int) + nodes[:,1] = 1, 2, 3, 4, 5, 1 + nodes[:,2] = 2, 3, 4, 5, 6, 6 + topo = topology.SimplexTopology('X', nodes, transforms, transforms) + x = .5 + y = .5 * numpy.sqrt(3) + coords = numpy.array([[0, 0], [1, 0], [x, y], [-x, y], [-1, 0], [-x, -y], [x, -y]]) + geom = topo.basis('std', 1) @ coords + scale = (1 - numpy.product(function.rootcoords('X', 2)))**-.5 + nrefine = round(numpy.log2(nelems)) + return topo.refine(nrefine), geom * scale + else: raise Exception('invalid variant {!r}'.format(variant)) diff --git a/tests/test_mesh.py b/tests/test_mesh.py index 822485d1c..83a8fd876 100644 --- a/tests/test_mesh.py +++ b/tests/test_mesh.py @@ -200,3 +200,4 @@ def test_interface(self): unitcircle(variant='rectilinear') unitcircle(variant='multipatch') +unitcircle(variant='triangle')