def IntervalMesh(comm, nx: int, points: list, ghost_mode=cpp.mesh.GhostMode.shared_facet, partitioner=cpp.mesh.partition_cells_graph): """Create an interval mesh Parameters ---------- comm MPI communicator nx Number of cells point Coordinates of the end points ghost_mode """ domain = ufl.Mesh(ufl.VectorElement("Lagrange", "interval", 1)) cmap = fem.create_coordinate_map(comm, domain) mesh = cpp.generation.create_interval_mesh(comm, nx, points, cmap, ghost_mode, partitioner) domain._ufl_cargo = mesh mesh._ufl_domain = domain return mesh
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)) cmap = fem.create_coordinate_map(comm, domain) mesh = cpp.generation.create_box_mesh(comm, points, n, cmap, ghost_mode, partitioner) domain._ufl_cargo = mesh mesh._ufl_domain = domain return mesh
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
def test_higher_order_coordinate_map(points, celltype): """ Computes physical coordinates of a cell, based on the coordinate map. """ cells = np.array([range(len(points))]) mesh = Mesh(MPI.comm_world, celltype, points, cells, [], GhostMode.none) V = FunctionSpace(mesh, ("Lagrange", mesh.degree())) X = V.element.dof_reference_coordinates() coord_dofs = mesh.coordinate_dofs().entity_points() x_g = mesh.geometry.points cmap = fem.create_coordinate_map(mesh.ufl_domain()) 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[0, node], :mesh.geometry.dim] i += 1 x = np.zeros(X.shape) cmap.push_forward(x, 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]))
def UnitCubeMesh(comm, nx, ny, nz, cell_type=cpp.mesh.CellType.tetrahedron, ghost_mode=cpp.mesh.GhostMode.none): """Create a mesh of a unit cube with coordinate mapping attached Parameters ---------- comm MPI communicator nx Number of cells in "x" direction ny Number of cells in "y" direction nz Number of cells in "z" direction """ mesh = BoxMesh( comm, [numpy.array([0.0, 0.0, 0.0]), numpy.array([1.0, 1.0, 1.0])], [nx, ny, nz], cell_type, ghost_mode) mesh.geometry.coord_mapping = fem.create_coordinate_map(mesh) return mesh
def test_nullspace_check(mesh, degree): V = VectorFunctionSpace(mesh, ('Lagrange', degree)) u, v = TrialFunction(V), TestFunction(V) mesh.geometry.coord_mapping = fem.create_coordinate_map(mesh) E, nu = 2.0e2, 0.3 mu = E / (2.0 * (1.0 + nu)) lmbda = E * nu / ((1.0 + nu) * (1.0 - 2.0 * nu)) def sigma(w, gdim): return 2.0 * mu * ufl.sym(grad(w)) + lmbda * ufl.tr( grad(w)) * ufl.Identity(gdim) a = inner(sigma(u, mesh.geometry.dim), grad(v)) * dx # Assemble matrix and create compatible vector A = assemble_matrix(a) A.assemble() # Create null space basis and test null_space = build_elastic_nullspace(V) assert null_space.in_nullspace(A, tol=1.0e-8) null_space.orthonormalize() assert null_space.in_nullspace(A, tol=1.0e-8) # Create incorrect null space basis and test null_space = build_broken_elastic_nullspace(V) assert not null_space.in_nullspace(A, tol=1.0e-8) null_space.orthonormalize() assert not null_space.in_nullspace(A, tol=1.0e-8)
def test_higher_order_coordinate_map(points, celltype, order): """Computes physical coordinates of a cell, based on the coordinate map.""" 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.dof_reference_coordinates() coord_dofs = mesh.geometry.dofmap x_g = mesh.geometry.x cmap = fem.create_coordinate_map(mesh.mpi_comm(), mesh.ufl_domain()) 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 = np.zeros(X.shape) cmap.push_forward(x, 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]))
def UnitSquareMesh(comm, nx, ny, cell_type=cpp.mesh.CellType.triangle, ghost_mode=cpp.mesh.GhostMode.none, diagonal="right"): """Create a mesh of a unit square with coordinate mapping attached Parameters ---------- comm MPI communicator nx Number of cells in "x" direction ny Number of cells in "y" direction diagonal Direction of diagonal """ mesh = RectangleMesh( comm, [numpy.array([0.0, 0.0, 0.0]), numpy.array([1.0, 1.0, 0.0])], [nx, ny], cell_type, ghost_mode, diagonal) mesh.geometry.coord_mapping = fem.create_coordinate_map(mesh) return mesh
def read_mesh(self, ghost_mode=cpp.mesh.GhostMode.shared_facet, name="mesh", xpath="/Xdmf/Domain"): # Read mesh data from file cell_type = 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_type[0]), geometric_dimension=x.shape[1]) domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell, cell_type[1])) cmap = fem.create_coordinate_map(self.comm(), domain) # Build the mesh 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
def test_quadrilateral_dof_positions(space_type): """Checks that dofs on shared quadrilateral edges match up""" domain = ufl.Mesh(ufl.VectorElement("Lagrange", "quadrilateral", 1)) if MPI.COMM_WORLD.rank == 0: # Create a quadrilateral mesh N = 6 temp_points = np.array([[x / 2, y / 2] for x in range(N) for y in range(N)]) 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 x in range(N - 1): for y in range(N - 1): a = N * y + x cell = [order[i] for i in [a, a + 1, a + N, a + N + 1]] cells.append(cell) # On process 0, input mesh data and distribute to other # processes mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain) else: mesh = create_mesh(MPI.COMM_WORLD, np.ndarray((0, 4)), np.ndarray((0, 2)), domain) V = FunctionSpace(mesh, space_type) dofmap = V.dofmap edges = {} # Get coordinates of dofs and edges and check that they are the same # for each global dof number X = V.element.dof_reference_coordinates() coord_dofs = mesh.geometry.dofmap x_g = mesh.geometry.x cmap = fem.create_coordinate_map(mesh.ufl_domain()) for cell_n in range(coord_dofs.num_nodes): dofs = dofmap.cell_dofs(cell_n) x_coord_new = np.zeros([4, 2]) for v in range(4): x_coord_new[v] = x_g[coord_dofs.links(cell_n)[v], :2] x = X.copy() cmap.push_forward(x, X, x_coord_new) edge_dofs_local = [] for i in range(4): edge_dofs_local += list(dofmap.dof_layout.entity_dofs(1, i)) edge_dofs = [dofs[i] for i in edge_dofs_local] for i, j in zip(edge_dofs, x[edge_dofs_local]): if i in edges: assert np.allclose(j, edges[i]) else: edges[i] = j
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 = permute_cell_ordering( cells, permutation_vtk_to_dolfin(CellType.triangle, cells.shape[1])) mesh = Mesh(MPI.comm_world, CellType.triangle, points, cells, [], GhostMode.none) def e2(x): return x[2] + x[0] * x[1] degree = mesh.degree() # Interpolate function V = FunctionSpace(mesh, ("CG", degree)) u = Function(V) cmap = fem.create_coordinate_map(mesh.ufl_domain()) mesh.geometry.coord_mapping = cmap u.interpolate(e2) intu = assemble_scalar(u * dx(metadata={"quadrature_degree": 40})) intu = MPI.sum(mesh.mpi_comm(), intu) nodes = [0, 9, 8, 3] ref = sympy_scipy(points, nodes, L, H) assert ref == pytest.approx(intu, rel=1e-6)
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 UnitIntervalMesh(comm, nx, ghost_mode=cpp.mesh.GhostMode.none): """Create a mesh on the unit interval with coordinate mapping attached Parameters ---------- comm MPI communicator nx Number of cells """ mesh = IntervalMesh(comm, nx, [0.0, 1.0], ghost_mode) mesh.geometry.coord_mapping = fem.create_coordinate_map(mesh) return mesh
def create_mesh(comm, cells, x, domain, ghost_mode=cpp.mesh.GhostMode.shared_facet, partitioner=cpp.mesh.partition_cells_graph): """Create a mesh from topology and geometry data""" cmap = fem.create_coordinate_map(comm, domain) try: mesh = cpp.mesh.create_mesh(comm, cells, cmap, x, ghost_mode, partitioner) except TypeError: mesh = cpp.mesh.create_mesh(comm, cpp.graph.AdjacencyList_int64(numpy.cast['int64'](cells)), cmap, x, ghost_mode, partitioner) # Attach UFL data (used when passing a mesh into UFL functions) domain._ufl_cargo = mesh mesh._ufl_domain = domain return mesh
def test_fourth_order_tri(): L = 1 # *--*--*--*--* 3-21-20-19--2 # | \ | | \ | # * * * * * 10 9 24 23 18 # | \ | | \ | # * * * * * 11 15 8 22 17 # | \ | | \ | # * * * * * 12 13 14 7 16 # | \ | | \ | # *--*--*--*--* 0--4--5--6--1 for H in (1.0, 2.0): for Z in (0.0, 0.5): points = np.array( [[0, 0, 0], [L, 0, 0], [L, H, Z], [0, H, Z], # 0, 1, 2, 3 [L / 4, 0, 0], [L / 2, 0, 0], [3 * L / 4, 0, 0], # 4, 5, 6 [3 / 4 * L, H / 4, Z / 2], [L / 2, H / 2, 0], # 7, 8 [L / 4, 3 * H / 4, 0], [0, 3 * H / 4, 0], # 9, 10 [0, H / 2, 0], [0, H / 4, Z / 2], # 11, 12 [L / 4, H / 4, Z / 2], [L / 2, H / 4, Z / 2], [L / 4, H / 2, 0], # 13, 14, 15 [L, H / 4, Z / 2], [L, H / 2, 0], [L, 3 * H / 4, 0], # 16, 17, 18 [3 * L / 4, H, Z], [L / 2, H, Z], [L / 4, H, Z], # 19, 20, 21 [3 * L / 4, H / 2, 0], [3 * L / 4, 3 * H / 4, 0], # 22, 23 [L / 2, 3 * H / 4, 0]] # 24 ) cells = np.array([[0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], [1, 2, 3, 16, 17, 18, 19, 20, 21, 9, 8, 7, 22, 23, 24]]) cells = permute_cell_ordering(cells, permutation_vtk_to_dolfin(CellType.triangle, cells.shape[1])) mesh = Mesh(MPI.comm_world, CellType.triangle, points, cells, [], GhostMode.none) def e2(x): return x[2] + x[0] * x[1] degree = mesh.degree() # Interpolate function V = FunctionSpace(mesh, ("CG", degree)) u = Function(V) cmap = fem.create_coordinate_map(mesh.ufl_domain()) mesh.geometry.coord_mapping = cmap u.interpolate(e2) intu = assemble_scalar(u * dx(metadata={"quadrature_degree": 50})) intu = MPI.sum(mesh.mpi_comm(), intu) nodes = [0, 3, 10, 11, 12] ref = sympy_scipy(points, nodes, L, H) assert ref == pytest.approx(intu, rel=1e-4)
def perform_test(points, cells): mesh = cpp.mesh.Mesh(MPI.comm_world, CellType.tetrahedron, points, np.array(cells), [], cpp.mesh.GhostMode.none) mesh.geometry.coord_mapping = fem.create_coordinate_map(mesh) V = FunctionSpace(mesh, (space_type, order)) f = Function(V) output = [] for dof in range(len(f.vector[:])): f.vector[:] = np.zeros(len(f.vector[:])) f.vector[dof] = 1 points = np.array([[1 / 3, 1 / 3, 1 / 3], [1 / 3, 1 / 3, 1 / 3]]) cells = np.array([0, 1]) result = f.eval(points, cells) normal = np.array([1., 1., 1.]) output.append(result.dot(normal)) return output
def test_dof_positions(cell_type, space_type): """Checks that dofs on shared triangle edges match up""" mesh = randomly_ordered_mesh(cell_type) if cell_type == "triangle": entities_per_cell = [3, 3, 1] elif cell_type == "quadrilateral": entities_per_cell = [4, 4, 1] elif cell_type == "tetrahedron": entities_per_cell = [4, 6, 4, 1] elif cell_type == "hexahedron": entities_per_cell = [8, 12, 6, 1] # Get coordinates of dofs and edges and check that they are the same # for each global dof number coord_dofs = mesh.geometry.dofmap x_g = mesh.geometry.x tdim = mesh.topology.dim cmap = fem.create_coordinate_map(mesh.mpi_comm(), mesh.ufl_domain()) mesh.topology.create_entity_permutations() perms = mesh.topology.get_cell_permutation_info() V = FunctionSpace(mesh, space_type) entities = {i: {} for i in range(1, tdim)} for cell in range(coord_dofs.num_nodes): # Push coordinates forward X = V.element.interpolation_points V.element.apply_dof_transformation(X, perms[cell], tdim) x = X.copy() xg = x_g[coord_dofs.links(cell), :tdim] cmap.push_forward(x, X, xg) dofs = V.dofmap.cell_dofs(cell) for entity_dim in range(1, tdim): entity_dofs_local = [] for i in range(entities_per_cell[entity_dim]): entity_dofs_local += list( V.dofmap.dof_layout.entity_dofs(entity_dim, i)) entity_dofs = [dofs[i] for i in entity_dofs_local] for i, j in zip(entity_dofs, x[entity_dofs_local]): if i in entities[entity_dim]: assert np.allclose(j, entities[entity_dim][i]) else: entities[entity_dim][i] = j
def Mesh(comm, cell_type, x, cells, ghosts, degree=1, ghost_mode=cpp.mesh.GhostMode.none): """Crete a mesh from topology and geometry data""" cell = ufl.Cell(cpp.mesh.to_string(cell_type), geometric_dimension=x.shape[1]) domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell, degree)) cmap = fem.create_coordinate_map(domain) mesh = cpp.mesh.Mesh(comm, cell_type, x, cells, cmap, ghosts, ghost_mode) domain._ufl_cargo = mesh mesh._ufl_domain = domain return mesh
def xtest_read_write_p2_function(tempdir): mesh = cpp.generation.UnitDiscMesh.create(MPI.comm_world, 3, cpp.mesh.GhostMode.none) gdim = mesh.geometry.dim cmap = fem.create_coordinate_map(mesh.ufl_domain()) mesh.geometry.coord_mapping = cmap Q = FunctionSpace(mesh, ("Lagrange", 2)) F = Function(Q) if has_petsc_complex: def expr_eval(x): return x[0] + 1.0j * x[0] F.interpolate(expr_eval) else: def expr_eval(x): return x[0] F.interpolate(expr_eval) filename = os.path.join(tempdir, "tri6_function.xdmf") with XDMFFile(mesh.mpi_comm(), filename, encoding=XDMFFile.Encoding.HDF5) as xdmf: xdmf.write(F) Q = VectorFunctionSpace(mesh, ("Lagrange", 1)) F = Function(Q) if has_petsc_complex: def expr_eval(x): return x[:gdim] + 1.0j * x[:gdim] F.interpolate(expr_eval) else: def expr_eval(x): return x[:gdim] F.interpolate(expr_eval) filename = os.path.join(tempdir, "tri6_vector_function.xdmf") with XDMFFile(mesh.mpi_comm(), filename, encoding=XDMFFile.Encoding.HDF5) as xdmf: xdmf.write(F)
def read_mesh(self, name="mesh", xpath="/Xdmf/Domain"): # Read mesh data from file cell_type, x, cells = super().read_mesh_data(name, xpath) # Construct the geometry map cell = ufl.Cell(cpp.mesh.to_string(cell_type[0]), geometric_dimension=x.shape[1]) domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell, cell_type[1])) cmap = fem.create_coordinate_map(domain) # Build the mesh mesh = cpp.mesh.create(self.comm(), cpp.graph.AdjacencyList64(cells), cmap, x, cpp.mesh.GhostMode.none) mesh.name = name domain._ufl_cargo = mesh mesh._ufl_domain = domain return mesh
def test_higher_order_tetra_coordinate_map(order): """ Computes physical coordinates of a cell, based on the coordinate map. """ celltype = CellType.tetrahedron points = np.array([[0, 0, 0], [1, 0, 0], [0, 2, 0], [0, 0, 3], [0, 4 / 3, 1], [0, 2 / 3, 2], [2 / 3, 0, 1], [1 / 3, 0, 2], [2 / 3, 2 / 3, 0], [1 / 3, 4 / 3, 0], [0, 0, 1], [0, 0, 2], [0, 2 / 3, 0], [0, 4 / 3, 0], [1 / 3, 0, 0], [2 / 3, 0, 0], [1 / 3, 2 / 3, 1], [0, 2 / 3, 1], [1 / 3, 0, 1], [1 / 3, 2 / 3, 0]]) if order == 1: points = np.array( [points[0, :], points[1, :], points[2, :], points[3, :]]) elif order == 2: points = np.array([ points[0, :], points[1, :], points[2, :], points[3, :], [0, 1, 3 / 2], [1 / 2, 0, 3 / 2], [1 / 2, 1, 0], [0, 0, 3 / 2], [0, 1, 0], [1 / 2, 0, 0] ]) 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", order)) X = V.element.dof_reference_coordinates() coord_dofs = mesh.geometry.dofmap x_g = mesh.geometry.x cmap = fem.create_coordinate_map(mesh.mpi_comm(), mesh.ufl_domain()) 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 = np.zeros(X.shape) cmap.push_forward(x, X, x_coord_new) assert (np.allclose(x[:, 0], X[:, 0])) assert (np.allclose(x[:, 1], 2 * X[:, 1])) assert (np.allclose(x[:, 2], 3 * X[:, 2]))
def test_second_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--6--2 | | | | | | 7 8 5 | | | | *-----* 0--4--1 """ points = np.array([[0, 0, 0], [L, 0, 0], [L, H, Z], [0, H, Z], [L / 2, 0, 0], [L, H / 2, 0], [L / 2, H, Z], [0, H / 2, 0], [L / 2, H / 2, 0], [2 * L, 0, 0], [2 * L, H, Z]]) cells = np.array([[0, 1, 2, 3, 4, 5, 6, 7, 8]]) 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", 2)) 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, 7] ref = sympy_scipy(points, nodes, L, H) assert ref == pytest.approx(intu, rel=1e-6)
def test_second_order_tri(): # Test second order mesh by computing volume of two cells # *-----*-----* 3----6-----2 # | \ | | \ | # | \ | | \ | # * * * 7 8 5 # | \ | | \ | # | \ | | \ | # *-----*-----* 0----4-----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], [L / 2, 0, 0], [L, H / 2, 0], [L / 2, H, Z], [0, H / 2, 0], [L / 2, H / 2, 0]]) cells = np.array([[0, 1, 3, 4, 8, 7], [1, 2, 3, 5, 6, 8]]) cells = permute_cell_ordering( cells, permutation_vtk_to_dolfin(CellType.triangle, cells.shape[1])) mesh = Mesh(MPI.comm_world, CellType.triangle, points, cells, [], GhostMode.none) def e2(x): return x[2] + x[0] * x[1] degree = mesh.degree() # Interpolate function V = FunctionSpace(mesh, ("CG", degree)) 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, metadata={"quadrature_degree": 20})) intu = MPI.sum(mesh.mpi_comm(), intu) nodes = [0, 3, 7] ref = sympy_scipy(points, nodes, L, H) assert ref == pytest.approx(intu, rel=1e-6)
def test_higher_order_tetra_coordinate_map(order): """ Computes physical coordinates of a cell, based on the coordinate map. """ celltype = CellType.tetrahedron points = np.array([[0, 0, 0], [1, 0, 0], [0, 2, 0], [0, 0, 3], [0, 4 / 3, 1], [0, 2 / 3, 2], [2 / 3, 0, 1], [1 / 3, 0, 2], [2 / 3, 2 / 3, 0], [1 / 3, 4 / 3, 0], [0, 0, 1], [0, 0, 2], [0, 2 / 3, 0], [0, 4 / 3, 0], [1 / 3, 0, 0], [2 / 3, 0, 0], [1 / 3, 2 / 3, 1], [0, 2 / 3, 1], [1 / 3, 0, 1], [1 / 3, 2 / 3, 0]]) if order == 1: points = np.array( [points[0, :], points[1, :], points[2, :], points[3, :]]) elif order == 2: points = np.array([ points[0, :], points[1, :], points[2, :], points[3, :], [0, 1, 3 / 2], [1 / 2, 0, 3 / 2], [1 / 2, 1, 0], [0, 0, 3 / 2], [0, 1, 0], [1 / 2, 0, 0] ]) cells = np.array([range(len(points))]) mesh = Mesh(MPI.comm_world, celltype, points, cells, [], GhostMode.none) V = FunctionSpace(mesh, ("Lagrange", order)) X = V.element.dof_reference_coordinates() coord_dofs = mesh.coordinate_dofs().entity_points() x_g = mesh.geometry.points cmap = fem.create_coordinate_map(mesh.ufl_domain()) 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[0, node], :mesh.geometry.dim] i += 1 x = np.zeros(X.shape) cmap.push_forward(x, X, x_coord_new) assert (np.allclose(x[:, 0], X[:, 0])) assert (np.allclose(x[:, 1], 2 * X[:, 1])) assert (np.allclose(x[:, 2], 3 * X[:, 2]))
def test_read_write_p2_mesh(tempdir, encoding): cell = ufl.Cell("triangle", geometric_dimension=2) element = ufl.VectorElement("Lagrange", cell, 2) domain = ufl.Mesh(element) cmap = fem.create_coordinate_map(domain) mesh = cpp.generation.UnitDiscMesh.create(MPI.COMM_WORLD, 3, cmap, cpp.mesh.GhostMode.none) filename = os.path.join(tempdir, "tri6_mesh.xdmf") with XDMFFile(mesh.mpi_comm(), filename, "w", encoding=encoding) as xdmf: xdmf.write_mesh(mesh) with XDMFFile(mesh.mpi_comm(), filename, "r", encoding=encoding) as xdmf: mesh2 = xdmf.read_mesh() assert mesh.topology.index_map(0).size_global == mesh2.topology.index_map( 0).size_global dim = mesh.topology.dim assert mesh.topology.index_map( dim).size_global == mesh2.topology.index_map(dim).size_global
def unit_cell(cell_type, random_order=True): if cell_type == CellType.interval: points = np.array([[0.], [1.]]) if cell_type == CellType.triangle: # Define equilateral triangle with area 1 root = 3**0.25 # 4th root of 3 points = np.array([[0., 0.], [2 / root, 0.], [1 / root, root]]) elif cell_type == CellType.tetrahedron: # Define regular tetrahedron with volume 1 s = 2**0.5 * 3**(1 / 3) # side length points = np.array([[0., 0., 0.], [s, 0., 0.], [s / 2, s * np.sqrt(3) / 2, 0.], [s / 2, s / 2 / np.sqrt(3), s * np.sqrt(2 / 3)]]) elif cell_type == CellType.quadrilateral: # Define unit quadrilateral (area 1) points = np.array([[0., 0.], [1., 0.], [0., 1.], [1., 1.]]) elif cell_type == CellType.hexahedron: # Define unit hexahedron (volume 1) points = np.array([[0., 0., 0.], [1., 0., 0.], [0., 1., 0.], [1., 1., 0.], [0., 0., 1.], [1., 0., 1.], [0., 1., 1.], [1., 1., 1.]]) num_points = len(points) # Randomly number the points and create the mesh order = list(range(num_points)) if random_order: shuffle(order) ordered_points = np.zeros(points.shape) for i, j in enumerate(order): ordered_points[j] = points[i] cells = np.array([order]) mesh = Mesh(MPI.comm_world, cell_type, ordered_points, cells, [], cpp.mesh.GhostMode.none) mesh.geometry.coord_mapping = fem.create_coordinate_map(mesh) mesh.create_connectivity_all() return mesh
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 = 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] V = FunctionSpace(mesh, ("CG", 4)) 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, 5, 10, 15, 20] ref = sympy_scipy(points, nodes, 2 * L, H) assert ref == pytest.approx(intu, rel=1e-5)
def test_nth_order_triangle(order): num_nodes = (order + 1) * (order + 2) / 2 cells = np.array([range(int(num_nodes))]) cells = permute_cell_ordering( cells, permutation_vtk_to_dolfin(CellType.triangle, cells.shape[1])) if order == 1: points = np.array([[0.00000, 0.00000, 0.00000], [1.00000, 0.00000, 0.00000], [0.00000, 1.00000, 0.00000]]) elif order == 2: points = np.array([[0.00000, 0.00000, 0.00000], [1.00000, 0.00000, 0.00000], [0.00000, 1.00000, 0.00000], [0.50000, 0.00000, 0.00000], [0.50000, 0.50000, -0.25000], [0.00000, 0.50000, -0.25000]]) elif order == 3: points = np.array([[0.00000, 0.00000, 0.00000], [1.00000, 0.00000, 0.00000], [0.00000, 1.00000, 0.00000], [0.33333, 0.00000, 0.00000], [0.66667, 0.00000, 0.00000], [0.66667, 0.33333, -0.11111], [0.33333, 0.66667, 0.11111], [0.00000, 0.66667, 0.11111], [0.00000, 0.33333, -0.11111], [0.33333, 0.33333, -0.11111]]) elif order == 4: points = np.array([[0.00000, 0.00000, 0.00000], [1.00000, 0.00000, 0.00000], [0.00000, 1.00000, 0.00000], [0.25000, 0.00000, 0.00000], [0.50000, 0.00000, 0.00000], [0.75000, 0.00000, 0.00000], [0.75000, 0.25000, -0.06250], [0.50000, 0.50000, 0.06250], [0.25000, 0.75000, -0.06250], [0.00000, 0.75000, -0.06250], [0.00000, 0.50000, 0.06250], [0.00000, 0.25000, -0.06250], [0.25000, 0.25000, -0.06250], [0.50000, 0.25000, -0.06250], [0.25000, 0.50000, 0.06250]]) elif order == 5: points = np.array([[0.00000, 0.00000, 0.00000], [1.00000, 0.00000, 0.00000], [0.00000, 1.00000, 0.00000], [0.20000, 0.00000, 0.00000], [0.40000, 0.00000, 0.00000], [0.60000, 0.00000, 0.00000], [0.80000, 0.00000, 0.00000], [0.80000, 0.20000, -0.04000], [0.60000, 0.40000, 0.04000], [0.40000, 0.60000, -0.04000], [0.20000, 0.80000, 0.04000], [0.00000, 0.80000, 0.04000], [0.00000, 0.60000, -0.04000], [0.00000, 0.40000, 0.04000], [0.00000, 0.20000, -0.04000], [0.20000, 0.20000, -0.04000], [0.60000, 0.20000, -0.04000], [0.20000, 0.60000, -0.04000], [0.40000, 0.20000, -0.04000], [0.40000, 0.40000, 0.04000], [0.20000, 0.40000, 0.04000]]) elif order == 6: points = np.array([[0.00000, 0.00000, 0.00000], [1.00000, 0.00000, 0.00000], [0.00000, 1.00000, 0.00000], [0.16667, 0.00000, 0.00000], [0.33333, 0.00000, 0.00000], [0.50000, 0.00000, 0.00000], [0.66667, 0.00000, 0.00000], [0.83333, 0.00000, 0.00000], [0.83333, 0.16667, -0.00463], [0.66667, 0.33333, 0.00463], [0.50000, 0.50000, -0.00463], [0.33333, 0.66667, 0.00463], [0.16667, 0.83333, -0.00463], [0.00000, 0.83333, -0.00463], [0.00000, 0.66667, 0.00463], [0.00000, 0.50000, -0.00463], [0.00000, 0.33333, 0.00463], [0.00000, 0.16667, -0.00463], [0.16667, 0.16667, -0.00463], [0.66667, 0.16667, -0.00463], [0.16667, 0.66667, 0.00463], [0.33333, 0.16667, -0.00463], [0.50000, 0.16667, -0.00463], [0.50000, 0.33333, 0.00463], [0.33333, 0.50000, -0.00463], [0.16667, 0.50000, -0.00463], [0.16667, 0.33333, 0.00463], [0.33333, 0.33333, 0.00463]]) elif order == 7: points = np.array([[0.00000, 0.00000, 0.00000], [1.00000, 0.00000, 0.00000], [0.00000, 1.00000, 0.00000], [0.14286, 0.00000, 0.00000], [0.28571, 0.00000, 0.00000], [0.42857, 0.00000, 0.00000], [0.57143, 0.00000, 0.00000], [0.71429, 0.00000, 0.00000], [0.85714, 0.00000, 0.00000], [0.85714, 0.14286, -0.02041], [0.71429, 0.28571, 0.02041], [0.57143, 0.42857, -0.02041], [0.42857, 0.57143, 0.02041], [0.28571, 0.71429, -0.02041], [0.14286, 0.85714, 0.02041], [0.00000, 0.85714, 0.02041], [0.00000, 0.71429, -0.02041], [0.00000, 0.57143, 0.02041], [0.00000, 0.42857, -0.02041], [0.00000, 0.28571, 0.02041], [0.00000, 0.14286, -0.02041], [0.14286, 0.14286, -0.02041], [0.71429, 0.14286, -0.02041], [0.14286, 0.71429, -0.02041], [0.28571, 0.14286, -0.02041], [0.42857, 0.14286, -0.02041], [0.57143, 0.14286, -0.02041], [0.57143, 0.28571, 0.02041], [0.42857, 0.42857, -0.02041], [0.28571, 0.57143, 0.02041], [0.14286, 0.57143, 0.02041], [0.14286, 0.42857, -0.02041], [0.14286, 0.28571, 0.02041], [0.28571, 0.28571, 0.02041], [0.42857, 0.28571, 0.02041], [0.28571, 0.42857, -0.02041]]) # Higher order tests are too slow elif order == 8: points = np.array([[0.00000, 0.00000, 0.00000], [1.00000, 0.00000, 0.00000], [0.00000, 1.00000, 0.00000], [0.12500, 0.00000, 0.00000], [0.25000, 0.00000, 0.00000], [0.37500, 0.00000, 0.00000], [0.50000, 0.00000, 0.00000], [0.62500, 0.00000, 0.00000], [0.75000, 0.00000, 0.00000], [0.87500, 0.00000, 0.00000], [0.87500, 0.12500, -0.00195], [0.75000, 0.25000, 0.00195], [0.62500, 0.37500, -0.00195], [0.50000, 0.50000, 0.00195], [0.37500, 0.62500, -0.00195], [0.25000, 0.75000, 0.00195], [0.12500, 0.87500, -0.00195], [0.00000, 0.87500, -0.00195], [0.00000, 0.75000, 0.00195], [0.00000, 0.62500, -0.00195], [0.00000, 0.50000, 0.00195], [0.00000, 0.37500, -0.00195], [0.00000, 0.25000, 0.00195], [0.00000, 0.12500, -0.00195], [0.12500, 0.12500, -0.00195], [0.75000, 0.12500, -0.00195], [0.12500, 0.75000, 0.00195], [0.25000, 0.12500, -0.00195], [0.37500, 0.12500, -0.00195], [0.50000, 0.12500, -0.00195], [0.62500, 0.12500, -0.00195], [0.62500, 0.25000, 0.00195], [0.50000, 0.37500, -0.00195], [0.37500, 0.50000, 0.00195], [0.25000, 0.62500, -0.00195], [0.12500, 0.62500, -0.00195], [0.12500, 0.50000, 0.00195], [0.12500, 0.37500, -0.00195], [0.12500, 0.25000, 0.00195], [0.25000, 0.25000, 0.00195], [0.50000, 0.25000, 0.00195], [0.25000, 0.50000, 0.00195], [0.37500, 0.25000, 0.00195], [0.37500, 0.37500, -0.00195], [0.25000, 0.37500, -0.00195]]) mesh = Mesh(MPI.comm_world, CellType.triangle, points, cells, [], GhostMode.none) # Find nodes corresponding to y axis nodes = [] for j in range(points.shape[0]): if np.isclose(points[j][0], 0): nodes.append(j) def e2(x): return x[2] + x[0] * x[1] # For solution to be in functionspace V = FunctionSpace(mesh, ("CG", max(2, order))) u = Function(V) cmap = fem.create_coordinate_map(mesh.ufl_domain()) mesh.geometry.coord_mapping = cmap u.interpolate(e2) quad_order = 30 intu = assemble_scalar(u * dx(metadata={"quadrature_degree": quad_order})) intu = MPI.sum(mesh.mpi_comm(), intu) ref = scipy_one_cell(points, nodes) assert ref == pytest.approx(intu, rel=3e-3)
def two_unit_cells(cell_type, agree=False, random_order=True, return_order=False): if cell_type == CellType.interval: points = np.array([[0.], [1.], [-1.]]) if agree: cells = [[0, 1], [2, 0]] else: cells = [[0, 1], [0, 2]] if cell_type == CellType.triangle: # Define equilateral triangles with area 1 root = 3**0.25 # 4th root of 3 points = np.array([[0., 0.], [2 / root, 0.], [1 / root, root], [1 / root, -root]]) if agree: cells = [[0, 1, 2], [0, 3, 1]] else: cells = [[0, 1, 2], [1, 0, 3]] elif cell_type == CellType.tetrahedron: # Define regular tetrahedra with volume 1 s = 2**0.5 * 3**(1 / 3) # side length points = np.array([[0., 0., 0.], [s, 0., 0.], [s / 2, s * np.sqrt(3) / 2, 0.], [s / 2, s / 2 / np.sqrt(3), s * np.sqrt(2 / 3)], [s / 2, s / 2 / np.sqrt(3), -s * np.sqrt(2 / 3)]]) if agree: cells = [[0, 1, 2, 3], [0, 1, 4, 2]] else: cells = [[0, 1, 2, 3], [0, 2, 1, 4]] elif cell_type == CellType.quadrilateral: # Define unit quadrilaterals (area 1) points = np.array([[0., 0.], [1., 0.], [0., 1.], [1., 1.], [0., -1.], [1., -1.]]) if agree: cells = [[0, 1, 2, 3], [4, 5, 0, 1]] else: cells = [[0, 1, 2, 3], [5, 1, 4, 0]] elif cell_type == CellType.hexahedron: # Define unit hexahedra (volume 1) points = np.array([[0., 0., 0.], [1., 0., 0.], [0., 1., 0.], [1., 1., 0.], [0., 0., 1.], [1., 0., 1.], [0., 1., 1.], [1., 1., 1.], [0., 0., -1.], [1., 0., -1.], [0., 1., -1.], [1., 1., -1.]]) if agree: cells = [[0, 1, 2, 3, 4, 5, 6, 7], [8, 9, 10, 11, 0, 1, 2, 3]] else: cells = [[0, 1, 2, 3, 4, 5, 6, 7], [9, 11, 8, 10, 1, 3, 0, 2]] num_points = len(points) # Randomly number the points and create the mesh order = list(range(num_points)) if random_order: shuffle(order) ordered_points = np.zeros(points.shape) for i, j in enumerate(order): ordered_points[j] = points[i] ordered_cells = np.array([[order[i] for i in c] for c in cells]) mesh = Mesh(MPI.comm_world, cell_type, ordered_points, ordered_cells, [], cpp.mesh.GhostMode.none) mesh.geometry.coord_mapping = fem.create_coordinate_map(mesh) mesh.create_connectivity_all() if return_order: return mesh, order return mesh
def test_triangle_dof_ordering(space_type): """Checks that dofs on shared triangle edges match up""" # Create a mesh domain = ufl.Mesh(ufl.VectorElement("Lagrange", "triangle", 1)) if MPI.COMM_WORLD.rank == 0: N = 6 # Create a grid of points [0, 0.5, ..., 9.5]**2, then order them # in a random order temp_points = np.array([[x / 2, y / 2] for x in range(N) for y in range(N)]) 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] # Make triangle cells using the randomly ordered points cells = [] for x in range(N - 1): for y in range(N - 1): a = N * y + x # Adds two triangle cells: # a+N -- a+N+1 # | / | # | / | # | / | # a --- a+1 for cell in [[a, a + 1, a + N + 1], [a, a + N + 1, a + N]]: cells.append([order[i] for i in cell]) # On process 0, input mesh data and distribute to other # processes mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain) else: mesh = create_mesh(MPI.COMM_WORLD, np.ndarray((0, 3)), np.ndarray((0, 2)), domain) V = FunctionSpace(mesh, space_type) dofmap = V.dofmap edges = {} # Get coordinates of dofs and edges and check that they are the same # for each global dof number X = V.element.dof_reference_coordinates() coord_dofs = mesh.geometry.dofmap x_g = mesh.geometry.x cmap = fem.create_coordinate_map(mesh.ufl_domain()) for cell_n in range(coord_dofs.num_nodes): dofs = dofmap.cell_dofs(cell_n) x_coord_new = np.zeros([3, 2]) for v in range(3): x_coord_new[v] = x_g[coord_dofs.links(cell_n)[v], :2] x = X.copy() cmap.push_forward(x, X, x_coord_new) edge_dofs_local = [] for i in range(3): edge_dofs_local += list(dofmap.dof_layout.entity_dofs(1, i)) edge_dofs = [dofs[i] for i in edge_dofs_local] for i, j in zip(edge_dofs, x[edge_dofs_local]): if i in edges: assert np.allclose(j, edges[i]) else: edges[i] = j