diff --git a/hog/forms.py b/hog/forms.py
index c4aa334890e1cf8237154ad63db53761e72c1f66..14f9c06178b27332f70c1973431a1c9d2b7ec5c9 100644
--- a/hog/forms.py
+++ b/hog/forms.py
@@ -902,7 +902,7 @@ for details.
             # we would want tau = -pow(volume, 2.0 / 3.0) / 12.0
             # however pow(volume, 2.0 / 3.0) is not vectorized
             # do three iterations of newton's method with starting value x0 = volume instead
-            tau = -sp.sqrt(volume)/sp.S(162) - volume/sp.S(324) - volume/(sp.S(18)*sp.sqrt(sp.S(2)*sp.sqrt(volume)/sp.S(9) + volume/sp.S(9) + sp.S(2)*volume/(sp.S(3)*sp.sqrt(sp.S(2)*sp.sqrt(volume)/sp.S(3) + volume/sp.S(3))))) - volume/(sp.S(54)*sp.sqrt(sp.S(2)*sp.sqrt(volume)/sp.S(3) + volume/sp.S(3)))
+            tau = -sp.sqrt(volume)*sp.Rational(1,162) - volume*sp.Rational(1,324) - volume/(18*sp.sqrt(2*sp.sqrt(volume)*sp.Rational(1,9) + volume*sp.Rational(1,9) + 2*volume/(3*sp.sqrt(2*sp.sqrt(volume)*sp.Rational(1,3) + volume*sp.Rational(1,3))))) - volume/(54*sp.sqrt(2*sp.sqrt(volume)*sp.Rational(1,3) + volume*sp.Rational(1,3)))
 
         mat = create_empty_element_matrix(trial, test, geometry)
 
@@ -1520,6 +1520,15 @@ def grad_rho_rho(
                 domain="reference",
                 function_id="rho",
             )
+            
+            # invRho (density)
+            invRho,invRho_values,invRho_basis,invRho_len,invRho_derivatives,invRho_grad = fem_function_on_element_AHFC_compatibility_helper(
+                coefficient_function_space,
+                geometry,
+                symbolizer,
+                domain="reference",
+                function_id="invRho",
+            )
         else:
             raise HOGException(
                 "grad_rho_rho only defined for FEM function coefficients"
@@ -1541,7 +1550,7 @@ def grad_rho_rho(
             grad_rho_component_trafo = (jac_blending_inv.T * jac_affine_inv.T * rho_grad)[component_index]
 
             form = (
-                grad_rho_component_trafo/rho[0] * affine_factor * jac_blending_det
+                invRho[0] * grad_rho_component_trafo * affine_factor * jac_blending_det
             )
 
             mat[data.row, data.col] = form
@@ -1877,13 +1886,13 @@ def shear_heating(
             vRef = symbolizer.ref_coords_as_list(dimensions=geometry.dimensions)
             dim = geometry.dimensions
 
-            # rho (density)
-            rho, _ = fem_function_on_element(
+            # invRho (density)
+            invRho, _ = fem_function_on_element(
                 rho_function_space,
                 geometry,
                 symbolizer,
                 domain="reference",
-                function_id="rho",
+                function_id="invRho",
             )
 
             # eta (viscosity)
@@ -1960,13 +1969,13 @@ def shear_heating(
             sigma_u = sp.Rational(1,2) * (grad_u_vec_trafo +  grad_u_vec_trafo.T)
             xi_u = -sp.Rational(1,dim) * div_u * sp.eye(dim)
             epsilon_u = sigma_u + xi_u
-            tau_u = sp.S(2) * eta[0] * epsilon_u
+            tau_u = 2 * eta[0] * epsilon_u
 
             # double contraction
             double_contrac = sum([tau_u[i, j] * epsilon_u[i, j] for i in range(dim) for j in range(dim)])
 
             # scaling
-            scaling = sp.S(1) / rho[0]
+            scaling = invRho[0]
 
             affine_factor = tabulation.register_factor("affine_factor_symbol", sp.Matrix([phi * psi * jac_affine_det]))[0]
 
@@ -2060,13 +2069,13 @@ def shear_heating_supg(
             vRef = symbolizer.ref_coords_as_list(dimensions=geometry.dimensions)
             dim = geometry.dimensions
 
-            # rho (density)
-            rho, _ = fem_function_on_element(
+            # invRho (density)
+            invRho, _ = fem_function_on_element(
                 rho_function_space,
                 geometry,
                 symbolizer,
                 domain="reference",
-                function_id="rho",
+                function_id="invRho",
             )
 
             # eta (viscosity)
@@ -2169,13 +2178,13 @@ def shear_heating_supg(
             sigma_u = sp.Rational(1,2) * (grad_u_vec_trafo +  grad_u_vec_trafo.T)
             xi_u = -sp.Rational(1,dim) * div_u * sp.eye(dim)
             epsilon_u = sigma_u + xi_u
-            tau_u = sp.S(2) * eta[0] * epsilon_u
+            tau_u = 2 * eta[0] * epsilon_u
 
             # double contraction
             double_contrac = sum([tau_u[i, j] * epsilon_u[i, j] for i in range(dim) for j in range(dim)])
 
             # scaling
-            scaling = sp.S(1) / rho[0]
+            scaling = invRho[0]
 
             jac_affine_inv_T_grad_psi = tabulation.register_factor("jac_affine_inv_T_grad_psi", sp.Matrix([jac_affine_inv.T  * grad_psi]))
             affine_factor = tabulation.register_factor("affine_factor_symbol", sp.Matrix([phi * jac_affine_det]))[0]
@@ -2252,6 +2261,15 @@ def diffusion_inv_rho(
                 domain="reference",
                 function_id="rho",
             )
+            
+            # invRho (density)
+            invRho,invRho_values,invRho_basis,invRho_len,invRho_derivatives,invRho_grad = fem_function_on_element_AHFC_compatibility_helper(
+                coefficient_function_space,
+                geometry,
+                symbolizer,
+                domain="reference",
+                function_id="invRho",
+            )
         else:
             raise HOGException(
                 "diffusion_inv_rho only defined for FEM function coefficients"
@@ -2273,7 +2291,7 @@ def diffusion_inv_rho(
             grad_rho_trafo = (jac_blending_inv.T * jac_affine_inv.T * rho_grad)
             grad_phi_trafo = (jac_blending_inv.T * jac_affine_inv_T_grad_phi)
 
-            scaling = psi / (rho[0]*rho[0])
+            scaling = psi * invRho[0] * invRho[0]
 
             form = (
                 -scaling * (grad_phi_trafo.T * grad_rho_trafo)[0] * jac_blending_det
@@ -2903,13 +2921,13 @@ def diffusion_supg(
             vRef_tuple = tuple([vRef[i] for i in range(geometry.dimensions)])
             dim = geometry.dimensions
 
-            # rho (density)
-            rho, _ = fem_function_on_element(
+            # invRho (density)
+            invRho, _ = fem_function_on_element(
                 rho_function_space,
                 geometry,
                 symbolizer,
                 domain="reference",
-                function_id="rho",
+                function_id="invRho",
             )
             
             # uX (velocity x direction)
@@ -3005,7 +3023,7 @@ def diffusion_supg(
             supg = (u_vec.T * grad_psi_trafo)[0]
 
             # scaling
-            scaling = sp.S(1) / rho[0]
+            scaling = invRho[0]
             
             form = (
                  -delta * scaling * laplace_phi_trafo * supg * jac_affine_det * jac_blending_det
@@ -3080,10 +3098,10 @@ def centroid_test_mass(
 
         if dim > 2:
             # expr = x*z + x - 2y + 3
-            k = vCentroid[0] * vCentroid[2] + vCentroid[0] - 2*vCentroid[1] + sp.S(3)            
+            k = vCentroid[0] * vCentroid[2] + vCentroid[0] - 2*vCentroid[1] + 3     
         else:
             # expr = x*y + x - 2y + 3
-            k = vCentroid[0] * vCentroid[1] + vCentroid[0] - 2*vCentroid[1] + sp.S(3)
+            k = vCentroid[0] * vCentroid[1] + vCentroid[0] - 2*vCentroid[1] + 3
 
 
         mat = create_empty_element_matrix(trial, test, geometry)
@@ -4605,7 +4623,7 @@ def shear_heating_simple_visc(
             sigma_u = sp.Rational(1,2) * (grad_u_vec_trafo +  grad_u_vec_trafo.T)
             xi_u = -sp.Rational(1,dim) * div_u * sp.eye(dim)
             epsilon_u = sigma_u + xi_u
-            tau_u = sp.S(2) * eta * epsilon_u
+            tau_u = 2 * eta * epsilon_u
 
             # double contraction
             double_contrac = sum([tau_u[i, j] * epsilon_u[i, j] for i in range(dim) for j in range(dim)])
@@ -4811,7 +4829,7 @@ def shear_heating_supg_simple_visc(
             sigma_u = sp.Rational(1,2) * (grad_u_vec_trafo +  grad_u_vec_trafo.T)
             xi_u = -sp.Rational(1,dim) * div_u * sp.eye(dim)
             epsilon_u = sigma_u + xi_u
-            tau_u = sp.S(2) * eta * epsilon_u
+            tau_u = 2 * eta * epsilon_u
 
             # double contraction
             double_contrac = sum([tau_u[i, j] * epsilon_u[i, j] for i in range(dim) for j in range(dim)])
@@ -5276,7 +5294,7 @@ def shear_heating_frank_kamenetskii_simple_visc_base(
             sigma_u = sp.Rational(1,2) * (grad_u_vec_trafo +  grad_u_vec_trafo.T)
             xi_u = -sp.Rational(1,dim) * div_u * sp.eye(dim)
             epsilon_u = sigma_u + xi_u
-            tau_u = sp.S(2) * eta * epsilon_u
+            tau_u = 2 * eta * epsilon_u
 
             # double contraction
             double_contrac = sum([tau_u[i, j] * epsilon_u[i, j] for i in range(dim) for j in range(dim)])
@@ -5512,7 +5530,7 @@ def shear_heating_supg_frank_kamenetskii_simple_visc_base(
             sigma_u = sp.Rational(1,2) * (grad_u_vec_trafo +  grad_u_vec_trafo.T)
             xi_u = -sp.Rational(1,dim) * div_u * sp.eye(dim)
             epsilon_u = sigma_u + xi_u
-            tau_u = sp.S(2) * eta * epsilon_u
+            tau_u = 2 * eta * epsilon_u
 
             # double contraction
             double_contrac = sum([tau_u[i, j] * epsilon_u[i, j] for i in range(dim) for j in range(dim)])
@@ -5532,4 +5550,421 @@ def shear_heating_supg_frank_kamenetskii_simple_visc_base(
 
             mat[data.row, data.col] = form
 
+    return Form(mat, tabulation, symmetric=False, docstring=docstring)
+
+
+def shear_heating_no_surface(
+    trial: FunctionSpace,
+    test: FunctionSpace,
+    geometry: ElementGeometry,
+    symbolizer: Symbolizer,
+    blending: GeometryMap = IdentityMap(),
+    coefficient_function_space: Optional[FunctionSpace] = None,
+    eta_function_space: Optional[FunctionSpace] = None,
+    rho_function_space: Optional[FunctionSpace] = None
+) -> Form:
+    docstring = f"""
+    Shear heating operator for the TALA
+    
+    Intended for RHS use.
+    
+    For the two dimensional case this is the pseudo-3D form of the operator.
+    Otherwise eps(u) would need to be := 1/2 ∇u + 1/2 (∇u)^T - 1/2 (∇ · u) I.
+
+    Typical usage sets T = 1, i.e. applying the operator to a function containing only ones.
+    TODO: Linear forms in hyteg
+
+    Suggested quad degrees:
+    Maximum: {(((1 if coefficient_function_space is None else coefficient_function_space.degree))-1)*2 + trial.degree + test.degree + 1 + (0 if isinstance(blending, IdentityMap) else 1)}
+    Reduced: {trial.degree + test.degree + 1 + (0 if isinstance(blending, IdentityMap) else 1)}
+    Minimum: {trial.degree + test.degree + 1}
+
+    Geometry map: {blending}
+
+    Weak formulation
+
+        T: trial function (scalar space: {trial})
+        w: test function (scalar space: {test})
+        u: coefficient (vector space: {coefficient_function_space})
+        rho: coefficient (scalar space: {rho_function_space})
+        eta: coefficient (scalar space: {eta_function_space})
+
+        ∫ 1/rho ( tau(u,eta) : eps(u) ) T * w
+
+        with
+
+        tau(u,eta) = 2 eta eps(u)
+        eps(u) := 1/2 ∇u + 1/2 (∇u)^T - 1/dim (∇ · u) I
+        I := Identity Matrix             
+    """
+
+    with TimedLogger(
+        f"assembling shear_heating matrix",
+        level=logging.DEBUG,
+    ):
+        tabulation = Tabulation(symbolizer)
+
+        jac_affine = symbolizer.jac_ref_to_affine(geometry.dimensions)
+        jac_affine_inv = symbolizer.jac_ref_to_affine_inv(geometry.dimensions)
+        jac_affine_det = symbolizer.abs_det_jac_ref_to_affine()
+
+        if isinstance(blending, ExternalMap):
+            jac_blending = jac_affine_to_physical(geometry, symbolizer)
+        else:
+            affine_coords = trafo_ref_to_affine(geometry, symbolizer)
+            jac_blending = blending.jacobian(affine_coords)
+
+        jac_blending_det = abs(det(jac_blending))
+        with TimedLogger("inverting blending Jacobian", level=logging.DEBUG):
+            jac_blending_inv = inv(jac_blending)
+
+        if coefficient_function_space and eta_function_space and rho_function_space:
+            vRef = symbolizer.ref_coords_as_list(dimensions=geometry.dimensions)
+            dim = geometry.dimensions
+
+            # invRho (density)
+            invRho, _ = fem_function_on_element(
+                rho_function_space,
+                geometry,
+                symbolizer,
+                domain="reference",
+                function_id="invRho",
+            )
+
+            # eta (viscosity)
+            eta, _ = fem_function_on_element(
+                eta_function_space,
+                geometry,
+                symbolizer,
+                domain="reference",
+                function_id="eta",
+            )
+                        
+            # uX (velocity x direction)
+            uX,uX_values,uX_basis,uX_len,uX_derivatives,uX_grad = fem_function_on_element_AHFC_compatibility_helper(
+                coefficient_function_space,
+                geometry,
+                symbolizer,
+                domain="reference",
+                function_id="uX",
+            )
+
+            # uY (velocity y direction)
+            uY,uY_values,uY_basis,uY_len,uY_derivatives,uY_grad = fem_function_on_element_AHFC_compatibility_helper(
+                coefficient_function_space,
+                geometry,
+                symbolizer,
+                domain="reference",
+                function_id="uY",
+            )
+            
+            # lists
+            u = [uX, uY]
+            u_values = [uX_values,uY_values]
+            u_derivatives = [uX_derivatives,uY_derivatives]
+            u_len = [uX_len, uY_len]
+            
+            if dim > 2:
+                # uZ (velocity z direction)
+                uZ,uZ_values,uZ_basis,uZ_len,uZ_derivatives,uZ_grad = fem_function_on_element_AHFC_compatibility_helper(
+                    coefficient_function_space,
+                    geometry,
+                    symbolizer,
+                    domain="reference",
+                    function_id="uZ",
+                )
+
+                u.append(uZ)       
+                u_values.append(uZ_values)
+                u_derivatives.append(uZ_derivatives)
+                u_len.append(uZ_len)
+                
+            grad_u_vec = sp.zeros(dim,dim)
+            for component_u in range(dim):
+                for j in range(dim):
+                    # be aware that the jacobian is transposed here to get the gradient (i.e. j and component_u were swaped in comp to the jacobian)
+                    grad_u_vec[j,component_u] = sum([u_values[component_u][i]*u_derivatives[component_u][i][j] for i in range(u_len[component_u])])
+        else:
+            raise HOGException(
+                "shear heating only defined for FEM function coefficients"
+            )  
+            
+        mat = create_empty_element_matrix(trial, test, geometry)
+
+        it = element_matrix_iterator(trial, test, geometry)
+
+        # remove surface
+        if isinstance(blending, IdentityMap):
+            coords_on_element = trafo_ref_to_affine(geometry, symbolizer)
+        else:
+            coords_on_element = trafo_ref_to_physical(geometry, symbolizer, blending)
+            
+        dim = geometry.dimensions
+        v = [coords_on_element[i] for i in range(dim)]
+        norm = sp.sqrt(sum([v[i]*v[i] for i in range(dim)]))
+
+        radiusSurface = sp.symbols("radiusSurface")
+        cutoff = sp.symbols("cutoff")
+        pos = radiusSurface - norm
+
+        posScaling = sp.Piecewise(
+            (0.0, pos < cutoff     ),
+            (1.0, sp.sympify(True) )
+        )
+        # /remove surface
+        
+        for data in it:
+            phi = data.trial_shape
+            psi = data.test_shape
+            grad_phi = data.trial_shape_grad
+            grad_psi = data.test_shape_grad
+
+            grad_u_vec_trafo = jac_blending_inv.T * jac_affine_inv.T * grad_u_vec
+            div_u = sum([grad_u_vec_trafo[component_u, component_u] for component_u in range(dim)])
+
+            sigma_u = sp.Rational(1,2) * (grad_u_vec_trafo +  grad_u_vec_trafo.T)
+            xi_u = -sp.Rational(1,dim) * div_u * sp.eye(dim)
+            epsilon_u = sigma_u + xi_u
+            tau_u = 2 * eta[0] * epsilon_u
+
+            # double contraction
+            double_contrac = sum([tau_u[i, j] * epsilon_u[i, j] for i in range(dim) for j in range(dim)])
+
+            # scaling
+            scaling = invRho[0]
+
+            affine_factor = tabulation.register_factor("affine_factor_symbol", sp.Matrix([phi * psi * jac_affine_det]))[0]
+
+            form = (
+                posScaling * scaling * double_contrac * affine_factor * jac_blending_det
+            )
+
+            mat[data.row, data.col] = form
+
+    return Form(mat, tabulation, symmetric=False, docstring=docstring)
+
+def shear_heating_supg_no_surface(
+    trial: FunctionSpace,
+    test: FunctionSpace,
+    geometry: ElementGeometry,
+    symbolizer: Symbolizer,
+    blending: GeometryMap = IdentityMap(),
+    coefficient_function_space: Optional[FunctionSpace] = None,
+    eta_function_space: Optional[FunctionSpace] = None,
+    rho_function_space: Optional[FunctionSpace] = None,
+) -> Form:
+    docstring = f"""
+    Shear heating operator for the TALA
+    
+    Intended for RHS use.
+    
+    For the two dimensional case this is the pseudo-3D form of the operator.
+    Otherwise eps(u) would need to be := 1/2 ∇u + 1/2 (∇u)^T - 1/2 (∇ · u) I.
+
+    Typical usage sets T = 1, i.e. applying the operator to a function containing only ones.
+    TODO: Linear forms in hyteg
+
+    The scaling function for the supg stabilisation is hard coded into the form.
+
+    delta( u_abs ) := hMax / ( 2 * u_abs ) * xi( Pe )
+
+    with:
+        xi( Pe ) :=  ( 1 + 2 / ( exp( 2* Pe ) - 1 ) - 1 / Pe ) = coth( Pe ) - 1 / Pe
+        Pe := u_abs * h / ( 2 * k ) as the local Peclet number
+        h as the element diameter
+        k as the thermal conductivity coefficient
+        u_abs as the norm of the velocity vector at the element centroid
+
+    Note: h is calculated from the affine element geometry. If your blending map changes the element diameter too drastically, this will no longer work.
+
+    Suggested quad degrees:
+    Maximum: {(((1 if coefficient_function_space is None else coefficient_function_space.degree))-1)*2 + trial.degree + ((1 if coefficient_function_space is None else coefficient_function_space.degree)) + (test.degree-1) + 1 + (0 if isinstance(blending, IdentityMap) else 1)}
+    Reduced: {trial.degree + (test.degree-1) + 1 + (0 if isinstance(blending, IdentityMap) else 1)}
+    Minimum: {trial.degree + (test.degree-1) + 1}
+
+    Geometry map: {blending}
+
+    Weak formulation
+
+        T: trial function (scalar space: {trial})
+        w: test function (scalar space: {test})
+        u: coefficient (vector space: {coefficient_function_space})
+        rho: coefficient (scalar space: {rho_function_space})
+        eta: coefficient (scalar space: {eta_function_space})
+
+        ∫ delta 1/rho ( tau(u,eta) : eps(u) ) T * ( u · ∇w )
+
+        with
+
+        tau(u,eta) = 2 eta eps(u)
+        eps(u) := 1/2 ∇u + 1/2 (∇u)^T - 1/3 (∇ · u) I
+        I := Identity Matrix             
+    """
+
+    with TimedLogger(
+        f"assembling shear_heating_supg matrix",
+        level=logging.DEBUG,
+    ):
+        tabulation = Tabulation(symbolizer)
+
+        jac_affine = symbolizer.jac_ref_to_affine(geometry.dimensions)
+        jac_affine_inv = symbolizer.jac_ref_to_affine_inv(geometry.dimensions)
+        jac_affine_det = symbolizer.abs_det_jac_ref_to_affine()
+
+        if isinstance(blending, ExternalMap):
+            jac_blending = jac_affine_to_physical(geometry, symbolizer)
+        else:
+            affine_coords = trafo_ref_to_affine(geometry, symbolizer)
+            jac_blending = blending.jacobian(affine_coords)
+
+        jac_blending_det = abs(det(jac_blending))
+        with TimedLogger("inverting blending Jacobian", level=logging.DEBUG):
+            jac_blending_inv = inv(jac_blending)
+
+        if coefficient_function_space and eta_function_space and rho_function_space:
+            vRef = symbolizer.ref_coords_as_list(dimensions=geometry.dimensions)
+            dim = geometry.dimensions
+
+            # invRho (density)
+            invRho, _ = fem_function_on_element(
+                rho_function_space,
+                geometry,
+                symbolizer,
+                domain="reference",
+                function_id="invRho",
+            )
+
+            # eta (viscosity)
+            eta, _ = fem_function_on_element(
+                eta_function_space,
+                geometry,
+                symbolizer,
+                domain="reference",
+                function_id="eta",
+            )
+                        
+            # uX (velocity x direction)
+            uX,uX_values,uX_basis,uX_len,uX_derivatives,uX_grad = fem_function_on_element_AHFC_compatibility_helper(
+                coefficient_function_space,
+                geometry,
+                symbolizer,
+                domain="reference",
+                function_id="uX",
+            )
+
+            # uY (velocity y direction)
+            uY,uY_values,uY_basis,uY_len,uY_derivatives,uY_grad = fem_function_on_element_AHFC_compatibility_helper(
+                coefficient_function_space,
+                geometry,
+                symbolizer,
+                domain="reference",
+                function_id="uY",
+            )
+            
+            # lists
+            u = [uX, uY]
+            u_values = [uX_values,uY_values]
+            u_derivatives = [uX_derivatives,uY_derivatives]
+            u_len = [uX_len, uY_len]
+            
+            if dim > 2:
+                # uZ (velocity z direction)
+                uZ,uZ_values,uZ_basis,uZ_len,uZ_derivatives,uZ_grad = fem_function_on_element_AHFC_compatibility_helper(
+                    coefficient_function_space,
+                    geometry,
+                    symbolizer,
+                    domain="reference",
+                    function_id="uZ",
+                )
+
+                u.append(uZ)       
+                u_values.append(uZ_values)
+                u_derivatives.append(uZ_derivatives)
+                u_len.append(uZ_len)
+
+            u_vec = sp.Matrix([[u[i]] for i in range(dim)])
+            grad_u_vec = sp.zeros(dim,dim)
+            for component_u in range(dim):
+                for j in range(dim):
+                    # be aware that the jacobian is transposed here to get the gradient (i.e. j and component_u were swaped in comp to the jacobian)
+                    grad_u_vec[j,component_u] = sum([u_values[component_u][i]*u_derivatives[component_u][i][j] for i in range(u_len[component_u])])
+        else:
+            raise HOGException(
+                "shear heating supg only defined for FEM function coefficients"
+            )  
+        
+         # init hard coded form
+        if isinstance(blending, IdentityMap):
+            coords_on_element = trafo_ref_to_affine(geometry, symbolizer)
+        else:
+            coords_on_element = trafo_ref_to_physical(geometry, symbolizer, blending)
+            
+        v = [coords_on_element[i] for i in range(dim)]
+        
+        # u_abs
+        centroid = {vRef[i]: sp.Rational(1,dim+1) for i in range(dim)}
+        uCentroid = [sp.simplify(u[i].subs(centroid)[0]) for i in range(dim)]
+        abs_u_centroid = sp.sqrt(sum([uCentroid[i]*uCentroid[i] for i in range(dim)]))
+
+        # h
+        affine_points = symbolizer.affine_vertices_as_vectors(geometry.dimensions, geometry.num_vertices)
+        
+        h = diameter(affine_points)
+        # Alternative: h = sp.symbols("hMax")
+
+        # k
+        k = sp.symbols("thermalConductivity")
+        
+        # delta function
+        delta = deltaSUPG(abs_u_centroid, h, k, True)
+
+        # remove surface
+        norm = sp.sqrt(sum([v[i]*v[i] for i in range(dim)]))
+
+        radiusSurface = sp.symbols("radiusSurface")
+        cutoff = sp.symbols("cutoff")
+        pos = radiusSurface - norm
+
+        posScaling = sp.Piecewise(
+            (0.0, pos < cutoff     ),
+            (1.0, sp.sympify(True) )
+        )
+        # /remove surface
+            
+        mat = create_empty_element_matrix(trial, test, geometry)
+
+        it = element_matrix_iterator(trial, test, geometry)
+        
+        for data in it:
+            phi = data.trial_shape
+            psi = data.test_shape
+            grad_phi = data.trial_shape_grad
+            grad_psi = data.test_shape_grad
+
+            grad_u_vec_trafo = jac_blending_inv.T * jac_affine_inv.T * grad_u_vec
+            div_u = sum([grad_u_vec_trafo[component_u, component_u] for component_u in range(dim)])
+
+            sigma_u = sp.Rational(1,2) * (grad_u_vec_trafo +  grad_u_vec_trafo.T)
+            xi_u = -sp.Rational(1,dim) * div_u * sp.eye(dim)
+            epsilon_u = sigma_u + xi_u
+            tau_u = 2 * eta[0] * epsilon_u
+
+            # double contraction
+            double_contrac = sum([tau_u[i, j] * epsilon_u[i, j] for i in range(dim) for j in range(dim)])
+
+            # scaling
+            scaling = invRho[0]
+
+            jac_affine_inv_T_grad_psi = tabulation.register_factor("jac_affine_inv_T_grad_psi", sp.Matrix([jac_affine_inv.T  * grad_psi]))
+            affine_factor = tabulation.register_factor("affine_factor_symbol", sp.Matrix([phi * jac_affine_det]))[0]
+
+            grad_test_trafo = jac_blending_inv.T * jac_affine_inv_T_grad_psi
+            supg = (u_vec.T * grad_test_trafo)[0]
+
+            form = (
+                posScaling * delta * scaling * double_contrac * supg * affine_factor * jac_blending_det
+            )
+
+            mat[data.row, data.col] = form
+
     return Form(mat, tabulation, symmetric=False, docstring=docstring)
\ No newline at end of file
diff --git a/hog/math_helpers.py b/hog/math_helpers.py
index 8b4d5791ad5d963aef5085cd7e78eaedfb736461..eb096be812ef0199e4d582ac0078761a47ce0c39 100644
--- a/hog/math_helpers.py
+++ b/hog/math_helpers.py
@@ -204,7 +204,7 @@ def vol(vertices: List[sp.Matrix]) -> sp.Expr:
         bd = vertices[1]-vertices[3]
         cd = vertices[2]-vertices[3]
 
-        return sp.Abs(ad.dot(bd.cross(cd))) / sp.S(6)  
+        return sp.Abs(ad.dot(bd.cross(cd))) * sp.Rational(1,6)  
     else:
         raise HOGException(f"Not implemented for {len(vertices)} vertices")
     
@@ -219,7 +219,7 @@ def diameter(vertices: List[sp.Matrix]) -> sp.Expr:
         b = norm(vertices[2]-vertices[0])
         c = norm(vertices[0]-vertices[1])
 
-        return sp.S(2) * ( a * b * c / (sp.S(4) * vol(vertices)) )
+        return 2 * ( a * b * c / (4 * vol(vertices)) )
     elif len(vertices) == 4:
         # a tetrahedron
         a       = norm(vertices[0]-vertices[3])
@@ -230,9 +230,9 @@ def diameter(vertices: List[sp.Matrix]) -> sp.Expr:
         c_tilde = norm(vertices[0]-vertices[1])
 
         # heron type formula (from Cayley Menger determinant)
-        s = (a*a_tilde + b*b_tilde + c*c_tilde) / sp.S(2)
+        s = (a*a_tilde + b*b_tilde + c*c_tilde) * sp.Rational(1,2)
 
-        return sp.S(2) * ( sp.sqrt(s * (s - a*a_tilde) * (s- b*b_tilde) * (s - c*c_tilde)) / (sp.S(6) * vol(vertices)) ) 
+        return 2 * ( sp.sqrt(s * (s - a*a_tilde) * (s- b*b_tilde) * (s - c*c_tilde)) / (6 * vol(vertices)) ) 
     else:
         raise HOGException(f"Not implemented for {len(vertices)} vertices")    
 
@@ -242,7 +242,7 @@ def deltaSUPG(abs_u: sp.Expr, h: sp.Expr, k: sp. Expr, approximateXi: bool = Tru
     The exp function cannot be vectorized in pystencils yet.
     If approximateXi is True this returns an approximation that can be vectorized.
     """
-    Pe = abs_u * h / ( sp.S(2) * k )
+    Pe = abs_u * h / ( 2 * k )
     
     if approximateXi:
         # Taylor near 0, Cubic spline in a second region, 1 - 1/Pe for the rest
@@ -254,7 +254,7 @@ def deltaSUPG(abs_u: sp.Expr, h: sp.Expr, k: sp. Expr, approximateXi: bool = Tru
             ((sp.S(1) - sp.S(1)/Pe)                                                                            , sp.sympify(True)      )
         )
     else:
-        xi = sp.S(1) + sp.S(2) / ( sp.exp( sp.S(2) * Pe ) - sp.S(1) ) - sp.S(1) / Pe
+        xi = sp.S(1) + sp.S(2) / ( sp.exp( 2 * Pe ) - sp.S(1) ) - sp.S(1) / Pe
 
     return h / ( 2 * abs_u ) * xi 
 
@@ -276,12 +276,12 @@ def simpleViscosityProfile(x: sp.Expr) -> sp.Expr:
 
     etaSimple = sp.Piecewise(
         (1.25e+23, x <= 0.75),
-        (3.54619628745821e+26*x**2 - 5.43063135866058e+26*x + 2.07948810730019e+26,x <= 0.758405172413793),
+        (3.54619628745821e+26*x**2 - 5.43063135866058e+26*x + 2.07948810730019e+26, x <= 0.758405172413793),
         (1.86568634321297e+26*x**2 - 2.88161649064377e+26*x + 1.11289507706839e+26, x <= 0.764008620689655),
         (1.06929133385375e+26*x**2 - 1.66471118539444e+26*x + 6.48032005181657e+25, x <= 0.772413793103448),
         (1.5e+22 , x <= 0.85172414),
         (3.85797403183421e+25*x**2 - 6.69652358427785e+25*x + 2.90638521562008e+25, x <= 0.85948275862069),
-        (2.2385551110116e+25*x**2 - 3.91279830141555e+25*x + 1.71010327294176e+25, x <= 0.864655172413793),
+        (2.2385551110116e+25*x**2 - 3.91279830141555e+25*x + 1.71010327294176e+25 , x <= 0.864655172413793),
         (1.38463307937214e+25*x**2 - 2.43610209842523e+25*x + 1.07168676794207e+25, x <= 0.872413793103448),
         (2.5e+21, x <= 0.93793103),
         (1.95514620595374e+25*x**2 - 3.65353225743697e+25*x + 1.70704057747143e+25, x <= 0.953448275862069),