def test_N2curl_interpolation(cell_type, order): mesh = one_cell_mesh(cell_type) tdim = mesh.topology.dim # TODO: fix higher order elements if tdim == 2 and order > 1: pytest.skip("N2curl order > 1 in 2D needs fixing") V = FunctionSpace(mesh, ("Nedelec 2nd kind H(curl)", order)) v = Function(V) if tdim == 2: def f(x): return (x[1]**order, 2 * x[0]) else: def f(x): return (x[1]**order + 2 * x[0], x[2]**order, -3 * x[2]) 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) assert np.allclose(values, [f(p) for p in points])
def test_save_and_read_function(tempdir): filename = os.path.join(tempdir, "function.h5") mesh = UnitSquareMesh(MPI.comm_world, 10, 10) Q = FunctionSpace(mesh, ("CG", 3)) F0 = Function(Q) F1 = Function(Q) def E(x): return x[0] F0.interpolate(E) # Save to HDF5 File hdf5_file = HDF5File(mesh.mpi_comm(), filename, "w") hdf5_file.write(F0, "/function") hdf5_file.close() # Read back from file hdf5_file = HDF5File(mesh.mpi_comm(), filename, "r") F1 = hdf5_file.read_function(Q, "/function") F0.vector.axpy(-1.0, F1.vector) assert F0.vector.norm() < 1.0e-12 hdf5_file.close()
def test_scatter_reverse(element): comm = MPI.COMM_WORLD mesh = UnitSquareMesh(MPI.COMM_WORLD, 5, 5) V = FunctionSpace(mesh, element) u = Function(V) bs = V.dofmap.bs u.interpolate(lambda x: [x[i] for i in range(bs)]) # Reverse scatter (insert) should have no effect w0 = u.x.array.copy() u.x.scatter_reverse(cpp.common.ScatterMode.insert) assert np.allclose(w0, u.x.array) # Fill with MPI rank, and sum all entries in the vector (including ghosts) u.x.array.fill(comm.rank) all_count0 = MPI.COMM_WORLD.allreduce(u.x.array.sum(), op=MPI.SUM) # Reverse scatter (add) u.x.scatter_reverse(cpp.common.ScatterMode.add) num_ghosts = V.dofmap.index_map.num_ghosts ghost_count = MPI.COMM_WORLD.allreduce(num_ghosts * comm.rank, op=MPI.SUM) # New count should have gone up by the number of ghosts times their rank # on all processes all_count1 = MPI.COMM_WORLD.allreduce(u.x.array.sum(), op=MPI.SUM) assert all_count1 == (all_count0 + bs * ghost_count)
def test_save_and_checkpoint_scalar(tempdir, encoding, fe_degree, fe_family, tdim, n): if invalid_fe(fe_family, fe_degree): pytest.skip("Trivial finite element") filename = os.path.join(tempdir, "u1_checkpoint.xdmf") mesh = mesh_factory(tdim, n) FE = FiniteElement(fe_family, mesh.ufl_cell(), fe_degree) V = FunctionSpace(mesh, FE) u_in = Function(V) u_out = Function(V) if has_petsc_complex: def expr_eval(x): return x[0] + 1.0j * x[0] u_out.interpolate(expr_eval) else: def expr_eval(x): return x[0] u_out.interpolate(expr_eval) with XDMFFile(mesh.mpi_comm(), filename, encoding=encoding) as file: file.write_checkpoint(u_out, "u_out", 0) with XDMFFile(mesh.mpi_comm(), filename) as file: u_in = file.read_checkpoint(V, "u_out", 0) u_in.vector.axpy(-1.0, u_out.vector) assert u_in.vector.norm() < 1.0e-12
def test_interpolation_mismatch_rank1(W): def f(values, x): return np.ones((2, x.shape[1])) u = Function(W) with pytest.raises(RuntimeError): u.interpolate(f)
def test_scatter_forward(element): mesh = UnitSquareMesh(MPI.COMM_WORLD, 5, 5) V = FunctionSpace(mesh, element) u = Function(V) bs = V.dofmap.bs u.interpolate(lambda x: [x[i] for i in range(bs)]) # Forward scatter should have no effect w0 = u.x.array.copy() u.x.scatter_forward() assert np.allclose(w0, u.x.array) # Fill local array with the mpi rank u.x.array.fill(MPI.COMM_WORLD.rank) w0 = u.x.array.copy() u.x.scatter_forward() # Now the ghosts should have the value of the rank of # the owning process ghost_owners = u.function_space.dofmap.index_map.ghost_owner_rank() ghost_owners = np.repeat(ghost_owners, bs) local_size = u.function_space.dofmap.index_map.size_local * bs assert np.allclose(u.x.array[local_size:], ghost_owners)
def test_vector_p1_3d(): meshc = UnitCubeMesh(MPI.comm_world, 2, 3, 4) meshf = UnitCubeMesh(MPI.comm_world, 3, 4, 5) Vc = VectorFunctionSpace(meshc, ("CG", 1)) Vf = VectorFunctionSpace(meshf, ("CG", 1)) def u(x): values0 = x[0] + 2.0 * x[1] values1 = 4.0 * x[0] values2 = 3.0 * x[2] + x[0] return np.stack([values0, values1, values2], axis=0) uc, uf = Function(Vc), Function(Vf) uc.interpolate(u) uf.interpolate(u) mat = PETScDMCollection.create_transfer_matrix(Vc._cpp_object, Vf._cpp_object) Vuc = Function(Vf) mat.mult(uc.vector, Vuc.vector) diff = Vuc.vector diff.axpy(-1, uf.vector) assert diff.norm() < 1.0e-12
def test_taylor_hood_cube(): pytest.xfail("Problem with Mixed Function Spaces") meshc = UnitCubeMesh(MPI.comm_world, 2, 2, 2) meshf = UnitCubeMesh(MPI.comm_world, 3, 4, 5) Ve = VectorElement("CG", meshc.ufl_cell(), 2) Qe = FiniteElement("CG", meshc.ufl_cell(), 1) Ze = MixedElement([Ve, Qe]) Zc = FunctionSpace(meshc, Ze) Zf = FunctionSpace(meshf, Ze) def z(x): return np.row_stack((x[0] * x[1], x[1] * x[2], x[2] * x[0], x[0] + 3.0 * x[1] + x[2])) zc, zf = Function(Zc), Function(Zf) zc.interpolate(z) zf.interpolate(z) mat = PETScDMCollection.create_transfer_matrix(Zc, Zf) Zuc = Function(Zf) mat.mult(zc.vector, Zuc.vector) Zuc.vector.update_ghost_values() diff = Function(Zf) diff.assign(Zuc - zf) assert diff.vector.norm("l2") < 1.0e-12
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))
def test_facet_normals(cell_type): """Test that FacetNormal is outward facing""" for count in range(5): mesh = unit_cell(cell_type) tdim = mesh.topology.dim V = VectorFunctionSpace(mesh, ("Lagrange", 1)) normal = FacetNormal(mesh) v = Function(V) map_f = mesh.topology.index_map(tdim - 1) num_facets = map_f.size_local + map_f.num_ghosts indices = np.arange(0, num_facets) values = np.arange(0, num_facets, dtype=np.intc) marker = MeshTags(mesh, tdim - 1, indices, values) # For each facet, check that the inner product of the normal and # the vector that has a positive normal component on only that facet # is positive for i in range(num_facets): if cell_type == CellType.interval: co = mesh.geometry.x[i] v.interpolate(lambda x: x[0] - co[0]) if cell_type == CellType.triangle: co = mesh.geometry.x[i] # Vector function that is zero at `co` and points away from `co` # so that there is no normal component on two edges and the integral # over the other edge is 1 v.interpolate(lambda x: ((x[0] - co[0]) / 2, (x[1] - co[1]) / 2)) elif cell_type == CellType.tetrahedron: co = mesh.geometry.x[i] # Vector function that is zero at `co` and points away from `co` # so that there is no normal component on three faces and the integral # over the other edge is 1 v.interpolate(lambda x: ((x[0] - co[0]) / 3, (x[1] - co[1]) / 3, (x[2] - co[2]) / 3)) elif cell_type == CellType.quadrilateral: # function that is 0 on one edge and points away from that edge # so that there is no normal component on three edges v.interpolate(lambda x: tuple(x[j] - i % 2 if j == i // 2 else 0 * x[j] for j in range(2))) elif cell_type == CellType.hexahedron: # function that is 0 on one face and points away from that face # so that there is no normal component on five faces v.interpolate(lambda x: tuple(x[j] - i % 2 if j == i // 3 else 0 * x[j] for j in range(3))) # assert that the integrals these functions dotted with the normal over a face # is 1 on one face and 0 on the others ones = 0 for j in range(num_facets): a = inner(v, normal) * ds(subdomain_data=marker, subdomain_id=j) result = fem.assemble_scalar(a) if np.isclose(result, 1): ones += 1 else: assert np.isclose(result, 0) assert ones == 1
def run_vector_test(V, poly_order): """Test that interpolation is correct in a scalar valued space.""" random.seed(12) tdim = V.mesh.topology.dim if tdim == 1: def f(x): return x[0]**poly_order elif tdim == 2: def f(x): return (x[1]**min(poly_order, 1), 2 * x[0]**poly_order) else: def f(x): return (x[1]**min(poly_order, 1), 2 * x[0]**poly_order, 3 * x[2]**min(poly_order, 2)) v = Function(V) v.interpolate(f) points = [random_point_in_cell(V.mesh) for count in range(5)] cells = [0 for count in range(5)] values = v.eval(points, cells) for p, val in zip(points, values): assert np.allclose(val, f(p))
def test_scalar_interpolation(cell_type, order): """Test that interpolation is correct in a FunctionSpace""" mesh = one_cell_mesh(cell_type) tdim = mesh.topology.dim V = FunctionSpace(mesh, ("Lagrange", order)) v = Function(V) if tdim == 1: def f(x): return x[0]**order elif tdim == 2: def f(x): return x[1]**order + 2 * x[0] else: def f(x): return x[1]**order + 2 * x[0] - 3 * x[2] 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))
def test_fourth_order_quad(L, H, Z): """Test by comparing integration of z+x*y against sympy/scipy integration of a quad element. Z>0 implies curved element. *---------* 20-21-22-23-24-41--42--43--44 | | | | | | | 15 16 17 18 19 37 38 39 40 | | | | | | | 10 11 12 13 14 33 34 35 36 | | | | | | | 5 6 7 8 9 29 30 31 32 | | | | | *---------* 0--1--2--3--4--25--26--27--28 """ points = np.array([[0, 0, 0], [L / 4, 0, 0], [L / 2, 0, 0], # 0 1 2 [3 * L / 4, 0, 0], [L, 0, 0], # 3 4 [0, H / 4, -Z / 3], [L / 4, H / 4, -Z / 3], [L / 2, H / 4, -Z / 3], # 5 6 7 [3 * L / 4, H / 4, -Z / 3], [L, H / 4, -Z / 3], # 8 9 [0, H / 2, 0], [L / 4, H / 2, 0], [L / 2, H / 2, 0], # 10 11 12 [3 * L / 4, H / 2, 0], [L, H / 2, 0], # 13 14 [0, (3 / 4) * H, 0], [L / 4, (3 / 4) * H, 0], # 15 16 [L / 2, (3 / 4) * H, 0], [3 * L / 4, (3 / 4) * H, 0], # 17 18 [L, (3 / 4) * H, 0], [0, H, Z], [L / 4, H, Z], # 19 20 21 [L / 2, H, Z], [3 * L / 4, H, Z], [L, H, Z], # 22 23 24 [(5 / 4) * L, 0, 0], [(6 / 4) * L, 0, 0], # 25 26 [(7 / 4) * L, 0, 0], [2 * L, 0, 0], # 27 28 [(5 / 4) * L, H / 4, -Z / 3], [(6 / 4) * L, H / 4, -Z / 3], # 29 30 [(7 / 4) * L, H / 4, -Z / 3], [2 * L, H / 4, -Z / 3], # 31 32 [(5 / 4) * L, H / 2, 0], [(6 / 4) * L, H / 2, 0], # 33 34 [(7 / 4) * L, H / 2, 0], [2 * L, H / 2, 0], # 35 36 [(5 / 4) * L, 3 / 4 * H, 0], # 37 [(6 / 4) * L, 3 / 4 * H, 0], # 38 [(7 / 4) * L, 3 / 4 * H, 0], [2 * L, 3 / 4 * H, 0], # 39 40 [(5 / 4) * L, H, Z], [(6 / 4) * L, H, Z], # 41 42 [(7 / 4) * L, H, Z], [2 * L, H, Z]]) # 43 44 # VTK ordering cells = np.array([[0, 4, 24, 20, 1, 2, 3, 9, 14, 19, 21, 22, 23, 5, 10, 15, 6, 7, 8, 11, 12, 13, 16, 17, 18], [4, 28, 44, 24, 25, 26, 27, 32, 36, 40, 41, 42, 43, 9, 14, 19, 29, 30, 31, 33, 34, 35, 37, 38, 39]]) cells = cells[:, perm_vtk(CellType.quadrilateral, cells.shape[1])] cell = ufl.Cell("quadrilateral", geometric_dimension=points.shape[1]) domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell, 4)) mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain) def e2(x): return x[2] + x[0] * x[1] V = FunctionSpace(mesh, ("CG", 4)) u = Function(V) u.interpolate(e2) intu = assemble_scalar(u * dx(mesh)) intu = mesh.mpi_comm().allreduce(intu, op=MPI.SUM) nodes = [0, 5, 10, 15, 20] ref = sympy_scipy(points, nodes, 2 * L, H) assert ref == pytest.approx(intu, rel=1e-5)
def xtest_quadrilateral_integral(space_type, space_order): domain = ufl.Mesh(ufl.VectorElement("Lagrange", "quadrilateral", 1)) temp_points = np.array([[-1., -1.], [0., 0.], [1., 0.], [-1., 1.], [0., 1.], [2., 2.]]) 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] connections = {0: [1, 2], 1: [0, 3], 2: [0, 3], 3: [1, 2]} cells = [] for cell in [[0, 1, 3, 4], [1, 2, 4, 5]]: # Randomly number the cell start = choice(range(4)) cell_order = [start] for i in range(2): diff = choice([ i for i in connections[start] if i not in cell_order ]) - cell_order[0] cell_order += [c + diff for c in 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 ["RTCF"]: # Hdiv def normal(x): values = np.zeros((2, 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 ["RTCE"]: # Hcurl def tangent(x): values = np.zeros((2, x.shape[1])) values[1] = [1 for i in values[1]] return values t = Function(Vvec) t.interpolate(tangent) form = ufl.inner(ufl.jump(v), t) * ufl.dS else: form = ufl.jump(v) * ufl.dS value = fem.assemble_scalar(form) assert np.isclose(value, 0)
def test_mixed_interpolation(): """Test that interpolation raised an exception.""" mesh = one_cell_mesh(CellType.triangle) A = ufl.FiniteElement("Lagrange", mesh.ufl_cell(), 1) B = ufl.VectorElement("Lagrange", mesh.ufl_cell(), 1) v = Function(FunctionSpace(mesh, ufl.MixedElement([A, B]))) with pytest.raises(RuntimeError): v.interpolate(lambda x: (x[1], 2 * x[0], 3 * x[1]))
def test_interpolation_function(mesh): V = FunctionSpace(mesh, ("CG", 1)) u = Function(V) u.vector.set(1) Vh = FunctionSpace(mesh, ("CG", 1)) uh = Function(Vh) uh.interpolate(u) assert np.allclose(uh.vector.array, 1)
def solve_system(N): fenics_mesh = dolfinx.UnitCubeMesh(fenicsx_comm, N, N, N) fenics_space = dolfinx.FunctionSpace(fenics_mesh, ("CG", 1)) u = ufl.TrialFunction(fenics_space) v = ufl.TestFunction(fenics_space) k = 2 # print(u*v*ufl.ds) form = (ufl.inner(ufl.grad(u), ufl.grad(v)) - k**2 * ufl.inner(u, v)) * ufl.dx # locate facets on the cube boundary facets = locate_entities_boundary( fenics_mesh, 2, lambda x: np.logical_or( np.logical_or( np.logical_or(np.isclose(x[2], 0.0), np.isclose(x[2], 1.0)), np.logical_or(np.isclose(x[1], 0.0), np.isclose(x[1], 1.0))), np.logical_or(np.isclose(x[0], 0.0), np.isclose(x[0], 1.0)))) facets.sort() # alternative - more general approach boundary = entities_to_geometry( fenics_mesh, fenics_mesh.topology.dim - 1, exterior_facet_indices(fenics_mesh), True, ) # print(len(facets) assert len(facets) == len(exterior_facet_indices(fenics_mesh)) u0 = fem.Function(fenics_space) with u0.vector.localForm() as u0_loc: u0_loc.set(0) # solution vector bc = DirichletBC(u0, locate_dofs_topological(fenics_space, 2, facets)) A = 1 + 1j f = Function(fenics_space) f.interpolate(lambda x: A * k**2 * np.cos(k * x[0]) * np.cos(k * x[1])) L = ufl.inner(f, v) * ufl.dx u0.name = "u" problem = fem.LinearProblem(form, L, u=u0, petsc_options={ "ksp_type": "preonly", "pc_type": "lu" }) # problem = fem.LinearProblem(form, L, bcs=[bc], u=u0, petsc_options={"ksp_type": "preonly", "pc_type": "lu"}) start_time = time.time() soln = problem.solve() if world_rank == 0: print("--- fenics solve done in %s seconds ---" % (time.time() - start_time))
def run_scalar_test(mesh, V, degree): """ Manufactured Poisson problem, solving u = x[1]**p, where p is the degree of the Lagrange function space. """ u, v = TrialFunction(V), TestFunction(V) a = inner(grad(u), grad(v)) * dx # Get quadrature degree for bilinear form integrand (ignores effect of non-affine map) a = inner(grad(u), grad(v)) * dx(metadata={"quadrature_degree": -1}) a.integrals()[0].metadata()["quadrature_degree"] = ufl.algorithms.estimate_total_polynomial_degree(a) # Source term x = SpatialCoordinate(mesh) u_exact = x[1]**degree f = - div(grad(u_exact)) # Set quadrature degree for linear form integrand (ignores effect of non-affine map) L = inner(f, v) * dx(metadata={"quadrature_degree": -1}) L.integrals()[0].metadata()["quadrature_degree"] = ufl.algorithms.estimate_total_polynomial_degree(L) L = fem.Form(L) u_bc = Function(V) u_bc.interpolate(lambda x: x[1]**degree) # Create Dirichlet boundary condition facetdim = mesh.topology.dim - 1 mesh.topology.create_connectivity(facetdim, mesh.topology.dim) bndry_facets = np.where(np.array(cpp.mesh.compute_boundary_facets(mesh.topology)) == 1)[0] bdofs = locate_dofs_topological(V, facetdim, bndry_facets) bc = DirichletBC(u_bc, bdofs) b = assemble_vector(L) apply_lifting(b, [a], [[bc]]) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) set_bc(b, [bc]) a = fem.Form(a) A = assemble_matrix(a, [bc]) A.assemble() # Create LU linear solver solver = PETSc.KSP().create(MPI.COMM_WORLD) solver.setType(PETSc.KSP.Type.PREONLY) solver.getPC().setType(PETSc.PC.Type.LU) solver.setOperators(A) uh = Function(V) solver.solve(b, uh.vector) uh.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) M = (u_exact - uh)**2 * dx M = fem.Form(M) error = mesh.mpi_comm().allreduce(assemble_scalar(M), op=MPI.SUM) assert np.absolute(error) < 1.0e-14
def xtest_third_order_tri(): # *---*---*---* 3--11--10--2 # | \ | | \ | # * * * * 8 7 15 13 # | \ | | \ | # * * * * 9 14 6 12 # | \ | | \ | # *---*---*---* 0--4---5---1 for H in (1.0, 2.0): for Z in (0.0, 0.5): L = 1 points = np.array([ [0, 0, 0], [L, 0, 0], [L, H, Z], [0, H, Z], # 0, 1, 2, 3 [L / 3, 0, 0], [2 * L / 3, 0, 0], # 4, 5 [2 * L / 3, H / 3, 0], [L / 3, 2 * H / 3, 0], # 6, 7 [0, 2 * H / 3, 0], [0, H / 3, 0], # 8, 9 [2 * L / 3, H, Z], [L / 3, H, Z], # 10, 11 [L, H / 3, 0], [L, 2 * H / 3, 0], # 12, 13 [L / 3, H / 3, 0], # 14 [2 * L / 3, 2 * H / 3, 0] ]) # 15 cells = np.array([[0, 1, 3, 4, 5, 6, 7, 8, 9, 14], [1, 2, 3, 12, 13, 10, 11, 7, 6, 15]]) cells = permute_cell_ordering( cells, permutation_vtk_to_dolfin(CellType.triangle, cells.shape[1])) mesh = Mesh(MPI.COMM_WORLD, CellType.triangle, points, cells, [], degree=3) def e2(x): return x[2] + x[0] * x[1] degree = mesh.geometry.dofmap_layout().degree() # Interpolate function V = FunctionSpace(mesh, ("CG", degree)) u = Function(V) u.interpolate(e2) intu = assemble_scalar(u * dx(metadata={"quadrature_degree": 40})) intu = mesh.mpi_comm().allreduce(intu, op=MPI.SUM) nodes = [0, 9, 8, 3] ref = sympy_scipy(points, nodes, L, H) assert ref == pytest.approx(intu, rel=1e-6)
def test_plus_minus_vector(cell_type, pm1, pm2): """Test that ('+') and ('-') match up with the correct DOFs for DG functions""" results = [] orders = [] spaces = [] for count in range(3): for agree in [True, False]: mesh, order = two_unit_cells(cell_type, agree, return_order=True) if cell_type in [ CellType.interval, CellType.triangle, CellType.tetrahedron ]: V = FunctionSpace(mesh, ("DG", 1)) else: V = FunctionSpace(mesh, ("DQ", 1)) f = Function(V) f.interpolate(lambda x: x[0] - 2 * x[1]) v = TestFunction(V) a = inner(f(pm1), v(pm2)) * dS result = fem.assemble_vector(a) result.assemble() spaces.append(V) results.append(result) orders.append(order) for i, j in combinations(zip(results, spaces, orders), 2): dof_order = [] for cell in range(2): for point in range(len(mesh.geometry.points)): point_n = j[2][point] cell_points = list(j[1].mesh.cells()[cell]) if point_n in cell_points: point_n_in_cell = cell_points.index(point_n) dofmap = j[1].dofmap.cell_dofs(cell) j_dof_n = dofmap[point_n_in_cell] else: j_dof_n = None point_n = i[2][point] cell_points = list(i[1].mesh.cells()[cell]) if point_n in cell_points: point_n_in_cell = cell_points.index(point_n) dofmap = i[1].dofmap.cell_dofs(cell) i_dof_n = dofmap[point_n_in_cell] else: i_dof_n = None if i_dof_n is None: assert j_dof_n is None else: dof_order.append((i_dof_n, j_dof_n)) for a, b in dof_order: assert np.isclose(i[0][a], j[0][b])
def xtest_triangle_integral(space_type, space_order): domain = ufl.Mesh(ufl.VectorElement("Lagrange", "triangle", 1)) temp_points = np.array([[-1., -1.], [0., 0.], [1., 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], [1, 2, 3]]: # Randomly number the cell cell_order = list(range(3)) 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.vector.local_size) ] if space_type in ["RT", "BDM"]: # Hdiv def normal(x): values = np.zeros((2, 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 tangent(x): values = np.zeros((2, x.shape[1])) values[1] = [1 for i in values[1]] return values t = Function(Vvec) t.interpolate(tangent) form = ufl.inner(ufl.jump(v), t) * ufl.dS else: form = ufl.jump(v) * ufl.dS value = fem.assemble_scalar(form) assert np.isclose(value, 0)
def test_eval_manifold(): # Simple two-triangle surface in 3d vertices = [(0.0, 0.0, 1.0), (1.0, 1.0, 1.0), (1.0, 0.0, 0.0), (0.0, 1.0, 0.0)] cells = [(0, 1, 2), (0, 1, 3)] cell = ufl.Cell("triangle", geometric_dimension=3) domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell, 1)) mesh = create_mesh(MPI.COMM_WORLD, cells, vertices, domain) Q = FunctionSpace(mesh, ("Lagrange", 1)) u = Function(Q) u.interpolate(lambda x: x[0] + x[1]) assert np.isclose(u.eval([0.75, 0.25, 0.5], 0)[0], 1.0)
def test_third_order_quad(L, H, Z): """Test by comparing integration of z+x*y against sympy/scipy integration of a quad element. Z>0 implies curved element. *---------* 3--8--9--2-22-23-17 | | | | | | | 11 14 15 7 26 27 21 | | | | | | | 10 12 13 6 24 25 20 | | | | | *---------* 0--4--5--1-18-19-16 """ points = np.array([[0, 0, 0], [L, 0, 0], [L, H, Z], [0, H, Z], # 0 1 2 3 [L / 3, 0, 0], [2 * L / 3, 0, 0], # 4 5 [L, H / 3, 0], [L, 2 * H / 3, 0], # 6 7 [L / 3, H, Z], [2 * L / 3, H, Z], # 8 9 [0, H / 3, 0], [0, 2 * H / 3, 0], # 10 11 [L / 3, H / 3, 0], [2 * L / 3, H / 3, 0], # 12 13 [L / 3, 2 * H / 3, 0], [2 * L / 3, 2 * H / 3, 0], # 14 15 [2 * L, 0, 0], [2 * L, H, Z], # 16 17 [4 * L / 3, 0, 0], [5 * L / 3, 0, 0], # 18 19 [2 * L, H / 3, 0], [2 * L, 2 * H / 3, 0], # 20 21 [4 * L / 3, H, Z], [5 * L / 3, H, Z], # 22 23 [4 * L / 3, H / 3, 0], [5 * L / 3, H / 3, 0], # 24 25 [4 * L / 3, 2 * H / 3, 0], [5 * L / 3, 2 * H / 3, 0]]) # 26 27 # Change to multiple cells when matthews dof-maps work for quads cells = np.array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], [1, 16, 17, 2, 18, 19, 20, 21, 22, 23, 6, 7, 24, 25, 26, 27]]) cells = permute_cell_ordering(cells, permutation_vtk_to_dolfin(CellType.quadrilateral, cells.shape[1])) mesh = Mesh(MPI.comm_world, CellType.quadrilateral, points, cells, [], GhostMode.none) def e2(x): return x[2] + x[0] * x[1] # Interpolate function V = FunctionSpace(mesh, ("CG", 3)) u = Function(V) cmap = fem.create_coordinate_map(mesh.ufl_domain()) mesh.geometry.coord_mapping = cmap u.interpolate(e2) intu = assemble_scalar(u * dx(mesh)) intu = MPI.sum(mesh.mpi_comm(), intu) nodes = [0, 3, 10, 11] ref = sympy_scipy(points, nodes, 2 * L, H) assert ref == pytest.approx(intu, rel=1e-6)
def test_plus_minus_vector(cell_type, pm1, pm2): """Test that ('+') and ('-') match up with the correct DOFs for DG functions""" results = [] orders = [] spaces = [] for count in range(3): for agree in [True, False]: # Two cell mesh with randomly numbered points mesh, order = two_unit_cells(cell_type, agree, return_order=True) if cell_type in [ CellType.interval, CellType.triangle, CellType.tetrahedron ]: V = FunctionSpace(mesh, ("DG", 1)) else: V = FunctionSpace(mesh, ("DQ", 1)) # Assemble vectors with combinations of + and - for a few # different numberings f = Function(V) f.interpolate(lambda x: x[0] - 2 * x[1]) v = ufl.TestFunction(V) a = ufl.inner(f(pm1), v(pm2)) * ufl.dS result = fem.assemble_vector(a) result.assemble() spaces.append(V) results.append(result) orders.append(order) # Check that the above vectors all have the same values as the first # one, but permuted due to differently ordered dofs dofmap0 = spaces[0].mesh.geometry.dofmap for result, space in zip(results[1:], spaces[1:]): # Get the data relating to two results dofmap1 = space.mesh.geometry.dofmap # For each cell for cell in range(2): # For each point in cell 0 in the the first mesh for dof0, point0 in zip(spaces[0].dofmap.cell_dofs(cell), dofmap0.links(cell)): # Find the point in the cell 0 in the second mesh for dof1, point1 in zip(space.dofmap.cell_dofs(cell), dofmap1.links(cell)): if np.allclose(spaces[0].mesh.geometry.x[point0], space.mesh.geometry.x[point1]): break else: # If no matching point found, fail assert False assert np.isclose(results[0][dof0], result[dof1])
def test_interpolation_rank1(W): def f(x): values = np.empty((3, x.shape[1])) values[0] = 1.0 values[1] = 1.0 values[2] = 1.0 return values w = Function(W) w.interpolate(f) x = w.vector assert x.max()[1] == 1.0 assert x.min()[1] == 1.0
def test_eval_manifold(): # Simple two-triangle surface in 3d vertices = [(0.0, 0.0, 1.0), (1.0, 1.0, 1.0), (1.0, 0.0, 0.0), (0.0, 1.0, 0.0)] cells = [(0, 1, 2), (0, 1, 3)] mesh = Mesh(MPI.COMM_WORLD, cpp.mesh.CellType.triangle, np.array(vertices, dtype=np.float64), np.array(cells, dtype=np.int32), []) Q = FunctionSpace(mesh, ("CG", 1)) u = Function(Q) u.interpolate(lambda x: x[0] + x[1]) assert np.isclose(u.eval([0.75, 0.25, 0.5], 0)[0], 1.0)
def test_third_order_tri(): # *---*---*---* 3--11--10--2 # | \ | | \ | # * * * * 8 7 15 13 # | \ | | \ | # * * * * 9 14 6 12 # | \ | | \ | # *---*---*---* 0--4---5---1 for H in (1.0, 2.0): for Z in (0.0, 0.5): L = 1 points = np.array([ [0, 0, 0], [L, 0, 0], [L, H, Z], [0, H, Z], # 0, 1, 2, 3 [L / 3, 0, 0], [2 * L / 3, 0, 0], # 4, 5 [2 * L / 3, H / 3, 0], [L / 3, 2 * H / 3, 0], # 6, 7 [0, 2 * H / 3, 0], [0, H / 3, 0], # 8, 9 [2 * L / 3, H, Z], [L / 3, H, Z], # 10, 11 [L, H / 3, 0], [L, 2 * H / 3, 0], # 12, 13 [L / 3, H / 3, 0], # 14 [2 * L / 3, 2 * H / 3, 0] ]) # 15 cells = np.array([[0, 1, 3, 4, 5, 6, 7, 8, 9, 14], [1, 2, 3, 12, 13, 10, 11, 7, 6, 15]]) cells = cells[:, perm_vtk(CellType.triangle, cells.shape[1])] cell = ufl.Cell("triangle", geometric_dimension=points.shape[1]) domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell, 3)) mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain) def e2(x): return x[2] + x[0] * x[1] # Interpolate function V = FunctionSpace(mesh, ("Lagrange", 3)) u = Function(V) u.interpolate(e2) intu = assemble_scalar(u * dx(metadata={"quadrature_degree": 40})) intu = mesh.mpi_comm().allreduce(intu, op=MPI.SUM) nodes = [0, 9, 8, 3] ref = sympy_scipy(points, nodes, L, H) assert ref == pytest.approx(intu, rel=1e-6)
def test_facet_integral(cell_type): """Test that the integral of a function over a facet is correct""" for count in range(5): mesh = unit_cell(cell_type) tdim = mesh.topology.dim V = FunctionSpace(mesh, ("Lagrange", 2)) v = Function(V) map_f = mesh.topology.index_map(tdim - 1) num_facets = map_f.size_local + map_f.num_ghosts indices = np.arange(0, num_facets) values = np.arange(0, num_facets, dtype=np.intc) marker = MeshTags(mesh, tdim - 1, indices, values) # Functions that will have the same integral over each facet if cell_type == CellType.triangle: root = 3 ** 0.25 # 4th root of 3 v.interpolate(lambda x: (x[0] - 1 / root) ** 2 + (x[1] - root / 3) ** 2) elif cell_type == CellType.quadrilateral: v.interpolate(lambda x: x[0] * (1 - x[0]) + x[1] * (1 - x[1])) elif cell_type == CellType.tetrahedron: s = 2 ** 0.5 * 3 ** (1 / 3) # side length v.interpolate(lambda x: (x[0] - s / 2) ** 2 + (x[1] - s / 2 / np.sqrt(3)) ** 2 + (x[2] - s * np.sqrt(2 / 3) / 4) ** 2) elif cell_type == CellType.hexahedron: v.interpolate(lambda x: x[0] * (1 - x[0]) + x[1] * (1 - x[1]) + x[2] * (1 - x[2])) # assert that the integral of these functions over each face are equal out = [] for j in range(num_facets): a = v * ds(subdomain_data=marker, subdomain_id=j) result = fem.assemble_scalar(a) out.append(result) assert np.isclose(result, out[0])
def test_save_1d_scalar(tempdir): mesh = UnitIntervalMesh(MPI.COMM_WORLD, 32) def f(x): return x[0] u = Function(FunctionSpace(mesh, ("CG", 2))) u.interpolate(f) u.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) filename = os.path.join(tempdir, "u.pvd") with VTKFile(MPI.COMM_WORLD, filename, "w") as vtk: vtk.write_function(u, 0.) vtk.write_function(u, 1.)
def test_manufactured_vector1(family, degree, filename, datadir): """Projection into H(div/curl) spaces""" with XDMFFile(MPI.COMM_WORLD, os.path.join(datadir, filename), "r", encoding=XDMFFile.Encoding.ASCII) as xdmf: mesh = xdmf.read_mesh(name="Grid") V = FunctionSpace(mesh, (family, degree)) W = VectorFunctionSpace(mesh, ("CG", degree)) u, v = ufl.TrialFunction(V), ufl.TestFunction(V) a = inner(u, v) * dx # Source term x = SpatialCoordinate(mesh) u_ref = x[0]**degree L = inner(u_ref, v[0]) * dx b = assemble_vector(L) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) A = assemble_matrix(a) A.assemble() # Create LU linear solver (Note: need to use a solver that # re-orders to handle pivots, e.g. not the PETSc built-in LU # solver) solver = PETSc.KSP().create(MPI.COMM_WORLD) solver.setType("preonly") solver.getPC().setType('lu') solver.setOperators(A) # Solve uh = Function(V) solver.solve(b, uh.vector) uh.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) u_exact = Function(W) u_exact.interpolate(lambda x: np.array([ x[0]**degree if i == 0 else 0 * x[0] for i in range(mesh.topology.dim) ])) M = inner(uh - u_exact, uh - u_exact) * dx M = fem.Form(M) error = mesh.mpi_comm().allreduce(assemble_scalar(M), op=MPI.SUM) assert np.absolute(error) < 1.0e-14