Example #1
0
    def __init__(self, mesh, layers, layer_height=None, extrusion_type='uniform', kernel=None, gdim=None):
        # A cache of function spaces that have been built on this mesh
        self._cache = {}
        mesh.init()
        self._old_mesh = mesh
        if layers < 1:
            raise RuntimeError("Must have at least one layer of extruded cells (not %d)" % layers)
        # All internal logic works with layers of base mesh (not layers of cells)
        self._layers = layers + 1
        self.parent = mesh.parent
        self.uid = mesh.uid
        self.name = mesh.name
        self._plex = mesh._plex
        self._plex_renumbering = mesh._plex_renumbering
        self._cell_numbering = mesh._cell_numbering
        self._entity_classes = mesh._entity_classes

        interior_f = self._old_mesh.interior_facets
        self._interior_facets = _Facets(self, interior_f.classes,
                                        "interior",
                                        interior_f.facet_cell,
                                        interior_f.local_facet_number)
        exterior_f = self._old_mesh.exterior_facets
        self._exterior_facets = _Facets(self, exterior_f.classes,
                                        "exterior",
                                        exterior_f.facet_cell,
                                        exterior_f.local_facet_number,
                                        exterior_f.markers,
                                        unique_markers=exterior_f.unique_markers)

        self.ufl_cell_element = ufl.FiniteElement("Lagrange",
                                                  domain=mesh.ufl_cell(),
                                                  degree=1)
        self.ufl_interval_element = ufl.FiniteElement("Lagrange",
                                                      domain=ufl.Cell("interval", 1),
                                                      degree=1)

        self.fiat_base_element = fiat_utils.fiat_from_ufl_element(self.ufl_cell_element)
        self.fiat_vert_element = fiat_utils.fiat_from_ufl_element(self.ufl_interval_element)

        fiat_element = FIAT.tensor_finite_element.TensorFiniteElement(self.fiat_base_element, self.fiat_vert_element)

        if extrusion_type == "uniform":
            # *must* add a new dimension
            self._ufl_cell = ufl.OuterProductCell(mesh.ufl_cell(), ufl.Cell("interval", 1), gdim=mesh.ufl_cell().geometric_dimension() + 1)

        elif extrusion_type in ("radial", "radial_hedgehog"):
            # do not allow radial extrusion if tdim = gdim
            if mesh.ufl_cell().geometric_dimension() == mesh.ufl_cell().topological_dimension():
                raise RuntimeError("Cannot radially-extrude a mesh with equal geometric and topological dimension")
            # otherwise, all is fine, so make cell
            self._ufl_cell = ufl.OuterProductCell(mesh.ufl_cell(), ufl.Cell("interval", 1))

        else:
            # check for kernel
            if kernel is None:
                raise RuntimeError("If the custom extrusion_type is used, a kernel must be provided")
            # otherwise, use the gdim that was passed in
            if gdim is None:
                raise RuntimeError("The geometric dimension of the mesh must be specified if a custom extrusion kernel is used")
            self._ufl_cell = ufl.OuterProductCell(mesh.ufl_cell(), ufl.Cell("interval", 1), gdim=gdim)

        self._ufl_domain = ufl.Domain(self.ufl_cell(), data=self)
        flat_temp = fiat_utils.FlattenedElement(fiat_element)

        # Calculated dofs_per_column from flattened_element and layers.
        # The mirrored elements have to be counted only once.
        # Then multiply by layers and layers - 1 accordingly.
        self.dofs_per_column = eutils.compute_extruded_dofs(fiat_element, flat_temp.entity_dofs(),
                                                            layers)

        # Compute Coordinates of the extruded mesh
        if layer_height is None:
            # Default to unit
            layer_height = 1.0 / layers

        if extrusion_type == 'radial_hedgehog':
            hfamily = "DG"
        else:
            hfamily = mesh.coordinates.element().family()
        hdegree = mesh.coordinates.element().degree()

        self._coordinate_fs = functionspace.VectorFunctionSpace(self, hfamily,
                                                                hdegree,
                                                                vfamily="CG",
                                                                vdegree=1)

        self.coordinates = function.Function(self._coordinate_fs)
        self._ufl_domain = ufl.Domain(self.coordinates)
        eutils.make_extruded_coords(self, layer_height, extrusion_type=extrusion_type,
                                    kernel=kernel)
        if extrusion_type == "radial_hedgehog":
            fs = functionspace.VectorFunctionSpace(self, "CG", hdegree, vfamily="CG", vdegree=1)
            self.radial_coordinates = function.Function(fs)
            eutils.make_extruded_coords(self, layer_height, extrusion_type="radial",
                                        output_coords=self.radial_coordinates)

        # Build a new ufl element for this function space with the
        # correct domain.  This is necessary since this function space
        # is in the cache and will be picked up by later
        # VectorFunctionSpace construction.
        self._coordinate_fs._ufl_element = self._coordinate_fs.ufl_element().reconstruct(domain=self.ufl_domain())
        # HACK alert!
        # Replace coordinate Function by one that has a real domain on it (but don't copy values)
        self.coordinates = function.Function(self._coordinate_fs, val=self.coordinates.dat)
        # Add subdomain_data to the measure objects we store with
        # the mesh.  These are weakrefs for consistency with the
        # "global" measure objects
        self._dx = ufl.Measure('cell', subdomain_data=weakref.ref(self.coordinates))
        self._ds = ufl.Measure('exterior_facet', subdomain_data=weakref.ref(self.coordinates))
        self._dS = ufl.Measure('interior_facet', subdomain_data=weakref.ref(self.coordinates))
        self._ds_t = ufl.Measure('exterior_facet_top', subdomain_data=weakref.ref(self.coordinates))
        self._ds_b = ufl.Measure('exterior_facet_bottom', subdomain_data=weakref.ref(self.coordinates))
        self._ds_v = ufl.Measure('exterior_facet_vert', subdomain_data=weakref.ref(self.coordinates))
        self._dS_h = ufl.Measure('interior_facet_horiz', subdomain_data=weakref.ref(self.coordinates))
        self._dS_v = ufl.Measure('interior_facet_vert', subdomain_data=weakref.ref(self.coordinates))
        # Set the subdomain_data on all the default measures to this
        # coordinate field.  We don't set the domain on the measure
        # since this causes an uncollectable reference in the global
        # space (dx is global).  Furthermore, it's never used anyway.
        for measure in [ufl.ds, ufl.dS, ufl.dx, ufl.ds_t, ufl.ds_b, ufl.ds_v, ufl.dS_h, ufl.dS_v]:
            measure._subdomain_data = weakref.ref(self.coordinates)
Example #2
0
    def __init__(self, mesh, layers, kernel=None, layer_height=None, extrusion_type='uniform'):
        # A cache of function spaces that have been built on this mesh
        self._cache = {}
        if kernel is None and extrusion_type is None:
            raise RuntimeError("Please provide a kernel or a preset extrusion_type ('uniform' or 'radial') for extruding the mesh")
        self._old_mesh = mesh
        if layers < 1:
            raise RuntimeError("Must have at least one layer of extruded cells (not %d)" % layers)
        # All internal logic works with layers of base mesh (not layers of cells)
        self._layers = layers + 1
        self._cells = mesh._cells
        self.parent = mesh.parent
        self.uid = mesh.uid
        self.name = mesh.name
        self._plex = mesh._plex
        self._plex_renumbering = mesh._plex_renumbering
        self._cell_numbering = mesh._cell_numbering
        self._cell_closure = mesh._cell_closure

        interior_f = self._old_mesh.interior_facets
        self._interior_facets = _Facets(self, interior_f.classes,
                                        "interior",
                                        interior_f.facet_cell,
                                        interior_f.local_facet_number)
        exterior_f = self._old_mesh.exterior_facets
        self._exterior_facets = _Facets(self, exterior_f.classes,
                                        "exterior",
                                        exterior_f.facet_cell,
                                        exterior_f.local_facet_number,
                                        exterior_f.markers)

        self.ufl_cell_element = ufl.FiniteElement("Lagrange",
                                                  domain=mesh._ufl_cell,
                                                  degree=1)
        self.ufl_interval_element = ufl.FiniteElement("Lagrange",
                                                      domain=ufl.Cell("interval", 1),
                                                      degree=1)

        self.fiat_base_element = fiat_utils.fiat_from_ufl_element(self.ufl_cell_element)
        self.fiat_vert_element = fiat_utils.fiat_from_ufl_element(self.ufl_interval_element)

        fiat_element = FIAT.tensor_finite_element.TensorFiniteElement(self.fiat_base_element, self.fiat_vert_element)

        self._ufl_cell = ufl.OuterProductCell(mesh._ufl_cell, ufl.Cell("interval", 1))

        self._ufl_domain = ufl.Domain(self.ufl_cell(), data=self)
        flat_temp = fiat_element.flattened_element()

        # Calculated dofs_per_column from flattened_element and layers.
        # The mirrored elements have to be counted only once.
        # Then multiply by layers and layers - 1 accordingly.
        self.dofs_per_column = eutils.compute_extruded_dofs(fiat_element, flat_temp.entity_dofs(),
                                                            layers)

        #Compute Coordinates of the extruded mesh
        if layer_height is None:
            # Default to unit
            layer_height = 1.0 / layers

        self._coordinate_fs = functionspace.VectorFunctionSpace(self, mesh._coordinate_fs.ufl_element().family(),
                                                                mesh._coordinate_fs.ufl_element().degree(),
                                                                vfamily="CG",
                                                                vdegree=1)

        self.coordinates = function.Function(self._coordinate_fs)
        self._ufl_domain = ufl.Domain(self.coordinates)
        eutils.make_extruded_coords(self, layer_height, extrusion_type=extrusion_type,
                                    kernel=kernel)
        # Build a new ufl element for this function space with the
        # correct domain.  This is necessary since this function space
        # is in the cache and will be picked up by later
        # VectorFunctionSpace construction.
        self._coordinate_fs._ufl_element = self._coordinate_fs.ufl_element().reconstruct(domain=self.ufl_domain())
        # HACK alert!
        # Replace coordinate Function by one that has a real domain on it (but don't copy values)
        self.coordinates = function.Function(self._coordinate_fs, val=self.coordinates.dat)
        self._dx = ufl.Measure('cell', domain=self, subdomain_data=self.coordinates)
        self._ds = ufl.Measure('exterior_facet', domain=self, subdomain_data=self.coordinates)
        self._dS = ufl.Measure('interior_facet', domain=self, subdomain_data=self.coordinates)
        self._ds_t = ufl.Measure('exterior_facet_top', domain=self, subdomain_data=self.coordinates)
        self._ds_b = ufl.Measure('exterior_facet_bottom', domain=self, subdomain_data=self.coordinates)
        self._ds_v = ufl.Measure('exterior_facet_vert', domain=self, subdomain_data=self.coordinates)
        self._dS_h = ufl.Measure('interior_facet_horiz', domain=self, subdomain_data=self.coordinates)
        self._dS_v = ufl.Measure('interior_facet_vert', domain=self, subdomain_data=self.coordinates)
        # Set the subdomain_data on all the default measures to this coordinate field.
        for measure in [ufl.ds, ufl.dS, ufl.dx, ufl.ds_t, ufl.ds_b, ufl.ds_v, ufl.dS_h, ufl.dS_v]:
            measure._subdomain_data = self.coordinates
            measure._domain = self.ufl_domain()