From f090a2ac85870cf0e7841e4a8e3d77369eac7440 Mon Sep 17 00:00:00 2001 From: Pablo Brubeck Date: Thu, 26 Mar 2026 20:31:30 +0000 Subject: [PATCH 1/3] Support physical_normals on manifolds --- tsfc/fem.py | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/tsfc/fem.py b/tsfc/fem.py index 943089052e..95dc093c5c 100644 --- a/tsfc/fem.py +++ b/tsfc/fem.py @@ -268,19 +268,28 @@ def physical_tangents(self): return rts @ jac.T def physical_normals(self): + domain = extract_unique_domain(self.mt.terminal) + gdim = domain.geometric_dimension + tdim = domain.topological_dimension cell = self.interface.fiat_cell - sd = cell.get_spatial_dimension() - num_faces = len(cell.get_topology()[sd-1]) - if isinstance(cell, UFCSimplex) and sd == 2: + num_faces = len(cell.get_topology()[tdim-1]) + if isinstance(cell, UFCSimplex) and tdim == 1: + pts = self.physical_tangents() + return gem.ListTensor([[pts[0, j] for j in range(gdim)] for i in range(num_faces)]) + elif isinstance(cell, UFCSimplex) and tdim == 2 and gdim == 2: pts = self.physical_tangents() - return gem.ListTensor([[pts[i, 1], -1*pts[i, 0]] for i in range(num_faces)]) - elif isinstance(cell, UFCSimplex) and sd == 3: - t = ufl.classes.CellEdgeVectors(extract_unique_domain(self.mt.terminal)) - edges = cell.get_connectivity()[(sd-1, 1)] + return gem.ListTensor([[pts[i, 1], -pts[i, 0]] for i in range(num_faces)]) + elif isinstance(cell, UFCSimplex) and gdim == 3: + t = ufl.classes.CellEdgeVectors(domain) normalize = lambda x: x / ufl.sqrt(ufl.dot(x, x)) - expr = ufl.as_tensor([-2.0*normalize(ufl.cross(t[edges[i][0], :], t[edges[i][1], :])) - for i in range(num_faces)]) - return self.translate_point_expression(expr) + if tdim == 2: + R = ufl.cross(t[0, :], t[1, :]) + exprs = [normalize(ufl.cross(t[i, :], R)) for i in range(num_faces)] + else: + edges = cell.get_connectivity()[(tdim-1, 1)] + exprs = [-2.0*normalize(ufl.cross(t[edges[i][0], :], t[edges[i][1], :])) + for i in range(num_faces)] + return self.translate_point_expression(ufl.as_tensor(exprs)) else: raise NotImplementedError("Can't do physical normals on that cell yet") From 508828bbb45384620d496bc8731367089d6be99d Mon Sep 17 00:00:00 2001 From: Pablo Brubeck Date: Fri, 27 Mar 2026 10:26:38 +0000 Subject: [PATCH 2/3] Remove NaN from gem.Conditional, this triggers a loopy warning --- tsfc/kernel_interface/common.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tsfc/kernel_interface/common.py b/tsfc/kernel_interface/common.py index aed238c64f..8fe12a64fc 100644 --- a/tsfc/kernel_interface/common.py +++ b/tsfc/kernel_interface/common.py @@ -73,10 +73,7 @@ def cell_orientation(self, domain, restriction): f = {None: 0, '+': 0, '-': 1}[restriction] co_int = self._cell_orientations[domain][f] return gem.Conditional(gem.Comparison("==", co_int, gem.Literal(1)), - gem.Literal(-1), - gem.Conditional(gem.Comparison("==", co_int, gem.Zero()), - gem.Literal(1), - gem.Literal(numpy.nan))) + gem.Literal(-1), gem.Literal(1)) def cell_size(self, domain, restriction): if not hasattr(self, "_cell_sizes"): From 671b61572a7518951ba38b1b576849e2cb68401e Mon Sep 17 00:00:00 2001 From: Pablo Brubeck Date: Fri, 27 Mar 2026 10:32:04 +0000 Subject: [PATCH 3/3] DROP BEFORE MERGE --- .github/workflows/core.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml index e738561b9c..9e4f8623e9 100644 --- a/.github/workflows/core.yml +++ b/.github/workflows/core.yml @@ -210,6 +210,8 @@ jobs: --extra-index-url https://download.pytorch.org/whl/cpu \ "$(echo ./firedrake-repo/dist/firedrake-*.tar.gz)[ci]" + : # UNDO ME + pip install -v --no-deps --ignore-installed git+https://github.com/firedrakeproject/fiat.git@pbrubeck/zany-manifold firedrake-clean pip list