diff --git a/AUTHORS.rst b/AUTHORS.rst index 7c0a1be47b..5219fcd24a 100644 --- a/AUTHORS.rst +++ b/AUTHORS.rst @@ -148,6 +148,8 @@ Tomasz J. Salwa Kaho Sato +Matthew Scroggs............... + Ben Sepanski.................. Daniel R. Shapero............. diff --git a/docs/source/team.ini b/docs/source/team.ini index 3bad59123a..4553f13c58 100644 --- a/docs/source/team.ini +++ b/docs/source/team.ini @@ -107,6 +107,7 @@ Francis P. Russell: Thomas Roy: Tomasz J. Salwa: Kaho Sato: +Matthew Scroggs: https://mscroggs.co.uk Ben Sepanski: https://bensepanski.github.io Jemma Shipton: Joseph G. Wallwork: https://www.imperial.ac.uk/people/j.wallwork16 diff --git a/firedrake/__init__.py b/firedrake/__init__.py index b1a4d94e11..d15164b9f0 100644 --- a/firedrake/__init__.py +++ b/firedrake/__init__.py @@ -54,6 +54,7 @@ pass del ufl from ufl import * +from finat.ufl import * # Set up the cache directories before importing PyOP2. firedrake_configuration.setup_cache_dirs() diff --git a/firedrake/adjoint_utils/constant.py b/firedrake/adjoint_utils/constant.py index a596f2855d..42bc18e033 100644 --- a/firedrake/adjoint_utils/constant.py +++ b/firedrake/adjoint_utils/constant.py @@ -95,7 +95,7 @@ def _ad_dot(self, other, options=None): @staticmethod def _ad_assign_numpy(dst, src, offset): - l = dst.ufl_element().value_size() + l = dst.ufl_element().value_size dst.assign(numpy.reshape(src[offset:offset + l], dst.ufl_shape), annotate=False) offset += l return dst, offset diff --git a/firedrake/assemble.py b/firedrake/assemble.py index 1ac6b20710..ba1c15fa80 100644 --- a/firedrake/assemble.py +++ b/firedrake/assemble.py @@ -14,6 +14,7 @@ from tsfc.finatinterface import create_element from tsfc.ufl_utils import extract_firedrake_constants import ufl +import finat.ufl from firedrake import (extrusion_utils as eutils, matrix, parameters, solving, tsfc_interface, utils) from firedrake.adjoint_utils import annotate_assemble @@ -1294,7 +1295,7 @@ def _as_global_kernel_arg_coefficient(_, self): ufl_element = V.ufl_element() if ufl_element.family() == "Real": - return op2.GlobalKernelArg((ufl_element.value_size(),)) + return op2.GlobalKernelArg((ufl_element.value_size,)) else: finat_element = create_element(ufl_element) return self._make_dat_global_kernel_arg(finat_element, index) @@ -1310,7 +1311,7 @@ def _as_global_kernel_arg_constant(_, self): @_as_global_kernel_arg.register(kernel_args.CellSizesKernelArg) def _as_global_kernel_arg_cell_sizes(_, self): # this mirrors tsfc.kernel_interface.firedrake_loopy.KernelBuilder.set_cell_sizes - ufl_element = ufl.FiniteElement("P", self._mesh.ufl_cell(), 1) + ufl_element = finat.ufl.FiniteElement("P", self._mesh.ufl_cell(), 1) finat_element = create_element(ufl_element) return self._make_dat_global_kernel_arg(finat_element) @@ -1337,7 +1338,7 @@ def _as_global_kernel_arg_cell_facet(_, self): @_as_global_kernel_arg.register(kernel_args.CellOrientationsKernelArg) def _as_global_kernel_arg_cell_orientations(_, self): # this mirrors firedrake.mesh.MeshGeometry.init_cell_orientations - ufl_element = ufl.FiniteElement("DG", cell=self._form.ufl_domain().ufl_cell(), degree=0) + ufl_element = finat.ufl.FiniteElement("DG", cell=self._form.ufl_domain().ufl_cell(), degree=0) finat_element = create_element(ufl_element) return self._make_dat_global_kernel_arg(finat_element) diff --git a/firedrake/assign.py b/firedrake/assign.py index e19ce6406f..8d1b30681a 100644 --- a/firedrake/assign.py +++ b/firedrake/assign.py @@ -5,7 +5,7 @@ from pyadjoint.tape import annotate_tape from pyop2.utils import cached_property import pytools -import ufl +import finat.ufl from ufl.algorithms import extract_coefficients from ufl.constantvalue import as_ufl from ufl.corealg.map_dag import map_expr_dag @@ -155,9 +155,9 @@ def __init__(self, assignee, expression, subset=None): raise ValueError("All functions in the expression must use the same " "mesh as the assignee") - if (subset and type(assignee.ufl_element()) == ufl.MixedElement + if (subset and type(assignee.ufl_element()) == finat.ufl.MixedElement and any(el.family() == "Real" - for el in assignee.ufl_element().sub_elements())): + for el in assignee.ufl_element().sub_elements)): raise ValueError("Subset is not a valid argument for assigning to a mixed " "element including a real element") diff --git a/firedrake/bcs.py b/firedrake/bcs.py index a83c98f7b9..b07ea6f856 100644 --- a/firedrake/bcs.py +++ b/firedrake/bcs.py @@ -5,7 +5,8 @@ import itertools import ufl -from ufl import as_ufl, as_tensor, VectorElement +from ufl import as_ufl, as_tensor +from finat.ufl import VectorElement import finat import pyop2 as op2 @@ -329,12 +330,12 @@ def function_arg(self, g): raise RuntimeError("%r is defined on incompatible FunctionSpace!" % g) self._function_arg = g elif isinstance(g, ufl.classes.Zero): - if g.ufl_shape and g.ufl_shape != self.function_space().ufl_element().value_shape(): + if g.ufl_shape and g.ufl_shape != self.function_space().ufl_element().value_shape: raise ValueError(f"Provided boundary value {g} does not match shape of space") # Special case. Scalar zero for direct Function.assign. self._function_arg = g elif isinstance(g, ufl.classes.Expr): - if g.ufl_shape != self.function_space().ufl_element().value_shape(): + if g.ufl_shape != self.function_space().ufl_element().value_shape: raise RuntimeError(f"Provided boundary value {g} does not match shape of space") try: self._function_arg = firedrake.Function(self.function_space()) diff --git a/firedrake/checkpointing.py b/firedrake/checkpointing.py index 66107e2e3e..477dc07d08 100644 --- a/firedrake/checkpointing.py +++ b/firedrake/checkpointing.py @@ -1,7 +1,7 @@ import functools import pickle from petsc4py.PETSc import ViewerHDF5 -import ufl +import finat.ufl from pyop2 import op2 from pyop2.mpi import COMM_WORLD, internal_comm, decref, MPI from firedrake.cython import hdf5interface as h5i @@ -577,7 +577,7 @@ def save_mesh(self, mesh, distribution_name=None, permutation_name=None): # Save tmesh.layers, which contains (start layer, stop layer)-tuple for each cell # Conceptually, we project these integer pairs onto DG0 vector space of dim=2. cell = base_tmesh.ufl_cell() - element = ufl.VectorElement("DP" if cell.is_simplex() else "DQ", cell, 0, dim=2) + element = finat.ufl.VectorElement("DP" if cell.is_simplex() else "DQ", cell, 0, dim=2) layers_tV = impl.FunctionSpace(base_tmesh, element) self._save_function_space_topology(layers_tV) # Note that _cell_numbering coincides with DG0 section, so we can use tmesh.layers directly. @@ -762,7 +762,7 @@ def _save_function_space_topology(self, tV): path = self._path_to_dms(tmesh.name) if dm_name not in self.require_group(path): if element.family() == "Real": - assert not isinstance(element, (ufl.VectorElement, ufl.TensorElement)) + assert not isinstance(element, (finat.ufl.VectorElement, finat.ufl.TensorElement)) else: dm = self._get_dm_for_checkpointing(tV) topology_dm = tmesh.topology_dm @@ -845,7 +845,7 @@ def _save_function_topology(self, tf, idx=None): tmesh = tV.mesh() element = tV.ufl_element() if element.family() == "Real": - assert not isinstance(element, (ufl.VectorElement, ufl.TensorElement)) + assert not isinstance(element, (finat.ufl.VectorElement, finat.ufl.TensorElement)) dm_name = self._get_dm_name_for_checkpointing(tmesh, element) path = self._path_to_vec(tmesh.name, dm_name, tf.name()) self.require_group(path) @@ -894,7 +894,7 @@ def load_mesh(self, name=DEFAULT_MESH_NAME, reorder=None, distribution_parameter variable_layers = self.get_attr(path, PREFIX_EXTRUDED + "_variable_layers") if variable_layers: cell = base_tmesh.ufl_cell() - element = ufl.VectorElement("DP" if cell.is_simplex() else "DQ", cell, 0, dim=2) + element = finat.ufl.VectorElement("DP" if cell.is_simplex() else "DQ", cell, 0, dim=2) _ = self._load_function_space_topology(base_tmesh, element) base_tmesh_key = self._generate_mesh_key_from_names(base_tmesh.name, base_tmesh._distribution_name, @@ -955,7 +955,7 @@ def load_mesh(self, name=DEFAULT_MESH_NAME, reorder=None, distribution_parameter path = self._path_to_mesh_immersed(tmesh.name, name) if path in self.h5pyfile: cell = tmesh.ufl_cell() - element = ufl.FiniteElement("DP" if cell.is_simplex() else "DQ", cell, 0) + element = finat.ufl.FiniteElement("DP" if cell.is_simplex() else "DQ", cell, 0) cell_orientations_tV = self._load_function_space_topology(tmesh, element) tmesh_key = self._generate_mesh_key_from_names(tmesh.name, tmesh._distribution_name, @@ -1208,7 +1208,7 @@ def _load_function_topology(self, tmesh, element, tf_name, idx=None): self.viewer.pushTimestepping() self.viewer.setTimestep(idx) if element.family() == "Real": - assert not isinstance(element, (ufl.VectorElement, ufl.TensorElement)) + assert not isinstance(element, (finat.ufl.VectorElement, finat.ufl.TensorElement)) value = self.get_attr(path, "_".join([PREFIX, "value" if idx is None else "value_" + str(idx)])) tf.dat.data.itemset(value) else: @@ -1247,10 +1247,10 @@ def _generate_function_space_name(self, V): V_names = [PREFIX + "_function_space"] for Vsub in V: elem = Vsub.ufl_element() - if isinstance(elem, ufl.RestrictedElement): + if isinstance(elem, finat.ufl.RestrictedElement): # RestrictedElement.shortstr() contains '<>|{}'. elem_name = "RestrictedElement(%s,%s)" % (elem.sub_element().shortstr(), elem.restriction_domain()) - elif isinstance(elem, ufl.EnrichedElement): + elif isinstance(elem, finat.ufl.EnrichedElement): # EnrichedElement.shortstr() contains '<>+'. elem_name = "EnrichedElement(%s)" % ",".join(e.shortstr() for e in elem._elements) else: @@ -1274,11 +1274,11 @@ def _get_shared_data_key_for_checkpointing(self, mesh, ufl_element): real_tensorproduct = eutils.is_real_tensor_product_element(finat_element) entity_dofs = finat_element.entity_dofs() nodes_per_entity = tuple(mesh.make_dofs_per_plex_entity(entity_dofs)) - if isinstance(ufl_element, ufl.TensorElement): - shape = ufl_element.reference_value_shape() + if isinstance(ufl_element, finat.ufl.TensorElement): + shape = ufl_element.reference_value_shape block_size = np.product(shape) - elif isinstance(ufl_element, ufl.VectorElement): - shape = ufl_element.value_shape()[:1] + elif isinstance(ufl_element, finat.ufl.VectorElement): + shape = ufl_element.value_shape[:1] block_size = np.product(shape) else: block_size = 1 @@ -1286,7 +1286,7 @@ def _get_shared_data_key_for_checkpointing(self, mesh, ufl_element): def _get_dm_for_checkpointing(self, tV): sd_key = self._get_shared_data_key_for_checkpointing(tV.mesh(), tV.ufl_element()) - if isinstance(tV.ufl_element(), (ufl.VectorElement, ufl.TensorElement)): + if isinstance(tV.ufl_element(), (finat.ufl.VectorElement, finat.ufl.TensorElement)): nodes_per_entity, real_tensorproduct, block_size = sd_key global_numbering = tV.mesh().create_section(nodes_per_entity, real_tensorproduct, block_size=block_size) topology_dm = tV.mesh().topology_dm @@ -1421,6 +1421,7 @@ def _load_ufl_element(self, path, name): globals = {} locals = {} exec("from ufl import *", globals, locals) + exec("from finat.ufl import *", globals, locals) return eval(self.get_attr(path, name + "_repr"), globals, locals) else: return self._unpickle(self.get_attr(path, name)) # backward compat. diff --git a/firedrake/constant.py b/firedrake/constant.py index b4fe0264ae..cac96431ec 100644 --- a/firedrake/constant.py +++ b/firedrake/constant.py @@ -1,5 +1,6 @@ import numpy as np import ufl +import finat.ufl from tsfc.ufl_utils import TSFCConstantMixin from pyop2 import op2 @@ -67,14 +68,18 @@ def __new__(cls, value, domain=None, name=None, count=None): dat, rank, shape = _create_dat(op2.Global, value, domain._comm) - domain = ufl.as_domain(domain) + if not isinstance(domain, ufl.AbstractDomain): + cell = ufl.as_cell(domain) + coordinate_element = finat.ufl.VectorElement("Lagrange", cell, 1, gdim=cell.geometric_dimension) + domain = ufl.Mesh(coordinate_element) + cell = domain.ufl_cell() if rank == 0: - element = ufl.FiniteElement("R", cell, 0) + element = finat.ufl.FiniteElement("R", cell, 0) elif rank == 1: - element = ufl.VectorElement("R", cell, 0, shape[0]) + element = finat.ufl.VectorElement("R", cell, 0, shape[0]) else: - element = ufl.TensorElement("R", cell, 0, shape=shape) + element = finat.ufl.TensorElement("R", cell, 0, shape=shape) R = FunctionSpace(domain, element, name="firedrake.Constant") return Function(R, val=dat).assign(value) diff --git a/firedrake/embedding.py b/firedrake/embedding.py index fc0b744fac..cfb3b3c771 100644 --- a/firedrake/embedding.py +++ b/firedrake/embedding.py @@ -1,32 +1,33 @@ # -*- coding: utf-8 -*- """Module for utility functions for scalable HDF5 I/O.""" +import finat.ufl import ufl def get_embedding_dg_element(element): - cell = element.cell() + cell = element.cell degree = element.degree() family = lambda c: "DG" if c.is_simplex() else "DQ" if isinstance(cell, ufl.TensorProductCell): if type(degree) is int: - scalar_element = ufl.FiniteElement("DQ", cell=cell, degree=degree) + scalar_element = finat.ufl.FiniteElement("DQ", cell=cell, degree=degree) else: - scalar_element = ufl.TensorProductElement(*(ufl.FiniteElement(family(c), cell=c, degree=d) - for (c, d) in zip(cell.sub_cells(), degree))) + scalar_element = finat.ufl.TensorProductElement(*(finat.ufl.FiniteElement(family(c), cell=c, degree=d) + for (c, d) in zip(cell.sub_cells(), degree))) else: - scalar_element = ufl.FiniteElement(family(cell), cell=cell, degree=degree) - shape = element.value_shape() + scalar_element = finat.ufl.FiniteElement(family(cell), cell=cell, degree=degree) + shape = element.value_shape if len(shape) == 0: DG = scalar_element elif len(shape) == 1: shape, = shape - DG = ufl.VectorElement(scalar_element, dim=shape) + DG = finat.ufl.VectorElement(scalar_element, dim=shape) else: - if isinstance(element, ufl.TensorElement): + if isinstance(element, finat.ufl.TensorElement): symmetry = element.symmetry() else: symmetry = None - DG = ufl.TensorElement(scalar_element, shape=shape, symmetry=symmetry) + DG = finat.ufl.TensorElement(scalar_element, shape=shape, symmetry=symmetry) return DG @@ -43,10 +44,10 @@ def get_embedding_element_for_checkpointing(element): def get_embedding_method_for_checkpointing(element): """Return the method used to embed element in dg space.""" - if isinstance(element, (ufl.HDivElement, ufl.HCurlElement, ufl.WithMapping)): + if isinstance(element, (finat.ufl.HDivElement, finat.ufl.HCurlElement, finat.ufl.WithMapping)): return "project" - elif isinstance(element, (ufl.VectorElement, ufl.TensorElement)): - elem, = set(element.sub_elements()) + elif isinstance(element, (finat.ufl.VectorElement, finat.ufl.TensorElement)): + elem, = set(element.sub_elements) return get_embedding_method_for_checkpointing(elem) elif element.family() in ['Lagrange', 'Discontinuous Lagrange', 'Nedelec 1st kind H(curl)', 'Raviart-Thomas', @@ -54,8 +55,8 @@ def get_embedding_method_for_checkpointing(element): 'Q', 'DQ', 'S', 'DPC', 'Real']: return "interpolate" - elif isinstance(element, ufl.TensorProductElement): - methods = [get_embedding_method_for_checkpointing(elem) for elem in element.sub_elements()] + elif isinstance(element, finat.ufl.TensorProductElement): + methods = [get_embedding_method_for_checkpointing(elem) for elem in element.sub_elements] if any(method == "project" for method in methods): return "project" else: diff --git a/firedrake/extrusion_utils.py b/firedrake/extrusion_utils.py index 1eeab7ad84..84c2bf98bd 100644 --- a/firedrake/extrusion_utils.py +++ b/firedrake/extrusion_utils.py @@ -50,7 +50,7 @@ def make_extruded_coords(extruded_topology, base_coords, ext_coords, coordinates on the extruded cell (to write to), the fixed layer height, and the current cell layer. """ - _, vert_space = ext_coords.function_space().ufl_element().sub_elements()[0].sub_elements() + _, vert_space = ext_coords.function_space().ufl_element().sub_elements[0].sub_elements if kernel is None and not (vert_space.degree() == 1 and vert_space.family() in ['Lagrange', 'Discontinuous Lagrange']): diff --git a/firedrake/formmanipulation.py b/firedrake/formmanipulation.py index 7b14f6b8a3..eda7b730a1 100644 --- a/firedrake/formmanipulation.py +++ b/firedrake/formmanipulation.py @@ -125,7 +125,7 @@ def argument(self, o): else: args += [Zero() for j in numpy.ndindex( - V_is[i].ufl_element().value_shape())] + V_is[i].ufl_element().value_shape)] return self._arg_cache.setdefault(o, as_vector(args)) diff --git a/firedrake/functionspace.py b/firedrake/functionspace.py index 19b8321f46..d89d2a2bf7 100644 --- a/firedrake/functionspace.py +++ b/firedrake/functionspace.py @@ -5,6 +5,7 @@ backwards-compatibility, argument checking, and dispatch. """ import ufl +import finat.ufl from pyop2.utils import flatten @@ -20,7 +21,7 @@ @PETSc.Log.EventDecorator() def make_scalar_element(mesh, family, degree, vfamily, vdegree): - """Build a scalar :class:`ufl.FiniteElement`. + """Build a scalar :class:`finat.ufl.FiniteElement`. :arg mesh: The mesh to determine the cell from. :arg family: The finite element family. @@ -31,7 +32,7 @@ def make_scalar_element(mesh, family, degree, vfamily, vdegree): (extruded meshes only). The ``family`` argument may be an existing - :class:`ufl.FiniteElementBase`, in which case all other arguments + :class:`finat.ufl.FiniteElementBase`, in which case all other arguments are ignored and the element is returned immediately. .. note:: @@ -43,55 +44,55 @@ def make_scalar_element(mesh, family, degree, vfamily, vdegree): mesh.init() topology = mesh.topology cell = topology.ufl_cell() - if isinstance(family, ufl.FiniteElementBase): + if isinstance(family, finat.ufl.FiniteElementBase): return family.reconstruct(cell=cell) if isinstance(cell, ufl.TensorProductCell) \ and vfamily is not None and vdegree is not None: - la = ufl.FiniteElement(family, - cell=cell.sub_cells()[0], - degree=degree) + la = finat.ufl.FiniteElement(family, + cell=cell.sub_cells()[0], + degree=degree) # If second element was passed in, use it - lb = ufl.FiniteElement(vfamily, - cell=ufl.interval, - degree=vdegree) + lb = finat.ufl.FiniteElement(vfamily, + cell=ufl.interval, + degree=vdegree) # Now make the TensorProductElement - return ufl.TensorProductElement(la, lb) + return finat.ufl.TensorProductElement(la, lb) else: - return ufl.FiniteElement(family, cell=cell, degree=degree) + return finat.ufl.FiniteElement(family, cell=cell, degree=degree) def check_element(element, top=True): """Run some checks on the provided element. - The :class:`~ufl.classes.VectorElement` and - :class:`~ufl.classes.TensorElement` modifiers must be "outermost" + The :class:`~finat.ufl.VectorElement` and + :class:`~finat.ufl.TensorElement` modifiers must be "outermost" for function space construction to work, excepting that they - should not wrap a :class:`~ufl.classes.MixedElement`. Similarly, - a base :class:`~ufl.classes.MixedElement` must be outermost (it - can contain :class:`~ufl.classes.MixedElement` instances, provided + should not wrap a :class:`~finat.ufl.MixedElement`. Similarly, + a base :class:`~finat.ufl.MixedElement` must be outermost (it + can contain :class:`~finat.ufl.MixedElement` instances, provided they satisfy the other rules). This function checks that. :arg element: The :class:`UFL element - ` to check. + ` to check. :kwarg top: Are we at the top element (in which case the modifier is legal). :returns: ``None`` if the element is legal. :raises ValueError: if the element is illegal. """ - if type(element) in (ufl.BrokenElement, ufl.RestrictedElement, - ufl.HDivElement, ufl.HCurlElement): + if type(element) in (finat.ufl.BrokenElement, finat.ufl.RestrictedElement, + finat.ufl.HDivElement, finat.ufl.HCurlElement): inner = (element._element, ) - elif type(element) is ufl.EnrichedElement: + elif type(element) is finat.ufl.EnrichedElement: inner = element._elements - elif type(element) is ufl.TensorProductElement: - inner = element.sub_elements() - elif isinstance(element, ufl.MixedElement): + elif type(element) is finat.ufl.TensorProductElement: + inner = element.sub_elements + elif isinstance(element, finat.ufl.MixedElement): if not top: raise ValueError("%s modifier must be outermost" % type(element)) else: - inner = element.sub_elements() + inner = element.sub_elements else: return for e in inner: @@ -113,13 +114,13 @@ def FunctionSpace(mesh, family, degree=None, name=None, vfamily=None, (extruded meshes only). The ``family`` argument may be an existing - :class:`ufl.FiniteElementBase`, in which case all other arguments + :class:`finat.ufl.FiniteElementBase`, in which case all other arguments are ignored and the appropriate :class:`.FunctionSpace` is returned. """ element = make_scalar_element(mesh, family, degree, vfamily, vdegree) # Support FunctionSpace(mesh, MixedElement) - if type(element) is ufl.MixedElement: + if type(element) is finat.ufl.MixedElement: return MixedFunctionSpace(element, mesh=mesh, name=name) if mesh.ufl_cell().cellname() == "hexahedron" and \ element.family() not in ["Q", "DQ"]: @@ -154,13 +155,13 @@ def DualSpace(mesh, family, degree=None, name=None, vfamily=None, (extruded meshes only). The ``family`` argument may be an existing - :class:`ufl.FiniteElementBase`, in which case all other arguments + :class:`finat.ufl.FiniteElementBase`, in which case all other arguments are ignored and the appropriate :class:`.FunctionSpace` is returned. """ element = make_scalar_element(mesh, family, degree, vfamily, vdegree) # Support FunctionSpace(mesh, MixedElement) - if type(element) is ufl.MixedElement: + if type(element) is finat.ufl.MixedElement: return MixedFunctionSpace(element, mesh=mesh, name=name) # Check that any Vector/Tensor/Mixed modifiers are outermost. @@ -195,17 +196,17 @@ def VectorFunctionSpace(mesh, family, degree=None, dim=None, (extruded meshes only). The ``family`` argument may be an existing - :class:`ufl.FiniteElementBase`, in which case all other arguments + :class:`finat.ufl.FiniteElementBase`, in which case all other arguments are ignored and the appropriate :class:`.FunctionSpace` is returned. In this case, the provided element must have an empty - :meth:`ufl.FiniteElementBase.value_shape`. + :meth:`finat.ufl.FiniteElementBase.value_shape`. .. note:: The element that you provide need be a scalar element (with empty ``value_shape``), however, it should not be an existing - :class:`~ufl.classes.VectorElement`. If you already have an - existing :class:`~ufl.classes.VectorElement`, you should pass + :class:`~finat.ufl.VectorElement`. If you already have an + existing :class:`~finat.ufl.VectorElement`, you should pass it to :func:`FunctionSpace` directly instead. """ @@ -214,7 +215,7 @@ def VectorFunctionSpace(mesh, family, degree=None, dim=None, dim = mesh.ufl_cell().geometric_dimension() if not isinstance(dim, numbers.Integral) and dim > 0: raise ValueError(f"Can't make VectorFunctionSpace with dim={dim}") - element = ufl.VectorElement(sub_element, dim=dim) + element = finat.ufl.VectorElement(sub_element, dim=dim) return FunctionSpace(mesh, element, name=name) @@ -238,21 +239,21 @@ def TensorFunctionSpace(mesh, family, degree=None, shape=None, (extruded meshes only). The ``family`` argument may be an existing - :class:`~ufl.classes.FiniteElementBase`, in which case all other arguments + :class:`~finat.ufl.FiniteElementBase`, in which case all other arguments are ignored and the appropriate :class:`.FunctionSpace` is returned. In this case, the provided element must have an empty - :meth:`~ufl.classes.FiniteElementBase.value_shape`. + :meth:`~finat.ufl.FiniteElementBase.value_shape`. .. note:: The element that you provide must be a scalar element (with empty ``value_shape``). If you already have an existing - :class:`~ufl.classes.TensorElement`, you should pass it to + :class:`~finat.ufl.TensorElement`, you should pass it to :func:`FunctionSpace` directly instead. """ sub_element = make_scalar_element(mesh, family, degree, vfamily, vdegree) shape = shape or (mesh.ufl_cell().geometric_dimension(),) * 2 - element = ufl.TensorElement(sub_element, shape=shape, symmetry=symmetry) + element = finat.ufl.TensorElement(sub_element, shape=shape, symmetry=symmetry) return FunctionSpace(mesh, element, name=name) @@ -261,24 +262,24 @@ def MixedFunctionSpace(spaces, name=None, mesh=None): """Create a :class:`.MixedFunctionSpace`. :arg spaces: An iterable of constituent spaces, or a - :class:`~ufl.classes.MixedElement`. + :class:`~finat.ufl.MixedElement`. :arg name: An optional name for the mixed function space. :arg mesh: An optional mesh. Must be provided if spaces is a - :class:`~ufl.classes.MixedElement`, ignored otherwise. + :class:`~finat.ufl.MixedElement`, ignored otherwise. """ - if isinstance(spaces, ufl.FiniteElementBase): + if isinstance(spaces, finat.ufl.FiniteElementBase): # Build the spaces if we got a mixed element - assert type(spaces) is ufl.MixedElement and mesh is not None + assert type(spaces) is finat.ufl.MixedElement and mesh is not None sub_elements = [] def rec(eles): for ele in eles: # Only want to recurse into MixedElements - if type(ele) is ufl.MixedElement: - rec(ele.sub_elements()) + if type(ele) is finat.ufl.MixedElement: + rec(ele.sub_elements) else: sub_elements.append(ele) - rec(spaces.sub_elements()) + rec(spaces.sub_elements) spaces = [FunctionSpace(mesh, element) for element in sub_elements] # Check that function spaces are on the same mesh diff --git a/firedrake/functionspacedata.py b/firedrake/functionspacedata.py index 9f7f807103..e9bf789e41 100644 --- a/firedrake/functionspacedata.py +++ b/firedrake/functionspacedata.py @@ -15,7 +15,7 @@ """ import numpy -import ufl +import finat.ufl import finat from decorator import decorator from functools import partial @@ -404,7 +404,7 @@ class FunctionSpaceData(object): @PETSc.Log.EventDecorator() def __init__(self, mesh, ufl_element): - if type(ufl_element) is ufl.MixedElement: + if type(ufl_element) is finat.ufl.MixedElement: raise ValueError("Can't create FunctionSpace for MixedElement") finat_element = create_element(ufl_element) @@ -523,7 +523,7 @@ def get_shared_data(mesh, ufl_element): """ if not isinstance(mesh, mesh_mod.AbstractMeshTopology): raise ValueError("%s is not an AbstractMeshTopology" % mesh) - if not isinstance(ufl_element, ufl.finiteelement.FiniteElementBase): + if not isinstance(ufl_element, finat.ufl.finiteelement.FiniteElementBase): raise ValueError("Can't create function space data from a %s" % type(ufl_element)) return FunctionSpaceData(mesh, ufl_element) diff --git a/firedrake/functionspaceimpl.py b/firedrake/functionspaceimpl.py index 7537d001ac..0a73b73db7 100644 --- a/firedrake/functionspaceimpl.py +++ b/firedrake/functionspaceimpl.py @@ -11,6 +11,7 @@ import numpy import ufl +import finat.ufl from pyop2 import op2, mpi @@ -338,14 +339,14 @@ class FunctionSpace(object): determined from the provided element. :arg mesh: The :func:`~.Mesh` to build the function space on. - :arg element: The :class:`~ufl.classes.FiniteElementBase` describing the + :arg element: The :class:`~finat.ufl.FiniteElementBase` describing the degrees of freedom. :kwarg name: An optional name for this :class:`FunctionSpace`, useful for later identification. The element can be a essentially any - :class:`~ufl.classes.FiniteElementBase`, except for a - :class:`~ufl.classes.MixedElement`, for which one should use the + :class:`~finat.ufl.FiniteElementBase`, except for a + :class:`~finat.ufl.MixedElement`, for which one should use the :class:`MixedFunctionSpace` constructor. To determine whether the space is scalar-, vector- or @@ -364,25 +365,25 @@ class FunctionSpace(object): @PETSc.Log.EventDecorator() def __init__(self, mesh, element, name=None): super(FunctionSpace, self).__init__() - if type(element) is ufl.MixedElement: + if type(element) is finat.ufl.MixedElement: raise ValueError("Can't create FunctionSpace for MixedElement") sdata = get_shared_data(mesh, element) # The function space shape is the number of dofs per node, # hence it is not always the value_shape. Vector and Tensor # element modifiers *must* live on the outside! - if type(element) in {ufl.TensorElement, ufl.VectorElement} \ - or (isinstance(element, ufl.WithMapping) - and type(element.wrapee) in {ufl.TensorElement, ufl.VectorElement}): + if type(element) in {finat.ufl.TensorElement, finat.ufl.VectorElement} \ + or (isinstance(element, finat.ufl.WithMapping) + and type(element.wrapee) in {finat.ufl.TensorElement, finat.ufl.VectorElement}): # The number of "free" dofs is given by reference_value_shape, # not value_shape due to symmetry specifications - rvs = element.reference_value_shape() + rvs = element.reference_value_shape # This requires that the sub element is not itself a # tensor element (which is checked by the top level # constructor of function spaces) shape_element = element - if isinstance(element, ufl.WithMapping): + if isinstance(element, finat.ufl.WithMapping): shape_element = element.wrapee - sub = shape_element.sub_elements()[0].value_shape() + sub = shape_element.sub_elements[0].value_shape self.shape = rvs[:len(rvs) - len(sub)] else: self.shape = () @@ -393,10 +394,10 @@ def __init__(self, mesh, element, name=None): self.rank = len(self.shape) r"""The rank of this :class:`FunctionSpace`. Spaces where the element is scalar-valued (or intrinsically vector-valued) have - rank zero. Spaces built on :class:`~ufl.classes.VectorElement` or - :class:`~ufl.classes.TensorElement` instances have rank equivalent to + rank zero. Spaces built on :class:`~finat.ufl.VectorElement` or + :class:`~finat.ufl.TensorElement` instances have rank equivalent to the number of components of their - :meth:`~ufl.classes.FiniteElementBase.value_shape`.""" + :meth:`~finat.ufl.FiniteElementBase.value_shape`.""" self.value_size = int(numpy.prod(self.shape, dtype=int)) r"""The total number of degrees of freedom at each function @@ -498,7 +499,7 @@ def mesh(self): return self._mesh def ufl_element(self): - r"""The :class:`~ufl.classes.FiniteElementBase` associated with this space.""" + r"""The :class:`~finat.ufl.FiniteElementBase` associated with this space.""" return self.ufl_function_space().ufl_element() def ufl_function_space(self): @@ -703,7 +704,7 @@ def __init__(self, spaces, name=None): for i, s in enumerate(spaces)) mesh, = set(s.mesh() for s in spaces) self._ufl_function_space = ufl.FunctionSpace(mesh.ufl_mesh(), - ufl.MixedElement(*[s.ufl_element() for s in spaces])) + finat.ufl.MixedElement(*[s.ufl_element() for s in spaces])) self.name = name or "_".join(str(s.name) for s in spaces) self._subspaces = {} self._mesh = mesh @@ -724,7 +725,7 @@ def topological(self): return self def ufl_element(self): - r"""The :class:`~ufl.classes.MixedElement` associated with this space.""" + r"""The :class:`~finat.ufl.MixedElement` associated with this space.""" return self.ufl_function_space().ufl_element() def ufl_function_space(self): @@ -968,11 +969,11 @@ def ComponentFunctionSpace(parent, component): :returns: A new :class:`ProxyFunctionSpace` with the component set. """ element = parent.ufl_element() - assert type(element) in frozenset([ufl.VectorElement, ufl.TensorElement]) + assert type(element) in frozenset([finat.ufl.VectorElement, finat.ufl.TensorElement]) if not (0 <= component < parent.value_size): raise IndexError("Invalid component %d. not in [0, %d)" % (component, parent.value_size)) - new = ProxyFunctionSpace(parent.mesh(), element.sub_elements()[0], name=parent.name) + new = ProxyFunctionSpace(parent.mesh(), element.sub_elements[0], name=parent.name) new.identifier = "component" new.component = component new.parent = parent diff --git a/firedrake/interpolation.py b/firedrake/interpolation.py index 9e3d12357f..7c4251347c 100644 --- a/firedrake/interpolation.py +++ b/firedrake/interpolation.py @@ -6,6 +6,7 @@ import FIAT import ufl +import finat.ufl from ufl.algorithms import extract_arguments, extract_coefficients from ufl.algorithms.signature import compute_expression_signature from ufl.domain import extract_unique_domain @@ -346,22 +347,22 @@ def __init__( # input ordering VOM will only contain the points on rank 0! # QUESTION: Should any of the below have annotation turned off? ufl_scalar_element = V_dest.ufl_element() - if ufl_scalar_element.num_sub_elements() and not isinstance( - ufl_scalar_element, ufl.TensorProductElement + if ufl_scalar_element.num_sub_elements and not isinstance( + ufl_scalar_element, finat.ufl.TensorProductElement ): if all( - ufl_scalar_element.sub_elements()[0] == e - for e in ufl_scalar_element.sub_elements() + ufl_scalar_element.sub_elements[0] == e + for e in ufl_scalar_element.sub_elements ): # For a VectorElement or TensorElement the correct # VectorFunctionSpace equivalent is built from the scalar # sub-element. - ufl_scalar_element = ufl_scalar_element.sub_elements()[0] - if ufl_scalar_element.value_shape() != (): + ufl_scalar_element = ufl_scalar_element.sub_elements[0] + if ufl_scalar_element.value_shape != (): raise NotImplementedError( "Can't yet cross-mesh interpolate onto function spaces made from VectorElements or TensorElements made from sub elements with value shape other than ()." ) - elif type(ufl_scalar_element) is ufl.MixedElement: + elif type(ufl_scalar_element) is finat.ufl.MixedElement: # Build and save an interpolator for each sub-element # separately for MixedFunctionSpaces. NOTE: since we can't have # expressions for MixedFunctionSpaces we know that the input @@ -421,7 +422,7 @@ def __init__( # I first point evaluate my expression at these locations, giving a # P0DG function on the VOM. As described in the manual, this is an # interpolation operation. - shape = V_dest.ufl_element().value_shape() + shape = V_dest.ufl_element().value_shape if len(shape) == 0: fs_type = firedrake.FunctionSpace elif len(shape) == 1: @@ -801,7 +802,7 @@ def callable(): else: # Make sure we have an expression of the right length i.e. a value for # each component in the value shape of each function space - dims = [numpy.prod(fs.ufl_element().value_shape(), dtype=int) + dims = [numpy.prod(fs.ufl_element().value_shape, dtype=int) for fs in V] loops = [] if numpy.prod(expr.ufl_shape, dtype=int) != sum(dims): @@ -839,13 +840,13 @@ def _interpolator(V, tensor, expr, subset, arguments, access, bcs=None): if access is op2.READ: raise ValueError("Can't have READ access for output function") - if len(expr.ufl_shape) != len(V.ufl_element().value_shape()): + if len(expr.ufl_shape) != len(V.ufl_element().value_shape): raise RuntimeError('Rank mismatch: Expression rank %d, FunctionSpace rank %d' - % (len(expr.ufl_shape), len(V.ufl_element().value_shape()))) + % (len(expr.ufl_shape), len(V.ufl_element().value_shape))) - if expr.ufl_shape != V.ufl_element().value_shape(): + if expr.ufl_shape != V.ufl_element().value_shape: raise RuntimeError('Shape mismatch: Expression shape %r, FunctionSpace shape %r' - % (expr.ufl_shape, V.ufl_element().value_shape())) + % (expr.ufl_shape, V.ufl_element().value_shape)) # NOTE: The par_loop is always over the target mesh cells. target_mesh = V.ufl_domain() @@ -1058,7 +1059,7 @@ def rebuild_dg(element, expr, rt_var_name): runtime_points_expr = gem.Variable(rt_var_name, (num_points, expr_tdim)) rule_pointset = finat.point_set.UnknownPointSet(runtime_points_expr) try: - expr_fiat_cell = as_fiat_cell(expr.ufl_element().cell()) + expr_fiat_cell = as_fiat_cell(expr.ufl_element().cell) except AttributeError: # expression must be pure function of spatial coordinates so # domain has correct ufl cell diff --git a/firedrake/mesh.py b/firedrake/mesh.py index cb7a202f16..154917782b 100644 --- a/firedrake/mesh.py +++ b/firedrake/mesh.py @@ -3,6 +3,7 @@ import os import sys import ufl +import finat.ufl import FIAT import weakref from collections import OrderedDict, defaultdict @@ -982,7 +983,7 @@ def add_overlap(): # equal their topological dimension. This is reflected in the # corresponding UFL mesh. cell = ufl.Cell(_cells[tdim][nfacets]) - self._ufl_mesh = ufl.Mesh(ufl.VectorElement("Lagrange", cell, 1, dim=cell.topological_dimension())) + self._ufl_mesh = ufl.Mesh(finat.ufl.VectorElement("Lagrange", cell, 1, dim=cell.topological_dimension())) # Set/Generate names to be used when checkpointing. self._distribution_name = distribution_name or _generate_default_mesh_topology_distribution_name(self.topology_dm.comm.size, self._distribution_parameters) self._permutation_name = permutation_name or _generate_default_mesh_topology_permutation_name(reorder) @@ -1269,8 +1270,8 @@ def mark_entities(self, tf, label_value, label_name=None): elem = tV.ufl_element() if tV.mesh() is not self: raise RuntimeError(f"tf must be defined on {self}: {tf.mesh()} is not {self}") - if elem.value_shape() != (): - raise RuntimeError(f"tf must be scalar: {elem.value_shape()} != ()") + if elem.value_shape != (): + raise RuntimeError(f"tf must be scalar: {elem.value_shape} != ()") if elem.family() in {"Discontinuous Lagrange", "DQ"} and elem.degree() == 0: # cells height = 0 @@ -1345,7 +1346,7 @@ def __init__(self, mesh, layers, periodic=False, name=None, tolerance=0.5): self._distribution_parameters = mesh._distribution_parameters self._subsets = {} cell = ufl.TensorProductCell(mesh.ufl_cell(), ufl.interval) - self._ufl_mesh = ufl.Mesh(ufl.VectorElement("Lagrange", cell, 1, dim=cell.topological_dimension())) + self._ufl_mesh = ufl.Mesh(finat.ufl.VectorElement("Lagrange", cell, 1, dim=cell.topological_dimension())) if layers.shape: self.variable_layers = True extents = extnum.layer_extents(self.topology_dm, @@ -1568,7 +1569,7 @@ def __init__(self, swarm, parentmesh, name, reorder, use_cell_dm_marking, tolera tdim = 0 cell = ufl.Cell("vertex") - self._ufl_mesh = ufl.Mesh(ufl.VectorElement("DG", cell, 0, dim=cell.topological_dimension())) + self._ufl_mesh = ufl.Mesh(finat.ufl.VectorElement("DG", cell, 0, dim=cell.topological_dimension())) # Mark OP2 entities and derive the resulting Swarm numbering with PETSc.Log.Event("Mesh: numbering"): @@ -1853,7 +1854,7 @@ def __new__(cls, element): uid = utils._new_uid() mesh.uid = uid cargo = MeshGeometryCargo(uid) - assert isinstance(element, ufl.FiniteElementBase) + assert isinstance(element, finat.ufl.FiniteElementBase) ufl.Mesh.__init__(mesh, element, ufl_id=mesh.uid, cargo=cargo) return mesh @@ -1909,7 +1910,7 @@ def callback(self): self.topology.init() coordinates_fs = functionspace.FunctionSpace(self.topology, self.ufl_coordinate_element()) coordinates_data = dmcommon.reordered_coords(topology.topology_dm, coordinates_fs.dm.getDefaultSection(), - (self.num_vertices(), self.ufl_coordinate_element().cell().geometric_dimension())) + (self.num_vertices(), self.ufl_coordinate_element().cell.geometric_dimension())) coordinates = function.CoordinatelessFunction(coordinates_fs, val=coordinates_data, name=_generate_default_mesh_coordinates_name(self.name)) @@ -2384,11 +2385,11 @@ def make_mesh_from_coordinates(coordinates, name): V = coordinates.function_space() element = coordinates.ufl_element() - if V.rank != 1 or len(element.value_shape()) != 1: + if V.rank != 1 or len(element.value_shape) != 1: raise ValueError("Coordinates must be from a rank-1 FunctionSpace with rank-1 value_shape.") assert V.mesh().ufl_cell().topological_dimension() <= V.value_size # Build coordinate element - cell = element.cell().reconstruct(geometric_dimension=V.value_size) + cell = element.cell.reconstruct(geometric_dimension=V.value_size) element = element.reconstruct(cell=cell) mesh = MeshGeometry.__new__(MeshGeometry, element) @@ -2405,7 +2406,7 @@ def make_mesh_from_mesh_topology(topology, name, comm=COMM_WORLD): cell = topology.ufl_cell() geometric_dim = topology.topology_dm.getCoordinateDim() cell = cell.reconstruct(geometric_dimension=geometric_dim) - element = ufl.VectorElement("Lagrange", cell, 1) + element = finat.ufl.VectorElement("Lagrange", cell, 1) # Create mesh object mesh = MeshGeometry.__new__(MeshGeometry, element) mesh._init_topology(topology) @@ -2689,14 +2690,14 @@ def ExtrudedMesh(mesh, layers, layer_height=None, extrusion_type='uniform', peri if gdim is None: raise RuntimeError("The geometric dimension of the mesh must be specified if a custom extrusion kernel is used") - helement = mesh._coordinates.ufl_element().sub_elements()[0] + helement = mesh._coordinates.ufl_element().sub_elements[0] if extrusion_type == 'radial_hedgehog': helement = helement.reconstruct(family="DG", variant="equispaced") if periodic: - velement = ufl.FiniteElement("DP", ufl.interval, 1, variant="equispaced") + velement = finat.ufl.FiniteElement("DP", ufl.interval, 1, variant="equispaced") else: - velement = ufl.FiniteElement("Lagrange", ufl.interval, 1) - element = ufl.TensorProductElement(helement, velement) + velement = finat.ufl.FiniteElement("Lagrange", ufl.interval, 1) + element = finat.ufl.TensorProductElement(helement, velement) if gdim is None: gdim = mesh.ufl_cell().geometric_dimension() + (extrusion_type == "uniform") @@ -2711,8 +2712,8 @@ def ExtrudedMesh(mesh, layers, layer_height=None, extrusion_type='uniform', peri self._base_mesh = mesh if extrusion_type == "radial_hedgehog": - helement = mesh._coordinates.ufl_element().sub_elements()[0].reconstruct(family="CG") - element = ufl.TensorProductElement(helement, velement) + helement = mesh._coordinates.ufl_element().sub_elements[0].reconstruct(family="CG") + element = finat.ufl.TensorProductElement(helement, velement) fs = functionspace.VectorFunctionSpace(self, element, dim=gdim) self.radial_coordinates = function.Function(fs, name=name + "_radial_coordinates") eutils.make_extruded_coords(topology, mesh._coordinates, self.radial_coordinates, @@ -2869,7 +2870,7 @@ def initialise(mesh, swarm, tdim, name, use_cell_dm_marking): # Geometry tcell = topology.ufl_cell() cell = tcell.reconstruct(geometric_dimension=gdim) - element = ufl.VectorElement("DG", cell, 0) + element = finat.ufl.VectorElement("DG", cell, 0) # Create mesh object vmesh = MeshGeometry.__new__(MeshGeometry, element) vmesh._topology = topology @@ -4027,8 +4028,8 @@ def RelabeledMesh(mesh, indicator_functions, subdomain_ids, **kwargs): plex1.createLabel(label_name) for f, subid in zip(indicator_functions, subdomain_ids): elem = f.topological.function_space().ufl_element() - if elem.value_shape() != (): - raise RuntimeError(f"indicator functions must be scalar: got {elem.value_shape()} != ()") + if elem.value_shape != (): + raise RuntimeError(f"indicator functions must be scalar: got {elem.value_shape} != ()") if elem.family() in {"Discontinuous Lagrange", "DQ"} and elem.degree() == 0: # cells height = 0 diff --git a/firedrake/mg/embedded.py b/firedrake/mg/embedded.py index a13ca96c44..57bd232900 100644 --- a/firedrake/mg/embedded.py +++ b/firedrake/mg/embedded.py @@ -1,5 +1,6 @@ import firedrake import ufl +import finat.ufl import weakref from functools import reduce from enum import IntEnum @@ -55,8 +56,8 @@ def __init__(self, *, native_transfers=None, use_averaging=True): def is_native(self, element): if element in self.native_transfers.keys(): return True - if isinstance(element.cell(), ufl.TensorProductCell) and len(element.sub_elements()) > 0: - return reduce(and_, map(self.is_native, element.sub_elements())) + if isinstance(element.cell, ufl.TensorProductCell) and len(element.sub_elements) > 0: + return reduce(and_, map(self.is_native, element.sub_elements)) return element.family() in native def _native_transfer(self, element, op): @@ -233,8 +234,8 @@ def op(self, source, target, transfer_op): if self.is_native(source_element) and self.is_native(target_element): self._native_transfer(source_element, transfer_op)(source, target) - elif type(source_element) is ufl.MixedElement: - assert type(target_element) is ufl.MixedElement + elif type(source_element) is finat.ufl.MixedElement: + assert type(target_element) is finat.ufl.MixedElement for source_, target_ in zip(source.subfunctions, target.subfunctions): self.op(source_, target_, transfer_op=transfer_op) else: @@ -298,8 +299,8 @@ def restrict(self, source, target): if self.is_native(source_element) and self.is_native(target_element): self._native_transfer(source_element, Op.RESTRICT)(source, target) - elif type(source_element) is ufl.MixedElement: - assert type(target_element) is ufl.MixedElement + elif type(source_element) is finat.ufl.MixedElement: + assert type(target_element) is finat.ufl.MixedElement for source_, target_ in zip(source.subfunctions, target.subfunctions): self.restrict(source_, target_) else: diff --git a/firedrake/mg/kernels.py b/firedrake/mg/kernels.py index 351b97b836..0af9664dfe 100644 --- a/firedrake/mg/kernels.py +++ b/firedrake/mg/kernels.py @@ -20,6 +20,7 @@ import gem.impero_utils as impero_utils import ufl +import finat.ufl import tsfc import tsfc.kernel_interface.firedrake_loopy as firedrake_interface @@ -46,7 +47,7 @@ def to_reference_coordinates(ufl_coordinate_element, parameters=None): # Create FInAT element element = tsfc.finatinterface.create_element(ufl_coordinate_element) - cell = ufl_coordinate_element.cell() + cell = ufl_coordinate_element.cell code = { "geometric_dimension": cell.geometric_dimension(), @@ -217,7 +218,7 @@ def prolong_kernel(expression): assert idx == int(idx) assert hierarchy._meshes[int(idx)].cell_set._extruded key = (("prolong",) - + expression.ufl_element().value_shape() + + expression.ufl_element().value_shape + entity_dofs_key(expression.function_space().finat_element.entity_dofs()) + entity_dofs_key(coordinates.function_space().finat_element.entity_dofs())) try: @@ -298,7 +299,7 @@ def restrict_kernel(Vf, Vc): if Vf.extruded: assert Vc.extruded key = (("restrict",) - + Vf.ufl_element().value_shape() + + Vf.ufl_element().value_shape + entity_dofs_key(Vf.finat_element.entity_dofs()) + entity_dofs_key(Vc.finat_element.entity_dofs()) + entity_dofs_key(coordinates.function_space().finat_element.entity_dofs())) @@ -384,7 +385,7 @@ def inject_kernel(Vf, Vc): else: level_ratio = 1 key = (("inject", level_ratio) - + Vf.ufl_element().value_shape() + + Vf.ufl_element().value_shape + entity_dofs_key(Vc.finat_element.entity_dofs()) + entity_dofs_key(Vf.finat_element.entity_dofs()) + entity_dofs_key(Vc.mesh().coordinates.function_space().finat_element.entity_dofs()) @@ -481,7 +482,7 @@ def set_coefficients(self, coefficients): self.coefficient_split = {} self.kernel_args = [] for i, coefficient in enumerate(coefficients): - if type(coefficient.ufl_element()) == ufl.MixedElement: + if type(coefficient.ufl_element()) == finat.ufl.MixedElement: raise NotImplementedError("Sorry, not for mixed.") self.coefficients.append(coefficient) self.kernel_args.append(self._coefficient(coefficient, "macro_w_%d" % (i, ))) diff --git a/firedrake/mg/utils.py b/firedrake/mg/utils.py index a61c1e2a77..0157d13c77 100644 --- a/firedrake/mg/utils.py +++ b/firedrake/mg/utils.py @@ -3,7 +3,7 @@ from pyop2 import op2 from firedrake.utils import IntType from firedrake.functionspacedata import entity_dofs_key -import ufl +import finat.ufl import firedrake from firedrake.cython import mgimpl as impl @@ -135,9 +135,9 @@ def coarse_cell_to_fine_node_map(Vc, Vf): def physical_node_locations(V): element = V.ufl_element() - if element.value_shape(): - assert isinstance(element, (ufl.VectorElement, ufl.TensorElement)) - element = element.sub_elements()[0] + if element.value_shape: + assert isinstance(element, (finat.ufl.VectorElement, finat.ufl.TensorElement)) + element = element.sub_elements[0] mesh = V.mesh() # This is a defaultdict, so the first time we access the key we # get a fresh dict for the cache. @@ -146,7 +146,7 @@ def physical_node_locations(V): try: return cache[key] except KeyError: - Vc = firedrake.FunctionSpace(mesh, ufl.VectorElement(element)) + Vc = firedrake.FunctionSpace(mesh, finat.ufl.VectorElement(element)) # FIXME: This is unsafe for DG coordinates and CG target spaces. locations = firedrake.interpolate(firedrake.SpatialCoordinate(mesh), Vc) return cache.setdefault(key, locations) diff --git a/firedrake/output.py b/firedrake/output.py index d70fa6965f..0b31120c4c 100644 --- a/firedrake/output.py +++ b/firedrake/output.py @@ -3,6 +3,7 @@ import numpy import os import ufl +import finat.ufl from ufl.domain import extract_unique_domain from itertools import chain from pyop2.mpi import COMM_WORLD, internal_comm, decref @@ -107,7 +108,7 @@ def get_sup_element(*elements, continuous=False, max_degree=None): :returns: A ufl element containing all elements. """ try: - cell, = set(e.cell() for e in elements) + cell, = set(e.cell for e in elements) except ValueError: raise ValueError("All cells must be identical") degree = max(chain(*(as_tuple(e.degree()) for e in elements))) @@ -118,10 +119,9 @@ def get_sup_element(*elements, continuous=False, max_degree=None): family = "DG" else: family = "DQ" - return ufl.FiniteElement(family, - cell=cell, - degree=degree if max_degree is None else max_degree, - variant="equispaced") + return finat.ufl.FiniteElement( + family, cell=cell, degree=degree if max_degree is None else max_degree, + variant="equispaced") @PETSc.Log.EventDecorator() diff --git a/firedrake/plot.py b/firedrake/plot.py index 9acdc35cfe..a8a4e40019 100644 --- a/firedrake/plot.py +++ b/firedrake/plot.py @@ -199,7 +199,7 @@ def _plot_2d_field(method_name, function, *args, complex_component="real", **kwa Q = function.function_space() mesh = Q.mesh() if len(function.ufl_shape) == 1: - element = function.ufl_element().sub_elements()[0] + element = function.ufl_element().sub_elements[0] Q = FunctionSpace(mesh, element) function = interpolate(sqrt(inner(function, function)), Q) @@ -312,7 +312,7 @@ def trisurf(function, *args, complex_component="real", **kwargs): _kwargs.update({"shade": False}) if len(function.ufl_shape) == 1: - element = function.ufl_element().sub_elements()[0] + element = function.ufl_element().sub_elements[0] Q = FunctionSpace(mesh, element) function = interpolate(sqrt(inner(function, function)), Q) @@ -1074,7 +1074,7 @@ def pgfplot(f, filename, degree=1, complex_component='real', print_latex_example raise NotImplementedError(f"Not yet implemented for functions in spatial dimension {dim}") if mesh.extruded: raise NotImplementedError("Not yet implemented for functions on extruded meshes") - if elem.value_shape(): + if elem.value_shape: raise NotImplementedError("Currently only implemeted for scalar functions") coordelem = get_embedding_dg_element(mesh.coordinates.function_space().ufl_element()).reconstruct(degree=degree, variant="equispaced") coordV = FunctionSpace(mesh, coordelem) diff --git a/firedrake/pointeval_utils.py b/firedrake/pointeval_utils.py index ab6df3ddb4..ab2c3b0193 100644 --- a/firedrake/pointeval_utils.py +++ b/firedrake/pointeval_utils.py @@ -1,7 +1,8 @@ import loopy as lp from firedrake.utils import IntType, as_cstr -from ufl import MixedElement, TensorProductCell +from ufl import TensorProductCell +from finat.ufl import MixedElement from ufl.corealg.map_dag import map_expr_dags from ufl.algorithms import extract_arguments, extract_coefficients from ufl.domain import extract_unique_domain diff --git a/firedrake/pointquery_utils.py b/firedrake/pointquery_utils.py index 2653db12c6..03db28fa4b 100644 --- a/firedrake/pointquery_utils.py +++ b/firedrake/pointquery_utils.py @@ -11,6 +11,7 @@ from firedrake.utils import IntType, as_cstr, ScalarType, ScalarType_c, complex_mode, RealType_c import ufl +import finat.ufl from ufl.corealg.map_dag import map_expr_dag import gem @@ -56,7 +57,7 @@ def X_isub_dX(topological_dimension): def is_affine(ufl_element): - return ufl_element.cell().is_simplex() and ufl_element.degree() <= 1 and ufl_element.family() in ["Discontinuous Lagrange", "Lagrange"] + return ufl_element.cell.is_simplex() and ufl_element.degree() <= 1 and ufl_element.family() in ["Discontinuous Lagrange", "Lagrange"] def inside_check(fiat_cell, eps, X="X"): @@ -126,11 +127,11 @@ def init_X(fiat_cell, parameters): @PETSc.Log.EventDecorator() def to_reference_coords_newton_step(ufl_coordinate_element, parameters, x0_dtype="double", dX_dtype=ScalarType): # Set up UFL form - cell = ufl_coordinate_element.cell() + cell = ufl_coordinate_element.cell domain = ufl.Mesh(ufl_coordinate_element) K = ufl.JacobianInverse(domain) x = ufl.SpatialCoordinate(domain) - x0_element = ufl.VectorElement("Real", cell, 0) + x0_element = finat.ufl.VectorElement("Real", cell, 0) x0 = ufl.Coefficient(ufl.FunctionSpace(domain, x0_element)) expr = ufl.dot(K, x - x0) @@ -205,7 +206,7 @@ def compile_coordinate_element(ufl_coordinate_element, contains_eps, parameters= # Create FInAT element element = tsfc.finatinterface.create_element(ufl_coordinate_element) - cell = ufl_coordinate_element.cell() + cell = ufl_coordinate_element.cell extruded = isinstance(cell, ufl.TensorProductCell) code = { diff --git a/firedrake/preconditioners/facet_split.py b/firedrake/preconditioners/facet_split.py index a1d134f206..86c313f0ab 100644 --- a/firedrake/preconditioners/facet_split.py +++ b/firedrake/preconditioners/facet_split.py @@ -38,7 +38,7 @@ def get_permutation(self, V, W): return self._permutation_cache[key] def initialize(self, pc): - from ufl import RestrictedElement, MixedElement, TensorElement, VectorElement + from finat.ufl import RestrictedElement, MixedElement, TensorElement, VectorElement from firedrake import FunctionSpace, TestFunctions, TrialFunctions from firedrake.assemble import allocate_matrix, TwoFormAssembler @@ -65,7 +65,7 @@ def initialize(self, pc): def restrict(ele, restriction_domain): if isinstance(ele, VectorElement): - return type(ele)(restrict(ele._sub_element, restriction_domain), dim=ele.num_sub_elements()) + return type(ele)(restrict(ele._sub_element, restriction_domain), dim=ele.num_sub_elements) elif isinstance(ele, TensorElement): return type(ele)(restrict(ele._sub_element, restriction_domain), shape=ele._shape, symmetry=ele._symmety) else: diff --git a/firedrake/preconditioners/fdm.py b/firedrake/preconditioners/fdm.py index 68317679aa..74c047d053 100644 --- a/firedrake/preconditioners/fdm.py +++ b/firedrake/preconditioners/fdm.py @@ -23,6 +23,7 @@ import firedrake.dmhooks as dmhooks import ufl +import finat.ufl import FIAT import finat import numpy @@ -372,10 +373,10 @@ def assemble_coefficients(self, J, fcp, block_diagonal=True): e = args_J[0].ufl_element() mesh = args_J[0].function_space().mesh() tdim = mesh.topological_dimension() - if isinstance(e, (ufl.VectorElement, ufl.TensorElement)): + if isinstance(e, (finat.ufl.VectorElement, finat.ufl.TensorElement)): e = e._sub_element e = unrestrict_element(e) - sobolev = e.sobolev_space() + sobolev = e.sobolev_space # Replacement rule for the exterior derivative = grad(arg) * eps map_grad = None @@ -414,11 +415,11 @@ def assemble_coefficients(self, J, fcp, block_diagonal=True): qvariant = "fdm_quadrature" elements = [e.reconstruct(variant=qvariant), - ufl.FiniteElement(qfam, cell=mesh.ufl_cell(), degree=qdeg, variant=qvariant)] - elements = list(map(ufl.BrokenElement, elements)) + finat.ufl.FiniteElement(qfam, cell=mesh.ufl_cell(), degree=qdeg, variant=qvariant)] + elements = list(map(finat.ufl.BrokenElement, elements)) if V.shape: - elements = [ufl.TensorElement(ele, shape=V.shape) for ele in elements] - Z = FunctionSpace(mesh, ufl.MixedElement(elements)) + elements = [finat.ufl.TensorElement(ele, shape=V.shape) for ele in elements] + Z = FunctionSpace(mesh, finat.ufl.MixedElement(elements)) # Transform the exterior derivative and the original arguments of J to arguments in Z args = (TestFunctions(Z), TrialFunctions(Z)) @@ -1217,7 +1218,7 @@ def tabulate_exterior_derivative(Vc, Vf, cbcs=[], fbcs=[], comm=None): A11.destroy() if any(is_restricted(ec)) or any(is_restricted(ef)): - scalar_element = lambda e: e._sub_element if isinstance(e, (ufl.TensorElement, ufl.VectorElement)) else e + scalar_element = lambda e: e._sub_element if isinstance(e, (finat.ufl.TensorElement, finat.ufl.VectorElement)) else e fdofs = restricted_dofs(ef, create_element(unrestrict_element(scalar_element(Vf.ufl_element())))) cdofs = restricted_dofs(ec, create_element(unrestrict_element(scalar_element(Vc.ufl_element())))) temp = Dhat @@ -1262,12 +1263,12 @@ def tabulate_exterior_derivative(Vc, Vf, cbcs=[], fbcs=[], comm=None): def restrict_element(ele, restriction_domain): """Get an element that is not restricted and return the restricted element.""" - if isinstance(ele, ufl.VectorElement): - return type(ele)(restrict_element(ele._sub_element, restriction_domain), dim=ele.num_sub_elements()) - elif isinstance(ele, ufl.TensorElement): + if isinstance(ele, finat.ufl.VectorElement): + return type(ele)(restrict_element(ele._sub_element, restriction_domain), dim=ele.num_sub_elements) + elif isinstance(ele, finat.ufl.TensorElement): return type(ele)(restrict_element(ele._sub_element, restriction_domain), shape=ele._shape, symmetry=ele.symmetry()) - elif isinstance(ele, ufl.MixedElement): - return type(ele)(*(restrict_element(e, restriction_domain) for e in ele.sub_elements())) + elif isinstance(ele, finat.ufl.MixedElement): + return type(ele)(*(restrict_element(e, restriction_domain) for e in ele.sub_elements)) else: return ele[restriction_domain] @@ -1275,13 +1276,13 @@ def restrict_element(ele, restriction_domain): def unrestrict_element(ele): """Get an element that might or might not be restricted and return the parent unrestricted element.""" - if isinstance(ele, ufl.VectorElement): - return type(ele)(unrestrict_element(ele._sub_element), dim=ele.num_sub_elements()) - elif isinstance(ele, ufl.TensorElement): + if isinstance(ele, finat.ufl.VectorElement): + return type(ele)(unrestrict_element(ele._sub_element), dim=ele.num_sub_elements) + elif isinstance(ele, finat.ufl.TensorElement): return type(ele)(unrestrict_element(ele._sub_element), shape=ele._shape, symmetry=ele.symmetry()) - elif isinstance(ele, ufl.MixedElement): - return type(ele)(*(unrestrict_element(e) for e in ele.sub_elements())) - elif isinstance(ele, ufl.RestrictedElement): + elif isinstance(ele, finat.ufl.MixedElement): + return type(ele)(*(unrestrict_element(e) for e in ele.sub_elements)) + elif isinstance(ele, finat.ufl.RestrictedElement): return unrestrict_element(ele._element) else: return ele @@ -1390,7 +1391,7 @@ def cell_to_global(lgmap, cell_to_local, cell_index, result=None): V = Vrow bsize = V.value_size - ncomp = V.ufl_element().reference_value_size() + ncomp = V.ufl_element().reference_value_size sdim = (V.finat_element.space_dimension() * bsize) // ncomp # dimension of a single component tdim = V.mesh().topological_dimension() shift = axes_shifts * bsize @@ -1602,7 +1603,7 @@ def assemble_coefficients(self, J, fcp): quad_deg = fcp.get("degree", 2*degree+1) dx = ufl.dx(degree=quad_deg, domain=mesh) family = "Discontinuous Lagrange" if tdim == 1 else "DQ" - DG = ufl.FiniteElement(family, mesh.ufl_cell(), degree=0) + DG = finat.ufl.FiniteElement(family, mesh.ufl_cell(), degree=0) # extract coefficients directly from the bilinear form integrals_J = J.integrals_by_type("cell") @@ -1627,7 +1628,7 @@ def assemble_coefficients(self, J, fcp): # assemble second order coefficient if not isinstance(alpha, ufl.constantvalue.Zero): - Q = FunctionSpace(mesh, ufl.TensorElement(DG, shape=alpha.ufl_shape)) + Q = FunctionSpace(mesh, finat.ufl.TensorElement(DG, shape=alpha.ufl_shape)) tensor = coefficients.setdefault("alpha", Function(Q.dual())) assembly_callables.append(OneFormAssembler(ufl.inner(TestFunction(Q), alpha)*dx, tensor=tensor, form_compiler_parameters=fcp).assemble) @@ -1635,7 +1636,7 @@ def assemble_coefficients(self, J, fcp): # get zero-th order coefficent ref_val = [ufl.variable(t) for t in args_J] if Piola: - dummy_element = ufl.TensorElement(family, cell=mesh.ufl_cell(), degree=1, shape=Piola.ufl_shape) + dummy_element = finat.ufl.TensorElement(family, cell=mesh.ufl_cell(), degree=1, shape=Piola.ufl_shape) dummy_Piola = ufl.Coefficient(ufl.FunctionSpace(mesh, dummy_element)) replace_val = {t: ufl.dot(dummy_Piola, s) for t, s in zip(args_J, ref_val)} else: @@ -1649,14 +1650,14 @@ def assemble_coefficients(self, J, fcp): if Piola: # keep diagonal beta = ufl.diag_vector(beta) - Q = FunctionSpace(mesh, ufl.TensorElement(DG, shape=beta.ufl_shape) if beta.ufl_shape else DG) + Q = FunctionSpace(mesh, finat.ufl.TensorElement(DG, shape=beta.ufl_shape) if beta.ufl_shape else DG) tensor = coefficients.setdefault("beta", Function(Q.dual())) assembly_callables.append(OneFormAssembler(ufl.inner(TestFunction(Q), beta)*dx, tensor=tensor, form_compiler_parameters=fcp).assemble) family = "CG" if tdim == 1 else "DGT" degree = 1 if tdim == 1 else 0 - DGT = ufl.BrokenElement(ufl.FiniteElement(family, cell=mesh.ufl_cell(), degree=degree)) + DGT = finat.ufl.BrokenElement(finat.ufl.FiniteElement(family, cell=mesh.ufl_cell(), degree=degree)) if Piola: # make DGT functions with the second order coefficient # and the Piola tensor for each side of each facet @@ -1672,19 +1673,19 @@ def assemble_coefficients(self, J, fcp): G = ufl.as_tensor([[[G[i, k, j, k] for i in range(G.ufl_shape[0])] for j in range(G.ufl_shape[2])] for k in range(G.ufl_shape[3])]) G = G * abs(ufl.JacobianDeterminant(mesh)) - Q = FunctionSpace(mesh, ufl.TensorElement(DGT, shape=G.ufl_shape)) + Q = FunctionSpace(mesh, finat.ufl.TensorElement(DGT, shape=G.ufl_shape)) tensor = coefficients.setdefault("Gq_facet", Function(Q.dual())) assembly_callables.append(OneFormAssembler(ifacet_inner(TestFunction(Q), G), tensor=tensor, form_compiler_parameters=fcp).assemble) PT = Piola.T - Q = FunctionSpace(mesh, ufl.TensorElement(DGT, shape=PT.ufl_shape)) + Q = FunctionSpace(mesh, finat.ufl.TensorElement(DGT, shape=PT.ufl_shape)) tensor = coefficients.setdefault("PT_facet", Function(Q.dual())) assembly_callables.append(OneFormAssembler(ifacet_inner(TestFunction(Q), PT), tensor=tensor, form_compiler_parameters=fcp).assemble) # make DGT functions with BC flags - shape = V.ufl_element().reference_value_shape() - Q = FunctionSpace(mesh, ufl.TensorElement(DGT, shape=shape) if shape else DGT) + shape = V.ufl_element().reference_value_shape + Q = FunctionSpace(mesh, finat.ufl.TensorElement(DGT, shape=shape) if shape else DGT) test = TestFunction(Q) ref_args = [ufl.variable(t) for t in args_J] diff --git a/firedrake/preconditioners/hiptmair.py b/firedrake/preconditioners/hiptmair.py index af1d1bab27..a1f24841e7 100644 --- a/firedrake/preconditioners/hiptmair.py +++ b/firedrake/preconditioners/hiptmair.py @@ -11,6 +11,7 @@ from ufl.algorithms.ad import expand_derivatives import firedrake.dmhooks as dmhooks import ufl +import finat.ufl __all__ = ("TwoLevelPC", "HiptmairPC") @@ -207,16 +208,16 @@ def coarsen(self, pc): def curl_to_grad(ele): - if isinstance(ele, ufl.VectorElement): - return type(ele)(curl_to_grad(ele._sub_element), dim=ele.num_sub_elements()) - elif isinstance(ele, ufl.TensorElement): - return type(ele)(curl_to_grad(ele._sub_element), shape=ele.value_shape(), symmetry=ele.symmetry()) - elif isinstance(ele, ufl.MixedElement): - return type(ele)(*(curl_to_grad(e) for e in ele.sub_elements())) - elif isinstance(ele, ufl.RestrictedElement): - return ufl.RestrictedElement(curl_to_grad(ele._element), ele.restriction_domain()) + if isinstance(ele, finat.ufl.VectorElement): + return type(ele)(curl_to_grad(ele._sub_element), dim=ele.num_sub_elements) + elif isinstance(ele, finat.ufl.TensorElement): + return type(ele)(curl_to_grad(ele._sub_element), shape=ele.value_shape, symmetry=ele.symmetry()) + elif isinstance(ele, finat.ufl.MixedElement): + return type(ele)(*(curl_to_grad(e) for e in ele.sub_elements)) + elif isinstance(ele, finat.ufl.RestrictedElement): + return finat.ufl.RestrictedElement(curl_to_grad(ele._element), ele.restriction_domain()) else: - cell = ele.cell() + cell = ele.cell family = ele.family() variant = ele.variant() degree = ele.degree() @@ -225,38 +226,38 @@ def curl_to_grad(ele): else: family = "CG" if isinstance(degree, tuple) and isinstance(cell, ufl.TensorProductCell): - cells = ele.cell().sub_cells() - elems = [ufl.FiniteElement(family, cell=c, degree=d, variant=variant) for c, d in zip(cells, degree)] - return ufl.TensorProductElement(*elems, cell=cell) - return ufl.FiniteElement(family, cell=cell, degree=degree, variant=variant) + cells = ele.cell.sub_cells() + elems = [finat.ufl.FiniteElement(family, cell=c, degree=d, variant=variant) for c, d in zip(cells, degree)] + return finat.ufl.TensorProductElement(*elems, cell=cell) + return finat.ufl.FiniteElement(family, cell=cell, degree=degree, variant=variant) def div_to_curl(ele): - if isinstance(ele, ufl.VectorElement): - return type(ele)(div_to_curl(ele._sub_element), dim=ele.num_sub_elements()) - elif isinstance(ele, ufl.TensorElement): - return type(ele)(div_to_curl(ele._sub_element), shape=ele.value_shape(), symmetry=ele.symmetry()) - elif isinstance(ele, ufl.MixedElement): - return type(ele)(*(div_to_curl(e) for e in ele.sub_elements())) - elif isinstance(ele, ufl.RestrictedElement): - return ufl.RestrictedElement(div_to_curl(ele._element), ele.restriction_domain()) - elif isinstance(ele, ufl.EnrichedElement): + if isinstance(ele, finat.ufl.VectorElement): + return type(ele)(div_to_curl(ele._sub_element), dim=ele.num_sub_elements) + elif isinstance(ele, finat.ufl.TensorElement): + return type(ele)(div_to_curl(ele._sub_element), shape=ele.value_shape, symmetry=ele.symmetry()) + elif isinstance(ele, finat.ufl.MixedElement): + return type(ele)(*(div_to_curl(e) for e in ele.sub_elements)) + elif isinstance(ele, finat.ufl.RestrictedElement): + return finat.ufl.RestrictedElement(div_to_curl(ele._element), ele.restriction_domain()) + elif isinstance(ele, finat.ufl.EnrichedElement): return type(ele)(*(div_to_curl(e) for e in reversed(ele._elements))) - elif isinstance(ele, ufl.TensorProductElement): - return type(ele)(*(div_to_curl(e) for e in ele.sub_elements()), cell=ele.cell()) - elif isinstance(ele, ufl.WithMapping): + elif isinstance(ele, finat.ufl.TensorProductElement): + return type(ele)(*(div_to_curl(e) for e in ele.sub_elements), cell=ele.cell) + elif isinstance(ele, finat.ufl.WithMapping): return type(ele)(div_to_curl(ele.wrapee), ele.mapping()) - elif isinstance(ele, ufl.BrokenElement): + elif isinstance(ele, finat.ufl.BrokenElement): return type(ele)(div_to_curl(ele._element)) - elif isinstance(ele, ufl.HDivElement): - return ufl.HCurlElement(div_to_curl(ele._element)) - elif isinstance(ele, ufl.HCurlElement): + elif isinstance(ele, finat.ufl.HDivElement): + return finat.ufl.HCurlElement(div_to_curl(ele._element)) + elif isinstance(ele, finat.ufl.HCurlElement): raise ValueError("Expecting an H(div) element") else: degree = ele.degree() family = ele.family() if family in ["Lagrange", "CG", "Q"]: - family = "DG" if ele.cell().is_simplex() else "DQ" + family = "DG" if ele.cell.is_simplex() else "DQ" degree = degree-1 elif family in ["Discontinuous Lagrange", "DG", "DQ"]: family = "CG" diff --git a/firedrake/preconditioners/patch.py b/firedrake/preconditioners/patch.py index f73245de8d..b5b7737c3e 100644 --- a/firedrake/preconditioners/patch.py +++ b/firedrake/preconditioners/patch.py @@ -13,7 +13,7 @@ from itertools import chain from functools import partial import numpy -from ufl import VectorElement, MixedElement +from finat.ufl import VectorElement, MixedElement from ufl.domain import extract_unique_domain from tsfc.kernel_interface.firedrake_loopy import make_builder from tsfc.ufl_utils import extract_firedrake_constants diff --git a/firedrake/preconditioners/pmg.py b/firedrake/preconditioners/pmg.py index 6bba237504..dd87cb9f5b 100644 --- a/firedrake/preconditioners/pmg.py +++ b/firedrake/preconditioners/pmg.py @@ -18,6 +18,7 @@ import finat import FIAT import ufl +import finat.ufl import loopy import numpy import os @@ -45,7 +46,7 @@ class PMGBase(PCSNESBase): - 'pmg_mg_levels_transfer_mat_type': can be either 'aij' or 'matfree' The p-coarsening is implemented in the `coarsen_element` routine. - This takes in a :class:`ufl.FiniteElement` and either returns a + This takes in a :class:`finat.ufl.FiniteElement` and either returns a new, coarser element, or raises a `ValueError` (if the supplied element should be the coarsest one of the hierarchy). @@ -66,12 +67,12 @@ def coarsen_element(self, ele): Coarsen a given element to form the next problem down in the p-hierarchy. If the supplied element should form the coarsest level of the p-hierarchy, - raise `ValueError`. Otherwise, return a new :class:`ufl.FiniteElement`. + raise `ValueError`. Otherwise, return a new :class:`finat.ufl.FiniteElement`. By default, this does power-of-2 coarsening in polynomial degree until we reach the coarse degree specified through PETSc options (1 by default). - :arg ele: a :class:`ufl.FiniteElement` to coarsen. + :arg ele: a :class:`finat.ufl.FiniteElement` to coarsen. """ degree = PMGBase.max_degree(ele) if degree <= self.coarse_degree: @@ -125,7 +126,7 @@ def initialize(self, obj): while True: try: ele_ = self.coarsen_element(ele) - assert ele_.value_shape() == ele.value_shape() + assert ele_.value_shape == ele.value_shape ele = ele_ except ValueError: break @@ -383,16 +384,16 @@ def create_injection(self, dmc, dmf): @staticmethod def max_degree(ele): - """Return the maximum degree of a :class:`ufl.FiniteElement`""" - if isinstance(ele, (ufl.VectorElement, ufl.TensorElement)): + """Return the maximum degree of a :class:`finat.ufl.FiniteElement`""" + if isinstance(ele, (finat.ufl.VectorElement, finat.ufl.TensorElement)): return PMGBase.max_degree(ele._sub_element) - elif isinstance(ele, (ufl.MixedElement, ufl.TensorProductElement)): - return max(PMGBase.max_degree(sub) for sub in ele.sub_elements()) - elif isinstance(ele, ufl.EnrichedElement): + elif isinstance(ele, (finat.ufl.MixedElement, finat.ufl.TensorProductElement)): + return max(PMGBase.max_degree(sub) for sub in ele.sub_elements) + elif isinstance(ele, finat.ufl.EnrichedElement): return max(PMGBase.max_degree(sub) for sub in ele._elements) - elif isinstance(ele, ufl.WithMapping): + elif isinstance(ele, finat.ufl.WithMapping): return PMGBase.max_degree(ele.wrapee) - elif isinstance(ele, (ufl.HDivElement, ufl.HCurlElement, ufl.BrokenElement, ufl.RestrictedElement)): + elif isinstance(ele, (finat.ufl.HDivElement, finat.ufl.HCurlElement, finat.ufl.BrokenElement, finat.ufl.RestrictedElement)): return PMGBase.max_degree(ele._element) else: degree = ele.degree() @@ -411,29 +412,29 @@ def reconstruct_degree(ele, degree): by the same amount so that the maximum degree is `degree`. This is useful to coarsen spaces like NCF(k) x DQ(k-1). - :arg ele: a :class:`ufl.FiniteElement` to reconstruct, + :arg ele: a :class:`finat.ufl.FiniteElement` to reconstruct, :arg degree: an integer degree. :returns: the reconstructed element """ - if isinstance(ele, ufl.VectorElement): - return type(ele)(PMGBase.reconstruct_degree(ele._sub_element, degree), dim=ele.num_sub_elements()) - elif isinstance(ele, ufl.TensorElement): + if isinstance(ele, finat.ufl.VectorElement): + return type(ele)(PMGBase.reconstruct_degree(ele._sub_element, degree), dim=ele.num_sub_elements) + elif isinstance(ele, finat.ufl.TensorElement): return type(ele)(PMGBase.reconstruct_degree(ele._sub_element, degree), shape=ele._shape, symmetry=ele.symmetry()) - elif isinstance(ele, ufl.EnrichedElement): + elif isinstance(ele, finat.ufl.EnrichedElement): shift = degree - PMGBase.max_degree(ele) return type(ele)(*(PMGBase.reconstruct_degree(e, PMGBase.max_degree(e) + shift) for e in ele._elements)) - elif isinstance(ele, ufl.TensorProductElement): + elif isinstance(ele, finat.ufl.TensorProductElement): shift = degree - PMGBase.max_degree(ele) - return type(ele)(*(PMGBase.reconstruct_degree(e, PMGBase.max_degree(e) + shift) for e in ele.sub_elements()), cell=ele.cell()) - elif isinstance(ele, ufl.MixedElement): + return type(ele)(*(PMGBase.reconstruct_degree(e, PMGBase.max_degree(e) + shift) for e in ele.sub_elements), cell=ele.cell) + elif isinstance(ele, finat.ufl.MixedElement): shift = degree - PMGBase.max_degree(ele) - return type(ele)(*(PMGBase.reconstruct_degree(e, PMGBase.max_degree(e) + shift) for e in ele.sub_elements())) - elif isinstance(ele, ufl.WithMapping): + return type(ele)(*(PMGBase.reconstruct_degree(e, PMGBase.max_degree(e) + shift) for e in ele.sub_elements)) + elif isinstance(ele, finat.ufl.WithMapping): return type(ele)(PMGBase.reconstruct_degree(ele.wrapee, degree), ele.mapping()) - elif isinstance(ele, (ufl.HDivElement, ufl.HCurlElement, ufl.BrokenElement)): + elif isinstance(ele, (finat.ufl.HDivElement, finat.ufl.HCurlElement, finat.ufl.BrokenElement)): return type(ele)(PMGBase.reconstruct_degree(ele._element, degree)) - elif isinstance(ele, ufl.RestrictedElement): + elif isinstance(ele, finat.ufl.RestrictedElement): return type(ele)(PMGBase.reconstruct_degree(ele._element, degree), restriction_domain=ele._restriction_domain) else: return ele.reconstruct(degree=degree) @@ -1062,7 +1063,7 @@ def make_mapping_code(Q, cmapping, fmapping, t_in, t_out): if B: tensor = ufl.dot(B, tensor) if tensor else B if tensor is None: - tensor = ufl.Identity(Q.ufl_element().value_shape()[0]) + tensor = ufl.Identity(Q.ufl_element().value_shape[0]) u = ufl.Coefficient(Q) expr = ufl.dot(tensor, u) @@ -1288,9 +1289,9 @@ def make_blas_kernels(Vf, Vc): mapping_output = make_mapping_code(Qf, cmapping, fmapping, "t0", "t1") in_place_mapping = True except Exception: - qelem = ufl.FiniteElement("DQ", cell=felem.cell(), degree=PMGBase.max_degree(felem)) - if felem.value_shape(): - qelem = ufl.TensorElement(qelem, shape=felem.value_shape(), symmetry=felem.symmetry()) + qelem = finat.ufl.FiniteElement("DQ", cell=felem.cell, degree=PMGBase.max_degree(felem)) + if felem.value_shape: + qelem = finat.ufl.TensorElement(qelem, shape=felem.value_shape, symmetry=felem.symmetry()) Qf = firedrake.FunctionSpace(Vf.mesh(), qelem) mapping_output = make_mapping_code(Qf, cmapping, fmapping, "t0", "t1") @@ -1520,8 +1521,8 @@ def prolongation_matrix_aij(P1, Pk, P1_bcs=[], Pk_bcs=[]): mesh = Pk.mesh() fele = Pk.ufl_element() - if isinstance(fele, ufl.MixedElement) and not isinstance(fele, (ufl.VectorElement, ufl.TensorElement)): - for i in range(fele.num_sub_elements()): + if isinstance(fele, finat.ufl.MixedElement) and not isinstance(fele, (finat.ufl.VectorElement, finat.ufl.TensorElement)): + for i in range(fele.num_sub_elements): Pk_bcs_i = [bc for bc in Pk_bcs if bc.function_space().index == i] P1_bcs_i = [bc for bc in P1_bcs if bc.function_space().index == i] @@ -1564,7 +1565,7 @@ def prolongation_matrix_aij(P1, Pk, P1_bcs=[], Pk_bcs=[]): def prolongation_matrix_matfree(Vc, Vf, Vc_bcs=[], Vf_bcs=[]): fele = Vf.ufl_element() - if isinstance(fele, ufl.MixedElement) and not isinstance(fele, (ufl.VectorElement, ufl.TensorElement)): + if isinstance(fele, finat.ufl.MixedElement) and not isinstance(fele, (finat.ufl.VectorElement, finat.ufl.TensorElement)): ctx = MixedInterpolationMatrix(Vc, Vf, Vc_bcs, Vf_bcs) else: ctx = StandaloneInterpolationMatrix(Vc, Vf, Vc_bcs, Vf_bcs) diff --git a/firedrake/projection.py b/firedrake/projection.py index 4b47273f73..ccb2147d41 100644 --- a/firedrake/projection.py +++ b/firedrake/projection.py @@ -1,5 +1,6 @@ import abc import ufl +import finat.ufl from ufl.domain import extract_unique_domain import firedrake @@ -132,7 +133,7 @@ def A(self): u = firedrake.TrialFunction(self.target.function_space()) v = firedrake.TestFunction(self.target.function_space()) F = self.target.function_space() - mixed = isinstance(F.ufl_element(), ufl.MixedElement) + mixed = isinstance(F.ufl_element(), finat.ufl.MixedElement) if not mixed and isinstance(F.finat_element, HDivTrace): if F.extruded: a = (firedrake.inner(u, v)*firedrake.ds_t @@ -195,7 +196,7 @@ class BasicProjector(ProjectorBase): def rhs_form(self): v = firedrake.TestFunction(self.target.function_space()) F = self.target.function_space() - mixed = isinstance(F.ufl_element(), ufl.MixedElement) + mixed = isinstance(F.ufl_element(), finat.ufl.MixedElement) if not mixed and isinstance(F.finat_element, HDivTrace): # Project onto a trace space by supplying the respective form on the facets. # The measures on the facets differ between extruded and non-extruded mesh. diff --git a/firedrake/slate/slac/kernel_builder.py b/firedrake/slate/slac/kernel_builder.py index d9ddc9ae4c..edf1fabfda 100644 --- a/firedrake/slate/slac/kernel_builder.py +++ b/firedrake/slate/slac/kernel_builder.py @@ -3,7 +3,7 @@ from collections import OrderedDict, namedtuple -from ufl import MixedElement +from finat.ufl import MixedElement import loopy from loopy.symbolic import SubArrayRef diff --git a/firedrake/slate/static_condensation/hybridization.py b/firedrake/slate/static_condensation/hybridization.py index 0f2cad616d..db5328b1c8 100644 --- a/firedrake/slate/static_condensation/hybridization.py +++ b/firedrake/slate/static_condensation/hybridization.py @@ -2,6 +2,7 @@ import numpy as np import ufl +import finat.ufl import firedrake.dmhooks as dmhooks from firedrake.slate.static_condensation.sc_base import SCBase @@ -59,15 +60,15 @@ def initialize(self, pc): if len(V) != 2: raise ValueError("Expecting two function spaces.") - if all(Vi.ufl_element().value_shape() for Vi in V): + if all(Vi.ufl_element().value_shape for Vi in V): raise ValueError("Expecting an H(div) x L2 pair of spaces.") # Automagically determine which spaces are vector and scalar for i, Vi in enumerate(V): - if Vi.ufl_element().sobolev_space().name == "HDiv": + if Vi.ufl_element().sobolev_space.name == "HDiv": self.vidx = i else: - assert Vi.ufl_element().sobolev_space().name == "L2" + assert Vi.ufl_element().sobolev_space.name == "L2" self.pidx = i # Create the space of approximate traces. @@ -87,7 +88,7 @@ def initialize(self, pc): TraceSpace = FunctionSpace(mesh, "HDiv Trace", tdegree) # Break the function spaces and define fully discontinuous spaces - broken_elements = ufl.MixedElement([ufl.BrokenElement(Vi.ufl_element()) for Vi in V]) + broken_elements = finat.ufl.MixedElement([finat.ufl.BrokenElement(Vi.ufl_element()) for Vi in V]) V_d = FunctionSpace(mesh, broken_elements) # Set up the functions for the original, hybridized diff --git a/firedrake/supermeshing.py b/firedrake/supermeshing.py index 585ffb67a8..861d21d5d2 100644 --- a/firedrake/supermeshing.py +++ b/firedrake/supermeshing.py @@ -118,9 +118,9 @@ def likely(cell_A): assert V_A.value_size == V_B.value_size orig_value_size = V_A.value_size if V_A.value_size > 1: - V_A = firedrake.FunctionSpace(mesh_A, V_A.ufl_element().sub_elements()[0]) + V_A = firedrake.FunctionSpace(mesh_A, V_A.ufl_element().sub_elements[0]) if V_B.value_size > 1: - V_B = firedrake.FunctionSpace(mesh_B, V_B.ufl_element().sub_elements()[0]) + V_B = firedrake.FunctionSpace(mesh_B, V_B.ufl_element().sub_elements[0]) assert V_A.value_size == 1 assert V_B.value_size == 1 diff --git a/firedrake/tsfc_interface.py b/firedrake/tsfc_interface.py index 7216e47e83..a9e84a8827 100644 --- a/firedrake/tsfc_interface.py +++ b/firedrake/tsfc_interface.py @@ -15,6 +15,7 @@ import collections import ufl +import finat.ufl from ufl import Form, conj from .ufl_expr import TestFunction @@ -344,7 +345,7 @@ def extract_numbered_coefficients(expr, numbers): orig_coefficients = ufl.algorithms.extract_coefficients(expr) coefficients = [] for coeff in (orig_coefficients[i] for i in numbers): - if type(coeff.ufl_element()) == ufl.MixedElement: + if type(coeff.ufl_element()) == finat.ufl.MixedElement: coefficients.extend(coeff.subfunctions) else: coefficients.append(coeff) diff --git a/firedrake/ufl_expr.py b/firedrake/ufl_expr.py index 98fe617949..d4c101d66f 100644 --- a/firedrake/ufl_expr.py +++ b/firedrake/ufl_expr.py @@ -72,7 +72,7 @@ def reconstruct(self, function_space=None, return self if not isinstance(number, int): raise TypeError(f"Expecting an int, not {number}") - if function_space.ufl_element().value_shape() != self.ufl_element().value_shape(): + if function_space.ufl_element().value_shape != self.ufl_element().value_shape: raise ValueError("Cannot reconstruct an Argument with a different value shape.") return Argument(function_space, number, part=part) @@ -134,7 +134,7 @@ def reconstruct(self, function_space=None, return self if not isinstance(number, int): raise TypeError(f"Expecting an int, not {number}") - if function_space.ufl_element().value_shape() != self.ufl_element().value_shape(): + if function_space.ufl_element().value_shape != self.ufl_element().value_shape: raise ValueError("Cannot reconstruct an Coargument with a different value shape.") return Coargument(function_space, number, part=part) diff --git a/tests/extrusion/test_kernel_intrhs.py b/tests/extrusion/test_kernel_intrhs.py index 674a44fd42..b86c108eb0 100644 --- a/tests/extrusion/test_kernel_intrhs.py +++ b/tests/extrusion/test_kernel_intrhs.py @@ -1,6 +1,6 @@ import numpy as np from firedrake import * -import ufl +import finat.ufl def integrate_rhs(family, degree): @@ -14,9 +14,9 @@ def integrate_rhs(family, degree): mesh = ExtrudedMesh(m, layers, layer_height=0.1) - horiz = ufl.FiniteElement(family, "triangle", degree) - vert = ufl.FiniteElement(family, "interval", degree) - prod = ufl.TensorProductElement(horiz, vert) + horiz = finat.ufl.FiniteElement(family, "triangle", degree) + vert = finat.ufl.FiniteElement(family, "interval", degree) + prod = finat.ufl.TensorProductElement(horiz, vert) fs = FunctionSpace(mesh, prod, name="fs") f = Function(fs) diff --git a/tests/extrusion/test_real_tensorproduct.py b/tests/extrusion/test_real_tensorproduct.py index 2c82d56950..379df06074 100644 --- a/tests/extrusion/test_real_tensorproduct.py +++ b/tests/extrusion/test_real_tensorproduct.py @@ -51,7 +51,7 @@ def solution(variant, fs_kind): @pytest.fixture def tolerance(variant): - return {"linear": 1e-15, "sin": 1e-5}[variant] + return {"linear": 2e-15, "sin": 1e-5}[variant] def test_vertical_average(V, expr, solution, tolerance): @@ -73,7 +73,7 @@ def quadrilateral(request): def test_vertical_average_variable(quadrilateral): """Test computing vertical average on mesh with variable nb of levels""" - tolerance = 1e-14 + tolerance = 2e-14 mesh2d = RectangleMesh(5, 1, 5, 1, quadrilateral=quadrilateral) # construct number of levels @@ -97,7 +97,7 @@ def test_vertical_average_variable(quadrilateral): fs_real = FunctionSpace(mesh, 'DG', 1, vfamily='Real', vdegree=0) f_real = Function(fs_real).project(f) - l2err = l2err = sqrt(assemble(inner((f_real-correct), (f_real-correct))*dx)) + l2err = sqrt(assemble(inner((f_real-correct), (f_real-correct))*dx)) assert abs(l2err) < tolerance diff --git a/tests/multigrid/test_hiptmair.py b/tests/multigrid/test_hiptmair.py index b59022d9c5..cb77d24791 100644 --- a/tests/multigrid/test_hiptmair.py +++ b/tests/multigrid/test_hiptmair.py @@ -49,7 +49,7 @@ def run_riesz_map(V, mat_type): }, } - sobolev = V.ufl_element().sobolev_space() + sobolev = V.ufl_element().sobolev_space assert sobolev in [HCurl, HDiv] d = div if sobolev == HDiv else curl diff --git a/tests/output/test_io_function.py b/tests/output/test_io_function.py index 5ffa073b62..d03a5b417d 100644 --- a/tests/output/test_io_function.py +++ b/tests/output/test_io_function.py @@ -67,7 +67,7 @@ def _get_mesh(cell_type, comm): def _get_expr(V): mesh = V.mesh() dim = mesh.geometric_dimension() - shape = V.ufl_element().value_shape() + shape = V.ufl_element().value_shape if dim == 2: x, y = SpatialCoordinate(mesh) z = x * y diff --git a/tests/output/test_io_mesh.py b/tests/output/test_io_mesh.py index 77f11f7cea..fb729d98c0 100644 --- a/tests/output/test_io_mesh.py +++ b/tests/output/test_io_mesh.py @@ -147,7 +147,6 @@ def test_io_mesh_radial_hedgehog_extrusion(radial_hedgehog_mesh, tmpdir): _test_io_mesh_extrusion(radial_hedgehog_mesh, tmpdir) -@pytest.mark.parallel(nprocs=3) def test_io_mesh_uniform_variable_layers(variable_layer_uniform_mesh, tmpdir, variable_layers=True): _test_io_mesh_extrusion(variable_layer_uniform_mesh, tmpdir) diff --git a/tests/output/test_io_timestepping.py b/tests/output/test_io_timestepping.py index c8628d8aed..c4d730b5c8 100644 --- a/tests/output/test_io_timestepping.py +++ b/tests/output/test_io_timestepping.py @@ -2,6 +2,7 @@ from firedrake import * from pyop2.mpi import COMM_WORLD import ufl +import finat.ufl import os cwd = os.path.abspath(os.path.dirname(__file__)) @@ -14,7 +15,7 @@ def _get_expr(V, i): mesh = V.mesh() element = V.ufl_element() x, y = SpatialCoordinate(mesh) - shape = element.value_shape() + shape = element.value_shape if element.family() == "Real": return 7. + i * i elif shape == (): @@ -37,14 +38,14 @@ def _project(f, expr, method): @pytest.fixture(params=["P1", "BDMF3", "P2-P1", "Real"]) def element(request): if request.param == "P1": - return ufl.FiniteElement("P", ufl.triangle, 1) + return finat.ufl.FiniteElement("P", ufl.triangle, 1) elif request.param == "BDMF3": - return ufl.FiniteElement("BDMF", ufl.triangle, 3) + return finat.ufl.FiniteElement("BDMF", ufl.triangle, 3) elif request.param == "P2-P1": - return ufl.MixedElement(ufl.FiniteElement("P", ufl.triangle, 2), - ufl.FiniteElement("P", ufl.triangle, 1)) + return finat.ufl.MixedElement(finat.ufl.FiniteElement("P", ufl.triangle, 2), + finat.ufl.FiniteElement("P", ufl.triangle, 1)) elif request.param == "Real": - return ufl.FiniteElement("Real", ufl.triangle, 0) + return finat.ufl.FiniteElement("Real", ufl.triangle, 0) @pytest.mark.parallel(nprocs=3) @@ -53,7 +54,7 @@ def test_io_timestepping(element, tmpdir): filename = COMM_WORLD.bcast(filename, root=0) mycolor = (COMM_WORLD.rank > COMM_WORLD.size - 1) comm = COMM_WORLD.Split(color=mycolor, key=COMM_WORLD.rank) - method = "project" if isinstance(element, ufl.MixedElement) else "interpolate" + method = "project" if isinstance(element, finat.ufl.MixedElement) else "interpolate" if mycolor == 0: mesh = Mesh("./docs/notebooks/stokes-control.msh", name=mesh_name, comm=comm) V = FunctionSpace(mesh, element) diff --git a/tests/regression/test_expressions.py b/tests/regression/test_expressions.py index 162c1e601c..9387e52684 100644 --- a/tests/regression/test_expressions.py +++ b/tests/regression/test_expressions.py @@ -295,7 +295,7 @@ def test_assign_with_different_meshes_fails(): def test_assign_vector_const_to_vfs(vcg1): f = Function(vcg1) - c = Constant(range(1, f.ufl_element().value_shape()[0]+1)) + c = Constant(range(1, f.ufl_element().value_shape[0]+1)) f.assign(c) assert np.allclose(f.dat.data_ro, c.dat.data_ro) diff --git a/tests/regression/test_fas_snespatch.py b/tests/regression/test_fas_snespatch.py index ee9e0ef1d4..0f03d57bff 100644 --- a/tests/regression/test_fas_snespatch.py +++ b/tests/regression/test_fas_snespatch.py @@ -172,7 +172,7 @@ def test_snespatch(mesh, CG1, solver_params): f = Constant(1, domain=mesh) F = inner(grad(u), grad(v))*dx - inner(f, v)*dx + inner(u**3 - u, v)*dx - z = zero(CG1.ufl_element().value_shape()) + z = zero(CG1.ufl_element().value_shape) bcs = DirichletBC(CG1, z, "on_boundary") nvproblem = NonlinearVariationalProblem(F, u, bcs=bcs) diff --git a/tests/regression/test_fdm.py b/tests/regression/test_fdm.py index 3ad7db838e..7ad43e216b 100644 --- a/tests/regression/test_fdm.py +++ b/tests/regression/test_fdm.py @@ -85,7 +85,7 @@ def build_riesz_map(V, d): x = SpatialCoordinate(V.mesh()) x -= Constant([0.5]*len(x)) - if V.ufl_element().value_shape() == (): + if V.ufl_element().value_shape == (): u_exact = exp(-10*dot(x, x)) u_bc = u_exact else: @@ -191,7 +191,7 @@ def test_variable_coefficient(mesh): subs = ("on_boundary",) if mesh.cell_set._extruded: subs += ("top", "bottom") - bcs = [DirichletBC(V, zero(V.ufl_element().value_shape()), sub) for sub in subs] + bcs = [DirichletBC(V, zero(V.ufl_element().value_shape), sub) for sub in subs] uh = Function(V) problem = LinearVariationalProblem(a, L, uh, bcs=bcs) @@ -225,7 +225,7 @@ def test_ipdg_direct_solver(fs): mesh = fs.mesh() x = SpatialCoordinate(mesh) gdim = mesh.geometric_dimension() - ncomp = fs.ufl_element().value_size() + ncomp = fs.ufl_element().value_size homogenize = gdim > 2 if homogenize: diff --git a/tests/regression/test_function.py b/tests/regression/test_function.py index eb900055d1..20bb701c40 100644 --- a/tests/regression/test_function.py +++ b/tests/regression/test_function.py @@ -91,7 +91,7 @@ def test_mismatching_shape_interpolation(V): VV = VectorFunctionSpace(V.mesh(), 'CG', 1) f = Function(VV) with pytest.raises(RuntimeError): - f.interpolate(Constant([1] * (VV.ufl_element().value_shape()[0] + 1))) + f.interpolate(Constant([1] * (VV.ufl_element().value_shape[0] + 1))) def test_function_val(V): diff --git a/tests/regression/test_interpolate.py b/tests/regression/test_interpolate.py index 83821a268d..17f62fc488 100644 --- a/tests/regression/test_interpolate.py +++ b/tests/regression/test_interpolate.py @@ -509,7 +509,7 @@ def test_interpolation_tensor_convergence(): V = TensorFunctionSpace(mesh, "RT", 1) x, y = SpatialCoordinate(mesh) - vs = V.ufl_element().value_shape() + vs = V.ufl_element().value_shape expr = as_tensor(np.asarray([ sin(2*pi*x*(i+1))*cos(4*pi*y*i) for i in range(np.prod(vs, dtype=int)) diff --git a/tests/regression/test_interpolate_cross_mesh.py b/tests/regression/test_interpolate_cross_mesh.py index 5b9f08c682..7ddc9b71a8 100644 --- a/tests/regression/test_interpolate_cross_mesh.py +++ b/tests/regression/test_interpolate_cross_mesh.py @@ -350,7 +350,7 @@ def test_interpolate_unitsquare_mixed(): # Can't go from non-mixed to mixed V_src_2 = VectorFunctionSpace(m_src, "CG", 1) - assert V_src_2.ufl_element().value_shape() == V_src.ufl_element().value_shape() + assert V_src_2.ufl_element().value_shape == V_src.ufl_element().value_shape f_src_2 = Function(V_src_2) with pytest.raises(NotImplementedError): interpolate(f_src_2, V_dest) diff --git a/tests/regression/test_interpolate_p3intmoments.py b/tests/regression/test_interpolate_p3intmoments.py index 64304d1f8b..14b25e945c 100644 --- a/tests/regression/test_interpolate_p3intmoments.py +++ b/tests/regression/test_interpolate_p3intmoments.py @@ -9,7 +9,7 @@ from FIAT.polynomial_set import ONPolynomialSet from finat.fiat_elements import ScalarFiatElement from tsfc.finatinterface import convert, as_fiat_cell -import ufl +import finat.ufl ufcint = UFCInterval() @@ -91,13 +91,13 @@ def __init__(self, cell, degree): # Replace the old tsfc.finatinterface.convert dispatch with a new one that # gives the the new FInAT element for P3 on an interval with variant # "interior-moment" -old_convert = convert.dispatch(ufl.FiniteElement) +old_convert = convert.dispatch(finat.ufl.FiniteElement) def temp_convert(element, **kwargs): - if element.family() == "Lagrange" and element.cell() == interval \ + if element.family() == "Lagrange" and element.cell == interval \ and element.degree() == 3 and element.variant() == "interior-moment": - return FInAT_P3IntMoments(as_fiat_cell(element.cell()), element.degree()), set() + return FInAT_P3IntMoments(as_fiat_cell(element.cell), element.degree()), set() else: return old_convert(element, **kwargs) @@ -105,15 +105,15 @@ def temp_convert(element, **kwargs): # Register the new tsfc covert method - remove after tests have run (post yield) @pytest.fixture def add_p3intmoments_tsfc(): - convert.register(ufl.FiniteElement, temp_convert) + convert.register(finat.ufl.FiniteElement, temp_convert) yield - convert.register(ufl.FiniteElement, old_convert) + convert.register(finat.ufl.FiniteElement, old_convert) # Test New Element Dual Evaluation def test_basic_dual_eval_p3intmoments(add_p3intmoments_tsfc): mesh = UnitIntervalMesh(1) - e = ufl.FiniteElement("CG", "interval", 3, variant="interior-moment") + e = finat.ufl.FiniteElement("CG", "interval", 3, variant="interior-moment") V = FunctionSpace(mesh, e) x = SpatialCoordinate(mesh) expr = Constant(1.) diff --git a/tests/regression/test_interpolate_vs_project.py b/tests/regression/test_interpolate_vs_project.py index 6e8cb2f799..6a057cd702 100644 --- a/tests/regression/test_interpolate_vs_project.py +++ b/tests/regression/test_interpolate_vs_project.py @@ -36,7 +36,7 @@ def test_interpolate_vs_project(V): elif dim == 3: x, y, z = SpatialCoordinate(mesh) - shape = V.ufl_element().value_shape() + shape = V.ufl_element().value_shape if dim == 2: if len(shape) == 0: expression = x + y diff --git a/tests/regression/test_p1pc.py b/tests/regression/test_p1pc.py index 75cd838dac..1bdbfe3181 100644 --- a/tests/regression/test_p1pc.py +++ b/tests/regression/test_p1pc.py @@ -36,7 +36,7 @@ def test_p_independence(mesh, expected): L = inner(Constant(1), v)*dx - bcs = DirichletBC(V, zero(V.ufl_element().value_shape()), "on_boundary") + bcs = DirichletBC(V, zero(V.ufl_element().value_shape), "on_boundary") uh = Function(V) problem = LinearVariationalProblem(a, L, uh, bcs=bcs) diff --git a/tests/regression/test_patch_pc.py b/tests/regression/test_patch_pc.py index cba143ee9e..5a70438089 100644 --- a/tests/regression/test_patch_pc.py +++ b/tests/regression/test_patch_pc.py @@ -38,7 +38,7 @@ def test_jacobi_sor_equivalence(mesh, problem_type, multiplicative): R = TensorFunctionSpace(mesh, "CG", 1) V = P*Q*R - shape = V.ufl_element().value_shape() + shape = V.ufl_element().value_shape rhs = numpy.full(shape, 1, dtype=float) u = TrialFunction(V) @@ -48,16 +48,16 @@ def test_jacobi_sor_equivalence(mesh, problem_type, multiplicative): # We also test patch pc with kernel argument compression. i = 1 # only active index f = Function(V) - fval = numpy.full(V.sub(i).ufl_element().value_shape(), 1.0, dtype=float) + fval = numpy.full(V.sub(i).ufl_element().value_shape, 1.0, dtype=float) f.sub(i).interpolate(Constant(fval)) a = (inner(f[i], f[i]) * inner(grad(u), grad(v)))*dx L = inner(Constant(rhs), v)*dx - bcs = [DirichletBC(Q, zero(Q.ufl_element().value_shape()), "on_boundary") + bcs = [DirichletBC(Q, zero(Q.ufl_element().value_shape), "on_boundary") for Q in V.subfunctions] else: a = inner(grad(u), grad(v))*dx L = inner(Constant(rhs), v)*dx - bcs = DirichletBC(V, zero(V.ufl_element().value_shape()), "on_boundary") + bcs = DirichletBC(V, zero(V.ufl_element().value_shape), "on_boundary") uh = Function(V) problem = LinearVariationalProblem(a, L, uh, bcs=bcs) diff --git a/tests/regression/test_patch_precompute_element_tensors.py b/tests/regression/test_patch_precompute_element_tensors.py index bd5f5f1604..15202466f4 100644 --- a/tests/regression/test_patch_precompute_element_tensors.py +++ b/tests/regression/test_patch_precompute_element_tensors.py @@ -26,7 +26,7 @@ def test_patch_precompute_element_tensors(mesh, V): f = Constant((1, 1)) F = inner(grad(u), grad(v))*dx + gamma*inner(div(u), div(v))*dx - inner(f, v)*dx + avg(inner(u, v))*dS - z = zero(V.ufl_element().value_shape()) + z = zero(V.ufl_element().value_shape) bcs = DirichletBC(V, z, "on_boundary") sp = {"mat_type": "matfree", diff --git a/tests/regression/test_vertex_based_limiter.py b/tests/regression/test_vertex_based_limiter.py index c746724104..9e1119fa3b 100644 --- a/tests/regression/test_vertex_based_limiter.py +++ b/tests/regression/test_vertex_based_limiter.py @@ -17,7 +17,7 @@ def mesh(request): def space(m): - element = BrokenElement(m.coordinates.function_space().ufl_element().sub_elements()[0]) + element = BrokenElement(m.coordinates.function_space().ufl_element().sub_elements[0]) return FunctionSpace(m, element) @@ -143,7 +143,7 @@ def test_parallel_limiting(tmpdir): import pickle from firedrake import * mesh = RectangleMesh(10, 4, 5000., 1000.) -element = BrokenElement(mesh.coordinates.function_space().ufl_element().sub_elements()[0]) +element = BrokenElement(mesh.coordinates.function_space().ufl_element().sub_elements[0]) V = FunctionSpace(mesh, element) f = Function(V) x, *_ = SpatialCoordinate(mesh)