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 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
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
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
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
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)
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)
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)
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)
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
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
def test_quadrilateral_mesh(order): random.seed(13) 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)] points += [[j / order, 1] for j in range(order + 1)] def coord_to_vertex(x, y): return (order + 1) * y + x # Define a cell using DOLFINx ordering cell = [coord_to_vertex(i, j) for i, j in [(0, 0), (order, 0), (0, order), (order, order)]] if order > 1: for i in range(1, order): cell.append(coord_to_vertex(i, 0)) for i in range(1, order): cell.append(coord_to_vertex(0, i)) for i in range(1, order): cell.append(coord_to_vertex(order, i)) for i in range(1, order): cell.append(coord_to_vertex(i, order)) for j in range(1, order): for i in range(1, order): cell.append(coord_to_vertex(i, j)) domain = ufl.Mesh(ufl.VectorElement( "Q", ufl.Cell("quadrilateral", geometric_dimension=2), order)) check_cell_volume(points, cell, domain, 1)
def ufl_domain(self): """Returns the ufl domain corresponding to the mesh.""" # Cache object to avoid recreating it a lot if not hasattr(self, "_ufl_domain"): self._ufl_domain = ufl.Mesh( self.ufl_coordinate_element(), ufl_id=self.ufl_id(), cargo=self) return self._ufl_domain
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
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)
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
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)
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)
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])
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
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 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)
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_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_tetrahedron_mesh(order): points = [] points += [[i / order, j / order, 0] for j in range(order + 1) for i in range(order + 1 - j)] for k in range(1, order): points += [[i / order, j / order + 0.1, k / order] for j in range(order + 1 - k) for i in range(order + 1 - k - j)] points += [[0, 0, 1]] def coord_to_vertex(x, y, z): return z * (3 * order**2 - 3 * order * z + 12 * order + z**2 - 6 * z + 11) // 6 + y * (2 * (order - z) + 3 - y) // 2 + x # Define a cell using dolfin ordering cell = [ coord_to_vertex(x, y, z) for x, y, z in [(0, 0, 0), (order, 0, 0), (0, order, 0), (0, 0, order)] ] if order > 1: for i in range(1, order): cell.append(coord_to_vertex(0, order - i, i)) for i in range(1, order): cell.append(coord_to_vertex(order - i, 0, i)) for i in range(1, order): cell.append(coord_to_vertex(order - i, i, 0)) for i in range(1, order): cell.append(coord_to_vertex(0, 0, i)) for i in range(1, order): cell.append(coord_to_vertex(0, i, 0)) for i in range(1, order): cell.append(coord_to_vertex(i, 0, 0)) for j in range(1, order): for i in range(1, order - j): cell.append(coord_to_vertex(order - i - j, i, j)) for j in range(1, order): for i in range(1, order - j): cell.append(coord_to_vertex(0, i, j)) for j in range(1, order): for i in range(1, order - j): cell.append(coord_to_vertex(i, 0, j)) for j in range(1, order): for i in range(1, order - j): cell.append(coord_to_vertex(i, j, 0)) for k in range(1, order): for j in range(1, order - k): for i in range(1, order - j - k): cell.append(coord_to_vertex(i, j, k)) domain = ufl.Mesh( ufl.VectorElement("Lagrange", ufl.Cell("tetrahedron", geometric_dimension=3), order)) check_cell_volume(points, cell, domain, 1 / 6)
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 ufl_mesh_from_gmsh(gmsh_cell: int, gdim: int): """ Create a UFL mesh from a Gmsh cell identifier and the geometric dimension. See: # http://gmsh.info//doc/texinfo/gmsh.html#MSH-file-format """ shape, degree = _gmsh_to_cells[gmsh_cell] cell = ufl.Cell(shape, geometric_dimension=gdim) return ufl.Mesh(ufl.VectorElement("Lagrange", cell, degree))
def ufl_domain(mesh): """Returns the ufl domain corresponding to the mesh.""" # Cache object to avoid recreating it a lot if not hasattr(mesh, "_ufl_domain"): mesh._ufl_domain = ufl.Mesh(mesh.ufl_coordinate_element(), ufl_id=mesh.ufl_id(), cargo=mesh) return mesh._ufl_domain
def create_quad_mesh(offset): """Creates a mesh of a single square element if offset = 0, or a trapezium element if |offset| > 0.""" x = np.array([[0, 0], [1, 0], [0, 0.5 + offset], [1, 0.5 - offset]]) cells = np.array([[0, 1, 2, 3]]) ufl_mesh = ufl.Mesh(ufl.VectorElement("Lagrange", "quadrilateral", 1)) mesh = create_mesh(MPI.COMM_WORLD, cells, x, ufl_mesh) return mesh
def test_second_order_vtx(tempdir): filename = os.path.join(tempdir, "mesh_fides.bp") points = np.array([[0, 0, 0], [1, 0, 0], [0.5, 0, 0]], dtype=np.float64) cells = np.array([[0, 1, 2]], dtype=np.int32) cell = ufl.Cell("interval", geometric_dimension=points.shape[1]) domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell, 2)) mesh = create_mesh(MPI.COMM_WORLD, cells, points, domain) with VTXWriter(mesh.comm, filename, mesh) as f: f.write(0.0)