示例#1
0
def test_save_vtk_mixed(tempdir):
    mesh = create_unit_cube(MPI.COMM_WORLD, 3, 3, 3)
    P2 = ufl.VectorElement("Lagrange", mesh.ufl_cell(), 1)
    P1 = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 1)
    W = FunctionSpace(mesh, P2 * P1)
    V1 = FunctionSpace(mesh, P1)
    V2 = FunctionSpace(mesh, P2)

    U = Function(W)
    U.sub(0).interpolate(lambda x: np.vstack((x[0], 0.2 * x[1], np.zeros_like(x[0]))))
    U.sub(1).interpolate(lambda x: 0.5 * x[0])

    U1, U2 = Function(V1), Function(V2)
    U1.interpolate(U.sub(1))
    U2.interpolate(U.sub(0))
    U2.name = "u"
    U1.name = "p"

    filename = os.path.join(tempdir, "u.pvd")
    with VTKFile(mesh.comm, filename, "w") as vtk:
        vtk.write_function([U2, U1], 0.)
    with VTKFile(mesh.comm, filename, "w") as vtk:
        vtk.write_function([U1, U2], 0.)

    Up = U.sub(1)
    Up.name = "psub"
    with pytest.raises(RuntimeError):
        with VTKFile(mesh.comm, filename, "w") as vtk:
            vtk.write_function([U2, Up, U1], 0)
    with pytest.raises(RuntimeError):
        with VTKFile(mesh.comm, filename, "w") as vtk:
            vtk.write_function([U.sub(i) for i in range(W.num_sub_spaces)], 0)
示例#2
0
    def __init__(self, value, cell=None, name=None):
        """
        Create constant-valued function with given value.

        *Arguments*
            value
                The value may be either a single scalar value, or a
                tuple/list of values for vector-valued functions, or
                nested lists or a numpy array for tensor-valued
                functions.
            cell
                Optional argument. A :py:class:`Cell
                <ufl.Cell>` which defines the geometrical
                dimensions the Constant is defined for.
            name
                Optional argument. A str which overrules the default
                name of the Constant.

        The data type Constant represents a constant value that is
        unknown at compile-time. Its values can thus be changed
        without requiring re-generation and re-compilation of C++
        code.

        *Examples of usage*

            .. code-block:: python

                p = Constant(pi/4)              # scalar
                C = Constant((0.0, -1.0, 0.0))  # constant vector

        """

        # TODO: Either take mesh instead of cell, or drop cell and let
        # grad(c) be undefined.
        if cell is not None:
            cell = ufl.as_cell(cell)
        ufl_domain = None

        array = numpy.array(value)
        rank = len(array.shape)
        floats = list(map(float, array.flat))

        # Create UFL element and initialize constant
        if rank == 0:
            ufl_element = ufl.FiniteElement("Real", cell, 0)
            cpp.Constant.__init__(self, floats[0])
        elif rank == 1:
            ufl_element = ufl.VectorElement("Real", cell, 0, dim=len(floats))
            cpp.Constant.__init__(self, floats)
        else:
            ufl_element = ufl.TensorElement("Real", cell, 0, shape=array.shape)
            cpp.Constant.__init__(self, list(array.shape), floats)

        # Initialize base classes
        ufl_function_space = ufl.FunctionSpace(ufl_domain, ufl_element)
        ufl.Coefficient.__init__(self, ufl_function_space, count=self.id())

        # Set name as given or automatic
        name = name or "f_%d" % self.count()
        self.rename(name, "a Constant")
示例#3
0
def RectangleMesh(comm,
                  points: typing.List[numpy.array],
                  n: list,
                  cell_type=cpp.mesh.CellType.triangle,
                  ghost_mode=cpp.mesh.GhostMode.shared_facet,
                  diagonal: str = "right"):
    """Create rectangle mesh

    Parameters
    ----------
    comm
        MPI communicator
    points
        List of `Points` representing vertices
    n
        List of number of cells in each direction
    diagonal
        Direction of diagonal

    """
    domain = ufl.Mesh(
        ufl.VectorElement("Lagrange", cpp.mesh.to_string(cell_type), 1))
    cmap = fem.create_coordinate_map(comm, domain)
    mesh = cpp.generation.RectangleMesh.create(comm, points, n, cmap,
                                               ghost_mode, diagonal)
    domain._ufl_cargo = mesh
    mesh._ufl_domain = domain
    return mesh
示例#4
0
 def __init__(self, element):
     cell = element.cell()
     degree = element.degree()
     family = lambda c: "DG" if c.is_simplex() else "DQ"
     if isinstance(cell, ufl.TensorProductCell):
         scalar_element = ufl.TensorProductElement(
             *(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()
     if len(shape) == 0:
         DG = scalar_element
     elif len(shape) == 1:
         shape, = shape
         DG = ufl.VectorElement(scalar_element, dim=shape)
     else:
         DG = ufl.TensorElement(scalar_element, shape=shape)
     self.embedding_element = DG
     self._V_DG_mass = {}
     self._DG_inv_mass = {}
     self._V_approx_inv_mass = {}
     self._V_inv_mass_ksp = {}
     self._DG_work = {}
     self._work_vec = {}
     self._V_dof_weights = {}
示例#5
0
    def monolithic_solve():
        """Monolithic (interleaved) solver"""
        P2_el = ufl.VectorElement("Lagrange", mesh.ufl_cell(), 2)
        P1_el = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 1)
        TH = P2_el * P1_el
        W = dolfinx.FunctionSpace(mesh, TH)
        (u, p) = ufl.TrialFunctions(W)
        (v, q) = ufl.TestFunctions(W)
        a00 = ufl.inner(ufl.grad(u), ufl.grad(v)) * dx
        a01 = ufl.inner(p, ufl.div(v)) * dx
        a10 = ufl.inner(ufl.div(u), q) * dx
        a = a00 + a01 + a10

        p00 = ufl.inner(ufl.grad(u), ufl.grad(v)) * dx
        p11 = ufl.inner(p, q) * dx
        p_form = p00 + p11

        f = dolfinx.Function(W.sub(0).collapse())
        p_zero = dolfinx.Function(W.sub(1).collapse())
        L0 = inner(f, v) * dx
        L1 = inner(p_zero, q) * dx
        L = L0 + L1

        bdofsW0_P2_0 = dolfinx.fem.locate_dofs_topological(
            (W.sub(0), P2), facetdim, bndry_facets0)
        bdofsW0_P2_1 = dolfinx.fem.locate_dofs_topological(
            (W.sub(0), P2), facetdim, bndry_facets1)

        bc0 = dolfinx.DirichletBC(u0, bdofsW0_P2_0, W.sub(0))
        bc1 = dolfinx.DirichletBC(u0, bdofsW0_P2_1, W.sub(0))

        A = dolfinx.fem.assemble_matrix(a, [bc0, bc1])
        A.assemble()
        P = dolfinx.fem.assemble_matrix(p_form, [bc0, bc1])
        P.assemble()

        b = dolfinx.fem.assemble_vector(L)
        dolfinx.fem.apply_lifting(b, [a], [[bc0, bc1]])
        b.ghostUpdate(addv=PETSc.InsertMode.ADD,
                      mode=PETSc.ScatterMode.REVERSE)
        dolfinx.fem.set_bc(b, [bc0, bc1])

        ksp = PETSc.KSP()
        ksp.create(mesh.mpi_comm())
        ksp.setOperators(A, P)
        ksp.setType("minres")
        pc = ksp.getPC()
        pc.setType('lu')

        def monitor(ksp, its, rnorm):
            # print("Num it, rnorm:", its, rnorm)
            pass

        ksp.setTolerances(rtol=1.0e-8, max_it=50)
        ksp.setMonitor(monitor)
        ksp.setFromOptions()
        x = A.createVecRight()
        ksp.solve(b, x)
        assert ksp.getConvergedReason() > 0
        return b.norm(), x.norm(), A.norm(), P.norm()
示例#6
0
def test_mixed_constant_bc(mesh_factory):
    """Test that setting a dirichletbc with on a component of a mixed
    function yields the same result as setting it with a function"""
    func, args = mesh_factory
    mesh = func(*args)
    tdim, gdim = mesh.topology.dim, mesh.geometry.dim
    boundary_facets = locate_entities_boundary(
        mesh, tdim - 1, lambda x: np.ones(x.shape[1], dtype=bool))
    TH = ufl.MixedElement([
        ufl.VectorElement("Lagrange", mesh.ufl_cell(), 2),
        ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 1)
    ])
    W = FunctionSpace(mesh, TH)
    U = Function(W)

    # Apply BC to component of a mixed space using a Constant
    c = Constant(mesh, (PETSc.ScalarType(2), PETSc.ScalarType(2)))
    dofs0 = locate_dofs_topological(W.sub(0), tdim - 1, boundary_facets)
    bc0 = dirichletbc(c, dofs0, W.sub(0))
    u = U.sub(0)
    set_bc(u.vector, [bc0])

    # Apply BC to component of a mixed space using a Function
    ubc1 = u.collapse()
    ubc1.interpolate(lambda x: np.full((gdim, x.shape[1]), 2.0))
    dofs1 = locate_dofs_topological((W.sub(0), ubc1.function_space), tdim - 1,
                                    boundary_facets)
    bc1 = dirichletbc(ubc1, dofs1, W.sub(0))
    U1 = Function(W)
    u1 = U1.sub(0)
    set_bc(u1.vector, [bc1])

    # Check that both approaches yield the same vector
    assert np.allclose(u.x.array, u1.x.array)
示例#7
0
def VectorFunctionSpace(mesh, family, degree=None, dim=None,
                        name=None, vfamily=None, vdegree=None):
    """Create a rank-1 :class:`.FunctionSpace`.

    :arg mesh: The mesh to determine the cell from.
    :arg family: The finite element family.
    :arg degree: The degree of the finite element.
    :arg dim: An optional number of degrees of freedom per function
       space node (defaults to the geometric dimension of the mesh).
    :arg name: An optional name for the function space.
    :arg vfamily: The finite element in the vertical dimension
        (extruded meshes only).
    :arg vdegree: The degree of the element in the vertical dimension
        (extruded meshes only).

    The ``family`` argument may be an existing
    :class:`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`.

    .. 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
       it to :func:`FunctionSpace` directly instead.

    """
    sub_element = make_scalar_element(mesh, family, degree, vfamily, vdegree)
    dim = dim or mesh.ufl_cell().geometric_dimension()
    element = ufl.VectorElement(sub_element, dim=dim)
    return FunctionSpace(mesh, element, name=name)
示例#8
0
def test_cmap_triangle(degree, compile_args):
    """Test triangle cell."""
    cell = ufl.triangle
    element = ufl.VectorElement("Lagrange", cell, degree)
    mesh = ufl.Mesh(element)
    compiled_cmap, module = ffcx.codegeneration.jit.compile_coordinate_maps(
        [mesh], cffi_extra_compile_args=compile_args, cache_dir=".")

    assert compiled_cmap[0].is_affine == (1 if (degree == 1) else 0)
    assert compiled_cmap[0].geometric_dimension == 2
    assert compiled_cmap[0].topological_dimension == 2

    # Reference coordinates X to basis
    phi = np.zeros(((degree + 2) * (degree + 1)) // 2, dtype=np.float64)
    phi_ptr = module.ffi.cast("double *", module.ffi.from_buffer(phi))
    X = np.array([[1 / 3, 1 / 3]], dtype=np.float64)
    X_ptr = module.ffi.cast("double *", module.ffi.from_buffer(X))
    compiled_cmap[0].evaluate_basis_derivatives(phi_ptr, 0, X.shape[0], X_ptr)
    assert np.isclose(sum(phi), 1.0)

    num_entity_dofs = compiled_cmap[0].create_scalar_dofmap().num_entity_dofs

    assert num_entity_dofs[0] == 1
    assert num_entity_dofs[2] == 0
    assert num_entity_dofs[3] == 0

    if degree == 1:
        assert num_entity_dofs[1] == 0
    elif degree == 2:
        assert num_entity_dofs[1] == 1
示例#9
0
def test_cmap_hex(degree, compile_args):
    """Test hexahedron cell"""
    # Assuming FIAT Tensor Product layout of cell.

    cell = ufl.hexahedron
    e = ufl.VectorElement("Lagrange", cell, degree)
    mesh = ufl.Mesh(e)
    compiled_cmap, module = ffcx.codegeneration.jit.compile_coordinate_maps(
        [mesh], cffi_extra_compile_args=compile_args)

    assert compiled_cmap[0].is_affine == 0
    assert compiled_cmap[0].geometric_dimension == 3
    assert compiled_cmap[0].topological_dimension == 3

    # Reference coordinates X to basis
    phi = np.zeros((degree + 1)**3, dtype=np.float64)
    phi_ptr = module.ffi.cast("double *", module.ffi.from_buffer(phi))
    X = np.array([[0.5, 0.5, 0.5]], dtype=np.float64)
    X_ptr = module.ffi.cast("double *", module.ffi.from_buffer(X))
    compiled_cmap[0].evaluate_basis_derivatives(phi_ptr, 0, X.shape[0], X_ptr)
    assert np.isclose(sum(phi), 1.0)

    num_entity_dofs = compiled_cmap[0].create_scalar_dofmap().num_entity_dofs

    assert num_entity_dofs[0] == 1

    if degree == 1:
        assert num_entity_dofs[1] == 0
        assert num_entity_dofs[2] == 0
        assert num_entity_dofs[3] == 0
    elif degree == 2:
        assert num_entity_dofs[1] == 1
        assert num_entity_dofs[2] == 1
        assert num_entity_dofs[3] == 1
示例#10
0
    def __init__(self,
                 mesh,
                 family,
                 degree,
                 dim=None,
                 form_degree=None,
                 constrained_domain=None,
                 restriction=None):
        """Create vector-valued finite element function space.

        Use VectorFunctionSpace if the unknown is a vector field,
        instead of a :py:class:`FunctionSpace
        <dolfin.functions.functionspace.FunctionSpace>` object for
        scalar fields.

        *Arguments*
            mesh (:py:class:`Mesh <dolfin.cpp.Mesh>`)
                the mesh
            family (string)
                a string specifying the element family, see
                :py:class:`FunctionSpace
                <dolfin.functions.functionspace.FunctionSpace>` for
                alternatives.
            degree (int)
                the (polynomial) degree of the element.
            dim (int)
                an optional argument specifying the number of components.
            form_degree (int)
                an optional argument specifying the degree of the
                k-form (used for FEEC notation)

        If the dim argument is not provided, the dimension will be
        deduced from the dimension of the mesh.

        *Example of usage*

            .. code-block:: python

                V = VectorFunctionSpace(mesh, "CG", 1)

        """

        # Get Mesh or Restriction from Domain or Domain from Mesh or
        # Restriction
        ufl_domain, mesh = _analyse_mesh_argument(mesh)

        # Create element
        element = ufl.VectorElement(family,
                                    ufl_domain,
                                    degree,
                                    dim=dim,
                                    form_degree=form_degree)
        if restriction is not None:
            element = element[restriction]

        # Initialize base class
        FunctionSpaceBase.__init__(self,
                                   mesh,
                                   element,
                                   constrained_domain=constrained_domain)
示例#11
0
def test_save_2d_mixed(tempdir):
    mesh = UnitCubeMesh(MPI.COMM_WORLD, 3, 3, 3)

    P2 = ufl.VectorElement("Lagrange", mesh.ufl_cell(), 2)
    P1 = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 1)
    TH = P2 * P1
    W = FunctionSpace(mesh, TH)

    def vec_func(x):
        vals = np.zeros((3, x.shape[1]))
        vals[0] = x[0]
        vals[1] = 0.2 * x[1]
        return vals

    def scal_func(x):
        return 0.5 * x[0]

    U = Function(W)
    U.sub(0).interpolate(vec_func)
    U.sub(1).interpolate(scal_func)
    U.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD)

    filename = os.path.join(tempdir, "u.pvd")
    with VTKFile(mesh.mpi_comm(), filename, "w") as vtk:
        vtk.write_function([U.sub(i) for i in range(W.num_sub_spaces())], 0.)
示例#12
0
def test_collision_2nd_order_triangle():
    points = np.array([[0, 0], [1, 0], [0, 1], [0.65, 0.65], [0, 0.5], [0.5, 0]])
    cells = np.array([[0, 1, 2, 3, 4, 5]])
    cell = ufl.Cell("triangle", geometric_dimension=2)
    domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell, 2))
    mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain)

    # Sample points along an interior line of the domain. The last point
    # is outside the simplex made by the vertices.
    sample_points = np.array([[0.1, 0.3, 0], [0.2, 0.5, 0], [0.6, 0.6, 0]])

    # Create boundingboxtree
    tree = geometry.BoundingBoxTree(mesh, mesh.geometry.dim)
    for point in sample_points:
        colliding_cell = geometry.compute_colliding_cells(tree, mesh, point, 1)
        assert(len(colliding_cell) == 1)

    # Check if there is a point on the linear approximation of the
    # curved facet
    def line_through_points(p0, p1):
        return lambda x: (p1[1] - p0[1]) / (p1[0] - p0[0]) * (x - p0[0]) + p0[1]
    line_func = line_through_points(points[2], points[3])
    point = np.array([0.2, line_func(0.2), 0])
    # Point inside 2nd order geometry, outside linear approximation
    # Usefull for debugging on a later stage
    # point = np.array([0.25, 0.89320760, 0])
    distance = cpp.geometry.squared_distance(mesh, mesh.topology.dim - 1, 2, point)
    assert np.isclose(distance, 0)
示例#13
0
def test_mixed_interpolation(cell_type, order):
    """Test that interpolation is correct in a MixedElement."""
    mesh = one_cell_mesh(cell_type)
    tdim = mesh.topology.dim

    A = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), order)
    B = ufl.VectorElement("Lagrange", mesh.ufl_cell(), order)

    V = FunctionSpace(mesh, ufl.MixedElement([A, B]))
    v = Function(V)

    if tdim == 1:

        def f(x):
            return (x[0]**order, 2 * x[0])
    elif tdim == 2:

        def f(x):
            return (x[1], 2 * x[0]**order, 3 * x[1])
    else:

        def f(x):
            return (x[1], 2 * x[0]**order, 3 * x[2], 4 * x[0])

    v.interpolate(f)
    points = [random_point_in_cell(cell_type) for count in range(5)]
    cells = [0 for count in range(5)]
    values = v.eval(points, cells)

    for p, v in zip(points, values):
        assert np.allclose(v, f(p))
示例#14
0
def test_vector_element(compile_args):
    ufl_element = ufl.VectorElement("Lagrange", ufl.triangle, 1)
    jit_compiled_elements, module, code = ffcx.codegeneration.jit.compile_elements(
        [ufl_element], cffi_extra_compile_args=compile_args)
    ufc_element, ufc_dofmap = jit_compiled_elements[0]

    assert ufc_element.topological_dimension == 2
    assert ufc_element.geometric_dimension == 2
    assert ufc_element.space_dimension == 6
    assert ufc_element.value_rank == 1
    assert ufc_element.value_shape[0] == 2
    assert ufc_element.value_size == 2
    assert ufc_element.reference_value_rank == 1
    assert ufc_element.reference_value_shape[0] == 2
    assert ufc_element.reference_value_size == 2
    assert ufc_element.block_size == 2
    assert ufc_element.num_sub_elements == 2

    assert ufc_dofmap.block_size == 2
    assert ufc_dofmap.num_global_support_dofs == 0
    assert ufc_dofmap.num_global_support_dofs == 0
    assert ufc_dofmap.num_element_support_dofs == 3
    assert ufc_dofmap.num_entity_dofs[0] == 1
    assert ufc_dofmap.num_entity_dofs[1] == 0
    assert ufc_dofmap.num_entity_dofs[2] == 0
    assert ufc_dofmap.num_entity_dofs[3] == 0
    for v in range(3):
        vals = np.zeros(1, dtype=np.int32)
        vals_ptr = module.ffi.cast("int *", module.ffi.from_buffer(vals))
        ufc_dofmap.tabulate_entity_dofs(vals_ptr, 0, v)
        assert vals[0] == v
    assert ufc_dofmap.num_sub_dofmaps == 2
示例#15
0
def create_rectangle(comm: _MPI.Comm,
                     points: typing.List[np.array],
                     n: list,
                     cell_type=CellType.triangle,
                     ghost_mode=GhostMode.shared_facet,
                     partitioner=_cpp.mesh.create_cell_partitioner(),
                     diagonal: DiagonalType = DiagonalType.right) -> Mesh:
    """Create rectangle mesh

    Args:
        comm: MPI communicator
        points: Coordinates of the lower-left and upper-right corners of the
            rectangle
        n: Number of cells in each direction
        cell_type: Mesh cell type
        ghost_mode: Ghost mode used in the mesh partitioning
        partitioner: Function that computes the parallel distribution of
            cells across MPI ranks
        diagonal: Direction of diagonal of triangular meshes. The
            options are ``left``, ``right``, ``crossed``, ``left/right``,
            ``right/left``.

    Returns:
        A mesh of a rectangle

    """
    domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell_type.name, 1))
    mesh = _cpp.mesh.create_rectangle(comm, points, n, cell_type, ghost_mode,
                                      partitioner, diagonal)
    return Mesh.from_cpp(mesh, domain)
示例#16
0
def test_triangle_mesh(order):
    points = []
    points += [[i / order, 0] for i in range(order + 1)]
    for j in range(1, order):
        points += [[i / order + 0.1, j / order] for i in range(order + 1 - j)]
    points += [[0, 1]]

    def coord_to_vertex(x, y):
        return y * (2 * order + 3 - y) // 2 + x

    # Define a cell using dolfin ordering
    cell = [coord_to_vertex(i, j) for i, j in [(0, 0), (order, 0), (0, order)]]
    if order > 1:
        for i in range(1, order):
            cell.append(coord_to_vertex(order - i, i))
        for i in range(1, order):
            cell.append(coord_to_vertex(0, i))
        for i in range(1, order):
            cell.append(coord_to_vertex(i, 0))

        for j in range(1, order):
            for i in range(1, order - j):
                cell.append(coord_to_vertex(i, j))

    domain = ufl.Mesh(
        ufl.VectorElement("Lagrange",
                          ufl.Cell("triangle", geometric_dimension=2), order))

    check_cell_volume(points, cell, domain, 0.5)
示例#17
0
def create_box(
    comm: _MPI.Comm,
    points: typing.List[np.array],
    n: list,
    cell_type=CellType.tetrahedron,
    ghost_mode=GhostMode.shared_facet,
    partitioner=_cpp.mesh.create_cell_partitioner()
) -> Mesh:
    """Create box mesh

    Args:
        comm: MPI communicator
        points: Coordinates of the 'lower-left' and 'upper-right'
            corners of the box
        n: List of cells in each direction
        cell_type: The cell type
        ghost_mode: The ghost mode used in the mesh partitioning
        partitioner: Function that computes the parallel distribution of
            cells across MPI ranks

    Returns:
        A mesh of a box domain

    """
    domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell_type.name, 1))
    mesh = _cpp.mesh.create_box(comm, points, n, cell_type, ghost_mode,
                                partitioner)
    return Mesh.from_cpp(mesh, domain)
示例#18
0
def test_volume_quadrilateralR3(coordinates):
    x = numpy.array(coordinates, dtype=numpy.float64)
    cells = numpy.array([[0, 1, 2, 3]], dtype=numpy.int32)
    domain = ufl.Mesh(ufl.VectorElement("Lagrange", "quadrilateral", 1))
    mesh = create_mesh(MPI.COMM_SELF, cells, x, domain)
    mesh.topology.create_connectivity_all()
    assert cpp.mesh.volume_entities(mesh, [0], mesh.topology.dim) == 1.0
示例#19
0
def one_cell_mesh(cell_type):
    if cell_type == CellType.interval:
        points = np.array([[-1.], [2.]])
    if cell_type == CellType.triangle:
        points = np.array([[-1., -1.], [2., 0.], [0., 0.5]])
    elif cell_type == CellType.tetrahedron:
        points = np.array([[-1., -1., -1.], [2., 0., 0.], [0., 0.5, 0.], [0., 0., 1.]])
    elif cell_type == CellType.quadrilateral:
        points = np.array([[-1., 0.], [1., 0.], [-1., 1.5], [1., 1.5]])
    elif cell_type == CellType.hexahedron:
        points = np.array([[-1., -0.5, 0.], [1., -0.5, 0.], [-1., 1.5, 0.],
                           [1., 1.5, 0.], [0., -0.5, 1.], [1., -0.5, 1.],
                           [-1., 1.5, 1.], [1., 1.5, 1.]])
    num_points = len(points)

    # Randomly number the points and create the mesh
    order = list(range(num_points))
    random.shuffle(order)
    ordered_points = np.zeros(points.shape)
    for i, j in enumerate(order):
        ordered_points[j] = points[i]
    cells = np.array([order])

    domain = ufl.Mesh(ufl.VectorElement("Lagrange", cpp.mesh.to_string(cell_type), 1))
    mesh = create_mesh(MPI.COMM_WORLD, cells, ordered_points, domain)

    mesh.topology.create_connectivity_all()
    return mesh
示例#20
0
def create_submesh(mesh, dim, entities):
    submesh, vertex_map, geom_map = _cpp.mesh.create_submesh(mesh, dim, entities)
    submesh_ufl_cell = ufl.Cell(submesh.topology.cell_name(),
                                geometric_dimension=submesh.geometry.dim)
    # FIXME Don't hard code degree (and maybe Lagrange?)
    submesh_domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell=submesh_ufl_cell, degree=1))
    return (Mesh.from_cpp(submesh, submesh_domain), vertex_map, geom_map)
示例#21
0
def BoxMesh(comm,
            points: typing.List[numpy.array],
            n: list,
            cell_type=cpp.mesh.CellType.tetrahedron,
            ghost_mode=cpp.mesh.GhostMode.shared_facet,
            partitioner=cpp.mesh.partition_cells_graph):
    """Create box mesh

    Parameters
    ----------
    comm
        MPI communicator
    points
        List of points representing vertices
    n
        List of cells in each direction

    """
    domain = ufl.Mesh(
        ufl.VectorElement("Lagrange", cpp.mesh.to_string(cell_type), 1))
    mesh = cpp.generation.create_box_mesh(comm, points, n, cell_type,
                                          ghost_mode, partitioner)
    domain._ufl_cargo = mesh
    mesh._ufl_domain = domain
    return mesh
示例#22
0
def xtest_tetrahedron_integral(space_type, space_order):
    domain = ufl.Mesh(ufl.VectorElement("Lagrange", "tetrahedron", 1))
    temp_points = np.array([[-1., 0., -1.], [0., 0., 0.], [1., 0., 1.],
                            [0., 1., 0.], [0., 0., 1.]])

    for repeat in range(10):
        order = [i for i, j in enumerate(temp_points)]
        shuffle(order)
        points = np.zeros(temp_points.shape)
        for i, j in enumerate(order):
            points[j] = temp_points[i]

        cells = []
        for cell in [[0, 1, 3, 4], [1, 2, 3, 4]]:
            # Randomly number the cell
            cell_order = list(range(4))
            shuffle(cell_order)
            cells.append([order[cell[i]] for i in cell_order])

        mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain)
        V = FunctionSpace(mesh, (space_type, space_order))
        Vvec = VectorFunctionSpace(mesh, ("P", 1))
        dofs = [i for i in V.dofmap.cell_dofs(0) if i in V.dofmap.cell_dofs(1)]

        for d in dofs:
            v = Function(V)
            v.vector[:] = [1 if i == d else 0 for i in range(V.dim)]
            if space_type in ["RT", "BDM"]:
                # Hdiv
                def normal(x):
                    values = np.zeros((3, x.shape[1]))
                    values[0] = [1 for i in values[0]]
                    return values

                n = Function(Vvec)
                n.interpolate(normal)
                form = ufl.inner(ufl.jump(v), n) * ufl.dS
            elif space_type in ["N1curl", "N2curl"]:
                # Hcurl
                def tangent1(x):
                    values = np.zeros((3, x.shape[1]))
                    values[1] = [1 for i in values[1]]
                    return values

                def tangent2(x):
                    values = np.zeros((3, x.shape[1]))
                    values[2] = [1 for i in values[2]]
                    return values

                t1 = Function(Vvec)
                t1.interpolate(tangent1)
                t2 = Function(Vvec)
                t2.interpolate(tangent1)
                form = ufl.inner(ufl.jump(v), t1) * ufl.dS
                form += ufl.inner(ufl.jump(v), t2) * ufl.dS
            else:
                form = ufl.jump(v) * ufl.dS

            value = fem.assemble_scalar(form)
            assert np.isclose(value, 0)
示例#23
0
def test_assemble_manifold():
    """Test assembly of poisson problem on a mesh with topological dimension 1
    but embedded in 2D (gdim=2).
    """
    points = numpy.array([[0.0, 0.0], [0.2, 0.0], [0.4, 0.0], [0.6, 0.0],
                          [0.8, 0.0], [1.0, 0.0]],
                         dtype=numpy.float64)
    cells = numpy.array([[0, 1], [1, 2], [2, 3], [3, 4], [4, 5]],
                        dtype=numpy.int32)
    cell = ufl.Cell("interval", geometric_dimension=points.shape[1])
    domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell, 1))
    mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain)
    assert mesh.geometry.dim == 2
    assert mesh.topology.dim == 1

    U = dolfinx.FunctionSpace(mesh, ("P", 1))

    u, v = ufl.TrialFunction(U), ufl.TestFunction(U)
    w = dolfinx.Function(U)

    a = ufl.inner(ufl.grad(u), ufl.grad(v)) * ufl.dx(mesh)
    L = ufl.inner(1.0, v) * ufl.dx(mesh)

    bcdofs = dolfinx.fem.locate_dofs_geometrical(
        U, lambda x: numpy.isclose(x[0], 0.0))
    bcs = [dolfinx.DirichletBC(w, bcdofs)]
    A = dolfinx.fem.assemble_matrix(a, bcs)
    A.assemble()

    b = dolfinx.fem.assemble_vector(L)
    dolfinx.fem.apply_lifting(b, [a], [bcs])
    dolfinx.fem.set_bc(b, bcs)

    assert numpy.isclose(b.norm(), 0.41231)
    assert numpy.isclose(A.norm(), 25.0199)
示例#24
0
    def _process_args(cls,
                      mesh,
                      family,
                      degree=None,
                      dim=None,
                      vfamily=None,
                      vdegree=None,
                      **kwargs):
        # VectorFunctionSpace dimension defaults to the geometric dimension of the mesh.
        dim = dim or mesh.ufl_cell().geometric_dimension()

        if isinstance(mesh, mesh_t.ExtrudedMesh) and isinstance(
                family, ufl.OuterProductElement):
            element = ufl.OuterProductVectorElement(family, dim=dim)
        elif isinstance(mesh, mesh_t.ExtrudedMesh
                        ) and vfamily is not None and vdegree is not None:
            la = ufl.FiniteElement(family,
                                   domain=mesh._old_mesh.ufl_cell(),
                                   degree=degree)
            lb = ufl.FiniteElement(vfamily,
                                   domain=ufl.Cell("interval", 1),
                                   degree=vdegree)
            element = ufl.OuterProductVectorElement(la, lb, dim=dim)
        else:
            element = ufl.VectorElement(family,
                                        domain=mesh.ufl_cell(),
                                        degree=degree,
                                        dim=dim)
        return (mesh, mesh, element), dict(kwargs, dim=dim)
示例#25
0
def test_cmap_hex(degree, compile_args):
    """Test hexahedron cell"""

    cell = ufl.hexahedron
    e = ufl.VectorElement("Lagrange", cell, degree)
    mesh = ufl.Mesh(e)
    compiled_cmap, module = ffcx.codegeneration.jit.compile_coordinate_maps(
        [mesh], cffi_extra_compile_args=compile_args)

    assert compiled_cmap[0].is_affine == 0
    assert compiled_cmap[0].geometric_dimension == 3
    assert compiled_cmap[0].topological_dimension == 3

    num_entity_dofs = compiled_cmap[0].create_scalar_dofmap().num_entity_dofs

    assert num_entity_dofs[0] == 1

    if degree == 1:
        assert num_entity_dofs[1] == 0
        assert num_entity_dofs[2] == 0
        assert num_entity_dofs[3] == 0
    elif degree == 2:
        assert num_entity_dofs[1] == 1
        assert num_entity_dofs[2] == 1
        assert num_entity_dofs[3] == 1
示例#26
0
def create_boundary_mesh(mesh, comm, orient=False):
    """
    Create a mesh consisting of all exterior facets of a mesh
    Input:
      mesh   - The mesh
      comm   - The MPI communicator
      orient - Boolean flag for reorientation of facets to have
               consistent outwards-pointing normal (default: True)
    Output:
      bmesh - The boundary mesh
      bmesh_to_geometry - Map from cells of the boundary mesh
                          to the geometry of the original mesh
    """
    ext_facets = cpp.mesh.exterior_facet_indices(mesh)
    boundary_geometry = cpp.mesh.entities_to_geometry(mesh,
                                                      mesh.topology.dim - 1,
                                                      ext_facets, orient)
    facet_type = cpp.mesh.to_string(
        cpp.mesh.cell_entity_type(mesh.topology.cell_type,
                                  mesh.topology.dim - 1))
    facet_cell = ufl.Cell(facet_type, geometric_dimension=mesh.geometry.dim)
    degree = mesh.ufl_domain().ufl_coordinate_element().degree()
    ufl_domain = ufl.Mesh(ufl.VectorElement("Lagrange", facet_cell, degree))
    bmesh = create_mesh(comm, boundary_geometry, mesh.geometry.x, ufl_domain)
    return bmesh, boundary_geometry
示例#27
0
    def read_mesh(self,
                  ghost_mode=cpp.mesh.GhostMode.shared_facet,
                  name="mesh",
                  xpath="/Xdmf/Domain"):
        # Read mesh data from file
        cell_shape, cell_degree = super().read_cell_type(name, xpath)
        cells = super().read_topology_data(name, xpath)
        x = super().read_geometry_data(name, xpath)

        # Construct the geometry map
        cell = ufl.Cell(cpp.mesh.to_string(cell_shape),
                        geometric_dimension=x.shape[1])
        domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell, cell_degree))

        # Build the mesh
        cmap = cpp.fem.CoordinateElement(cell_shape, cell_degree)
        mesh = cpp.mesh.create_mesh(self.comm(),
                                    cpp.graph.AdjacencyList_int64(cells), cmap,
                                    x, ghost_mode,
                                    cpp.mesh.partition_cells_graph)
        mesh.name = name
        domain._ufl_cargo = mesh
        mesh._ufl_domain = domain

        return mesh
示例#28
0
def create_interval(
    comm: _MPI.Comm,
    nx: int,
    points: list,
    ghost_mode=GhostMode.shared_facet,
    partitioner=_cpp.mesh.create_cell_partitioner()
) -> Mesh:
    """Create an interval mesh

    Args:
        comm: MPI communicator
        nx: Number of cells
        points: Coordinates of the end points
        ghost_mode: Ghost mode used in the mesh partitioning. Options
            are `GhostMode.none' and `GhostMode.shared_facet`.
        partitioner: Partitioning function to use for determining the
            parallel distribution of cells across MPI ranks

    Returns:
        An interval mesh

    """
    domain = ufl.Mesh(ufl.VectorElement("Lagrange", "interval", 1))
    mesh = _cpp.mesh.create_interval(comm, nx, points, ghost_mode, partitioner)
    return Mesh.from_cpp(mesh, domain)
示例#29
0
def test_higher_order_coordinate_map(points, celltype, order):
    """Computes physical coordinates of a cell, based on the coordinate map."""
    print(celltype)
    cells = np.array([range(len(points))])
    domain = ufl.Mesh(ufl.VectorElement("Lagrange", cpp.mesh.to_string(celltype), order))
    mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain)

    V = FunctionSpace(mesh, ("Lagrange", 2))
    X = V.element.interpolation_points()
    coord_dofs = mesh.geometry.dofmap
    x_g = mesh.geometry.x
    cmap = mesh.geometry.cmap

    x_coord_new = np.zeros([len(points), mesh.geometry.dim])

    i = 0
    for node in range(len(points)):
        x_coord_new[i] = x_g[coord_dofs.links(0)[node], :mesh.geometry.dim]
        i += 1
    x = cmap.push_forward(X, x_coord_new)

    assert np.allclose(x[:, 0], X[:, 0])
    assert np.allclose(x[:, 1], 2 * X[:, 1])

    if mesh.geometry.dim == 3:
        assert np.allclose(x[:, 2], 3 * X[:, 2])
示例#30
0
def test_custom_quadrature(compile_args):
    ve = ufl.VectorElement("P", "triangle", 1)
    mesh = ufl.Mesh(ve)

    e = ufl.FiniteElement("P", mesh.ufl_cell(), 2)
    V = ufl.FunctionSpace(mesh, e)
    u, v = ufl.TrialFunction(V), ufl.TestFunction(V)

    points = [[0.0, 0.0], [1.0, 0.0], [0.0, 1.0], [0.5, 0.5], [0.0, 0.5], [0.5, 0.0]]
    weights = [1 / 12] * 6
    a = u * v * ufl.dx(metadata={"quadrature_rule": "custom",
                                 "quadrature_points": points, "quadrature_weights": weights})

    forms = [a]
    compiled_forms, module = ffcx.codegeneration.jit.compile_forms(forms, cffi_extra_compile_args=compile_args)

    ffi = cffi.FFI()
    form = compiled_forms[0][0]
    default_integral = form.create_cell_integral(-1)

    A = np.zeros((6, 6), dtype=np.float64)
    w = np.array([], dtype=np.float64)
    c = np.array([], dtype=np.float64)

    coords = np.array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0], dtype=np.float64)
    default_integral.tabulate_tensor(
        ffi.cast("double *", A.ctypes.data),
        ffi.cast("double *", w.ctypes.data),
        ffi.cast("double *", c.ctypes.data),
        ffi.cast("double *", coords.ctypes.data), ffi.NULL, ffi.NULL, 0)

    # Check that A is diagonal
    assert np.count_nonzero(A - np.diag(np.diagonal(A))) == 0