示例#1
0
def test_clear_sub_map_data_vector(mesh):
    mesh = UnitSquareMesh(8, 8)
    P1 = FiniteElement("Lagrange", mesh.ufl_cell(), 1)
    W = FunctionSpace(mesh, P1 * P1)

    # Check block size
    assert W.dofmap.index_map.block_size == 2

    W.dofmap.clear_sub_map_data()
    with pytest.raises(RuntimeError):
        W0 = W.sub(0)
        assert (W0)
    with pytest.raises(RuntimeError):
        W1 = W.sub(1)
        assert (W1)
示例#2
0
def test_tabulate_dofs(mesh_factory):
    func, args = mesh_factory
    mesh = func(*args)
    W0 = FiniteElement("Lagrange", mesh.ufl_cell(), 1)
    W1 = VectorElement("Lagrange", mesh.ufl_cell(), 1)
    W = FunctionSpace(mesh, W0 * W1)

    L0 = W.sub(0)
    L1 = W.sub(1)
    L01 = L1.sub(0)
    L11 = L1.sub(1)

    for i in range(mesh.num_cells()):
        dofs0 = L0.dofmap.cell_dofs(i)
        dofs1 = L01.dofmap.cell_dofs(i)
        dofs2 = L11.dofmap.cell_dofs(i)
        dofs3 = L1.dofmap.cell_dofs(i)
        assert len(np.intersect1d(dofs0, dofs1)) == 0
        assert len(np.intersect1d(dofs0, dofs2)) == 0
        assert len(np.intersect1d(dofs1, dofs2)) == 0
        assert np.array_equal(np.append(dofs1, dofs2), dofs3)
示例#3
0
def test_tabulate_coord_periodic(mesh_factory):
    def periodic_boundary(x):
        return x[0] < np.finfo(float).eps

    func, args = mesh_factory
    mesh = func(*args)

    V = FiniteElement("Lagrange", mesh.ufl_cell(), 1)
    Q = VectorElement("Lagrange", mesh.ufl_cell(), 1)
    W = V * Q

    V = FunctionSpace(mesh, V, constrained_domain=periodic_boundary)
    W = FunctionSpace(mesh, W, constrained_domain=periodic_boundary)

    L0 = W.sub(0)
    L1 = W.sub(1)
    L01 = L1.sub(0)
    L11 = L1.sub(1)

    sdim = V.element.space_dimension()
    coord0 = np.zeros((sdim, 2), dtype="d")
    coord1 = np.zeros((sdim, 2), dtype="d")
    coord2 = np.zeros((sdim, 2), dtype="d")
    coord3 = np.zeros((sdim, 2), dtype="d")

    map = mesh.topology.index_map(mesh.topology.dim)
    num_cells = map.size_local + map.num_ghosts
    for i in range(num_cells):
        cell = MeshEntity(mesh, mesh.topology.dim, i)
        coord0 = V.element.tabulate_dof_coordinates(cell)
        coord1 = L0.element.tabulate_dof_coordinates(cell)
        coord2 = L01.element.tabulate_dof_coordinates(cell)
        coord3 = L11.element.tabulate_dof_coordinates(cell)
        coord4 = L1.element.tabulate_dof_coordinates(cell)

        assert (coord0 == coord1).all()
        assert (coord0 == coord2).all()
        assert (coord0 == coord3).all()
        assert (coord4[:sdim] == coord0).all()
        assert (coord4[sdim:] == coord0).all()
示例#4
0
def test_tabulate_dofs(mesh_factory):
    func, args = mesh_factory
    mesh = func(*args)
    W0 = FiniteElement("Lagrange", mesh.ufl_cell(), 1)
    W1 = VectorElement("Lagrange", mesh.ufl_cell(), 1)
    W = FunctionSpace(mesh, W0 * W1)

    L0 = W.sub(0)
    L1 = W.sub(1)
    L01 = L1.sub(0)
    L11 = L1.sub(1)

    map = mesh.topology.index_map(mesh.topology.dim)
    num_cells = map.size_local + map.num_ghosts
    for c in range(num_cells):
        dofs0 = L0.dofmap.cell_dofs(c)
        dofs1 = L01.dofmap.cell_dofs(c)
        dofs2 = L11.dofmap.cell_dofs(c)
        dofs3 = L1.dofmap.cell_dofs(c)
        assert len(np.intersect1d(dofs0, dofs1)) == 0
        assert len(np.intersect1d(dofs0, dofs2)) == 0
        assert len(np.intersect1d(dofs1, dofs2)) == 0
        assert np.array_equal(np.append(dofs1, dofs2), dofs3)
示例#5
0
def test_clear_sub_map_data_scalar(mesh):
    V = FunctionSpace(mesh, ("CG", 2))
    with pytest.raises(ValueError):
        V.sub(1)

    V = VectorFunctionSpace(mesh, ("CG", 2))
    V1 = V.sub(1)
    assert (V1)

    # Clean sub-map data
    V.dofmap.clear_sub_map_data()

    # Can still get previously computed map
    V1 = V.sub(1)

    # New sub-map should throw an error
    with pytest.raises(RuntimeError):
        V.sub(0)
    print("(C) Norm of velocity coefficient vector (blocked, direct): {}".format(norm_u_2))
    print("(C) Norm of pressure coefficient vector (blocked, direct): {}".format(norm_p_2))
assert np.isclose(norm_u_2, norm_u_0)
assert np.isclose(norm_p_2, norm_p_0)


# Non-blocked direct solver
# ^^^^^^^^^^^^^^^^^^^^^^^^^
#
# Again, solve the same problem but this time with a non-blocked direct
# solver approach

# Create the function space
TH = P2 * P1
W = FunctionSpace(mesh, TH)
W0 = W.sub(0).collapse()

# No slip boundary condition
noslip = Function(V)
facets = locate_entities_boundary(mesh, 1, noslip_boundary)
dofs = locate_dofs_topological((W.sub(0), V), 1, facets)
bc0 = DirichletBC(noslip, dofs, W.sub(0))


# Driving velocity condition u = (1, 0) on top boundary (y = 1)
lid_velocity = Function(W0)
lid_velocity.interpolate(lid_velocity_expression)
facets = locate_entities_boundary(mesh, 1, lid)
dofs = locate_dofs_topological((W.sub(0), V), 1, facets)
bc1 = DirichletBC(lid_velocity, dofs, W.sub(0))
示例#7
0
if MPI.COMM_WORLD.rank == 0:
    print("(C) Norm of velocity coefficient vector: {}".format(norm_u_2))
    print("(C) Norm of pressure coefficient vector: {}".format(norm_p_2))
assert np.isclose(norm_u_2, norm_u_0)
assert np.isclose(norm_p_2, norm_p_0)

# Non-blocked direct solver
# ^^^^^^^^^^^^^^^^^^^^^^^^^
#
# Again, solve the same problem but this time with a non-blocked direct
# solver approach

# Create the function space
TH = P2 * P1
W = FunctionSpace(mesh, TH)
W0 = W.sub(0).collapse()

# No slip boundary condition
noslip = Function(W0)
facets = locate_entities_boundary(mesh, 1, noslip_boundary)
dofs = locate_dofs_topological((W.sub(0), V), 1, facets)
bc0 = DirichletBC(noslip, dofs, W.sub(0))

# Driving velocity condition u = (1, 0) on top boundary (y = 1)
lid_velocity = Function(W0)
lid_velocity.interpolate(lid_velocity_expression)
facets = locate_entities_boundary(mesh, 1, lid)
dofs = locate_dofs_topological((W.sub(0), V), 1, facets)
bc1 = DirichletBC(lid_velocity, dofs, W.sub(0))

# Since for this problem the pressure is only determined up to a constant,
示例#8
0
def test_biharmonic():
    """Manufactured biharmonic problem.

    Solved using rotated Regge mixed finite element method. This is equivalent
    to the Hellan-Herrmann-Johnson (HHJ) finite element method in
    two-dimensions."""
    mesh = RectangleMesh(MPI.COMM_WORLD, [np.array([0.0, 0.0, 0.0]),
                                          np.array([1.0, 1.0, 0.0])], [32, 32], CellType.triangle)

    element = ufl.MixedElement([ufl.FiniteElement("Regge", ufl.triangle, 1),
                                ufl.FiniteElement("Lagrange", ufl.triangle, 2)])

    V = FunctionSpace(mesh, element)
    sigma, u = ufl.TrialFunctions(V)
    tau, v = ufl.TestFunctions(V)

    x = ufl.SpatialCoordinate(mesh)
    u_exact = ufl.sin(ufl.pi * x[0]) * ufl.sin(ufl.pi * x[0]) * ufl.sin(ufl.pi * x[1]) * ufl.sin(ufl.pi * x[1])
    f_exact = div(grad(div(grad(u_exact))))
    sigma_exact = grad(grad(u_exact))

    # sigma and tau are tangential-tangential continuous according to the
    # H(curl curl) continuity of the Regge space. However, for the biharmonic
    # problem we require normal-normal continuity H (div div). Theorem 4.2 of
    # Lizao Li's PhD thesis shows that the latter space can be constructed by
    # the former through the action of the operator S:
    def S(tau):
        return tau - ufl.Identity(2) * ufl.tr(tau)

    sigma_S = S(sigma)
    tau_S = S(tau)

    # Discrete duality inner product eq. 4.5 Lizao Li's PhD thesis
    def b(tau_S, v):
        n = FacetNormal(mesh)
        return inner(tau_S, grad(grad(v))) * dx \
            - ufl.dot(ufl.dot(tau_S('+'), n('+')), n('+')) * jump(grad(v), n) * dS \
            - ufl.dot(ufl.dot(tau_S, n), n) * ufl.dot(grad(v), n) * ds

    # Non-symmetric formulation
    a = inner(sigma_S, tau_S) * dx - b(tau_S, u) + b(sigma_S, v)
    L = inner(f_exact, v) * dx

    V_1 = V.sub(1).collapse()
    zero_u = Function(V_1)
    with zero_u.vector.localForm() as zero_u_local:
        zero_u_local.set(0.0)

    # Strong (Dirichlet) boundary condition
    boundary_facets = locate_entities_boundary(
        mesh, mesh.topology.dim - 1, lambda x: np.full(x.shape[1], True, dtype=bool))
    boundary_dofs = locate_dofs_topological((V.sub(1), V_1), mesh.topology.dim - 1, boundary_facets)

    bcs = [DirichletBC(zero_u, boundary_dofs, V.sub(1))]

    A = assemble_matrix(a, bcs=bcs)
    A.assemble()
    b = assemble_vector(L)
    apply_lifting(b, [a], [bcs])
    b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE)

    # Solve
    solver = PETSc.KSP().create(MPI.COMM_WORLD)
    PETSc.Options()["ksp_type"] = "preonly"
    PETSc.Options()["pc_type"] = "lu"
    # PETSc.Options()["pc_factor_mat_solver_type"] = "mumps"
    solver.setFromOptions()
    solver.setOperators(A)

    x_h = Function(V)
    solver.solve(b, x_h.vector)
    x_h.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT,
                           mode=PETSc.ScatterMode.FORWARD)

    # Recall that x_h has flattened indices.
    u_error_numerator = np.sqrt(mesh.mpi_comm().allreduce(assemble_scalar(
        inner(u_exact - x_h[4], u_exact - x_h[4]) * dx(mesh, metadata={"quadrature_degree": 5})), op=MPI.SUM))
    u_error_denominator = np.sqrt(mesh.mpi_comm().allreduce(assemble_scalar(
        inner(u_exact, u_exact) * dx(mesh, metadata={"quadrature_degree": 5})), op=MPI.SUM))

    assert(np.absolute(u_error_numerator / u_error_denominator) < 0.05)

    # Reconstruct tensor from flattened indices.
    # Apply inverse transform. In 2D we have S^{-1} = S.
    sigma_h = S(ufl.as_tensor([[x_h[0], x_h[1]], [x_h[2], x_h[3]]]))
    sigma_error_numerator = np.sqrt(mesh.mpi_comm().allreduce(assemble_scalar(
        inner(sigma_exact - sigma_h, sigma_exact - sigma_h) * dx(mesh, metadata={"quadrature_degree": 5})), op=MPI.SUM))
    sigma_error_denominator = np.sqrt(mesh.mpi_comm().allreduce(assemble_scalar(
        inner(sigma_exact, sigma_exact) * dx(mesh, metadata={"quadrature_degree": 5})), op=MPI.SUM))

    assert(np.absolute(sigma_error_numerator / sigma_error_denominator) < 0.005)
示例#9
0
P1 = FiniteElement("Lagrange", mesh.ufl_cell(), 1)
TH = P2 * P1
W = FunctionSpace(mesh, TH)

# The mixed finite element space is known as Taylor–Hood.
# It is a stable, standard element pair for the Stokes
# equations. Now we can define boundary conditions::

# Extract subdomain facet arrays
mf = sub_domains.values
mf0 = np.where(mf == 0)[0]
mf1 = np.where(mf == 1)[0]

# No-slip boundary condition for velocity
# x1 = 0, x1 = 1 and around the dolphin
noslip = Function(W.sub(0).collapse())
noslip.interpolate(lambda x: np.zeros_like(x[:mesh.geometry.dim]))

bdofs = locate_dofs_topological((W.sub(0), noslip.function_space),
                                sub_domains.dim, mf0)
bc0 = DirichletBC(noslip, bdofs, W.sub(0))

# Inflow boundary condition for velocity
# x0 = 1


def inflow_eval(x):
    values = np.zeros((2, x.shape[1]))
    values[0] = -np.sin(x[1] * np.pi)
    return values