def __init__(self, p1dg_space, time_dependent_mesh=True): """ :arg p1dg_space: P1DG function space """ assert_function_space(p1dg_space, ['Discontinuous Lagrange', 'DQ'], 1) self.is_vector = p1dg_space.value_size > 1 if self.is_vector: p1dg_scalar_space = FunctionSpace(p1dg_space.mesh(), 'DG', 1) super(VertexBasedP1DGLimiter, self).__init__(p1dg_scalar_space) else: super(VertexBasedP1DGLimiter, self).__init__(p1dg_space) self.mesh = self.P0.mesh() self.is_2d = self.mesh.geometric_dimension() == 2 self.time_dependent_mesh = time_dependent_mesh # for vertical 2d in non-hydrostatic (nh) extension, WPan 2020-02-11 self.mesh_is_extruded = (p1dg_space.mesh().ufl_cell() not in (ufl.Cell('triangle'), ufl.Cell('interval'))) # NOTE below use non-loopy kernel which seems to run faster, TODO check, WPan 2020-03-27 # Update min and max loop self._min_max_loop = """ for (int i = 0; i < maxq.dofs; i++) { maxq[i] = fmax(maxq[i], q[0]); minq[i] = fmin(minq[i], q[0]); } """ # Perform limiting loop self._limit_kernel = """
def test_facetarea(self): "Testing assembly of facet area for embedded meshes" # Boundary mesh not running in parallel if MPI.num_processes() > 1: return area = ufl.Cell("interval", geometric_dimension=2).facet_area a = area * ds b = assemble(a, mesh=self.bottom1) self.assertAlmostEqual(b, 2.0) area = ufl.Cell("interval", geometric_dimension=3).facet_area a = area * ds b = assemble(a, mesh=self.bottom3) self.assertAlmostEqual(b, 2.0) area = ufl.Cell("triangle", geometric_dimension=2).facet_area a = area * ds b0 = assemble(a, mesh=UnitSquareMesh(self.m, self.m)) area = ufl.Cell("triangle", geometric_dimension=3).facet_area a = area * ds b1 = assemble(a, mesh=self.bottom2) self.assertAlmostEqual(b0, b1)
def cell(dimDomainOrGrid): if isinstance(dimDomainOrGrid, ufl.Cell): return dimDomainOrGrid try: dimWorld = int(dimDomainOrGrid.dimWorld) dimDomain = int(dimDomainOrGrid.dimGrid) except: dimDomain = dimDomainOrGrid if isinstance(dimDomain, tuple): if len(dimDomain) != 2: raise Exception( 'dimDomain tuple must contain exactly two elements.') dimWorld = int(dimDomain[1]) dimDomain = dimDomain[0] else: dimWorld = int(dimDomain) if dimDomain == 1: return ufl.Cell("interval", dimWorld) elif dimDomain == 2: return ufl.Cell("triangle", dimWorld) elif dimDomain == 3: return ufl.Cell("tetrahedron", dimWorld) elif dimDomain == 4: # add 4d cell types to ufl data structures _patchufl4d() return ufl.Cell("pentachoron", dimWorld) else: raise NotImplementedError('UFL cell not implemented for dimension ' + str(dimDomain) + '.')
def extension_cell(o): ''' UFL cell corresponding to extension of o[cell] to facets(triangles) in 3d or lines in (2d) ''' # Space if hasattr(o, 'ufl_cell'): return extension_cell(o.ufl_cell()) # Foo like if hasattr(o, 'ufl_element'): return extension_cell(o.ufl_element().cell()) # Elm if hasattr(o, 'cell'): return extension_cell(o.cell()) gdim = o.geometric_dimension() assert gdim in (2, 3) assert o.topological_dimension() == 1 # Always extend from 1 # Line in 3d extends to 'cylinder' surface around it if gdim == 3: return ufl.Cell('triangle', gdim) # Line in 2d extends to line in 3d else: return ufl.Cell('interval', gdim)
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_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_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 _process_args(cls, mesh, family, degree=None, dim=None, vfamily=None, vdegree=None, **kwargs): # VectorFunctionSpace dimension defaults to the geometric dimension of the mesh. dim = dim or mesh.ufl_cell().geometric_dimension() if isinstance(mesh, mesh_t.ExtrudedMesh) and isinstance( family, ufl.OuterProductElement): element = ufl.OuterProductVectorElement(family, dim=dim) elif isinstance(mesh, mesh_t.ExtrudedMesh ) and vfamily is not None and vdegree is not None: la = ufl.FiniteElement(family, domain=mesh._old_mesh.ufl_cell(), degree=degree) lb = ufl.FiniteElement(vfamily, domain=ufl.Cell("interval", 1), degree=vdegree) element = ufl.OuterProductVectorElement(la, lb, dim=dim) else: element = ufl.VectorElement(family, domain=mesh.ufl_cell(), degree=degree, dim=dim) return (mesh, mesh, element), dict(kwargs, dim=dim)
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 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 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 _process_args(cls, mesh, family, degree=None, vfamily=None, vdegree=None, **kwargs): # Two choices: # 1) pass in mesh, family, degree to generate a simple function space # 2) set up the function space using FiniteElement, EnrichedElement, # OuterProductElement and so on if isinstance(family, ufl.FiniteElementBase): # Second case... element = family else: # First case... if isinstance(mesh, mesh_t.ExtrudedMesh ) and vfamily is not None and vdegree is not None: # if extruded mesh, make the OPE la = ufl.FiniteElement(family, domain=mesh._old_mesh.ufl_cell(), degree=degree) # if second element was passed in, use in lb = ufl.FiniteElement(vfamily, domain=ufl.Cell("interval", 1), degree=vdegree) # now make the OPE element = ufl.OuterProductElement(la, lb) else: # if not an extruded mesh, just make the element element = ufl.FiniteElement(family, domain=mesh.ufl_cell(), degree=degree) return (mesh, mesh, element), kwargs
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 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 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 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 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)
def test_empty_rank_mesh(): """Construction of mesh where some ranks are empty""" comm = MPI.COMM_WORLD cell_type = CellType.triangle tdim = 2 domain = ufl.Mesh( ufl.VectorElement("Lagrange", ufl.Cell(cell_type.name), 1)) def partitioner(comm, nparts, local_graph, num_ghost_nodes, ghosting): """Leave cells on the curent rank""" dest = np.full(len(cells), comm.rank, dtype=np.int32) return graph.create_adjacencylist(dest) if comm.rank == 0: cells = np.array([[0, 1, 2], [0, 2, 3]], dtype=np.int64) cells = graph.create_adjacencylist(cells) x = np.array([[0., 0.], [1., 0.], [1., 1.], [0., 1.]]) else: cells = graph.create_adjacencylist(np.empty((0, 3), dtype=np.int64)) x = np.empty((0, 2), dtype=np.float64) mesh = _mesh.create_mesh(comm, cells, x, domain, GhostMode.none, partitioner) topology = mesh.topology # Check number of vertices vmap = topology.index_map(0) assert vmap.size_local == x.shape[0] assert vmap.num_ghosts == 0 # Check number of cells cmap = topology.index_map(tdim) assert cmap.size_local == cells.num_nodes assert cmap.num_ghosts == 0 # Check number of edges topology.create_entities(1) emap = topology.index_map(1) e_to_v = topology.connectivity(1, 0) assert emap.num_ghosts == 0 if comm.rank == 0: assert emap.size_local == 5 assert e_to_v.num_nodes == 5 assert len(e_to_v.array) == 10 else: assert emap.size_local == 0 assert len(e_to_v.array) == 0 assert e_to_v.num_nodes == 0 # Test creating and getting permutations doesn't throw an error mesh.topology.create_entity_permutations() mesh.topology.get_cell_permutation_info() mesh.topology.get_facet_permutations()
def test_second_order_fides(tempdir): """Check that fides throws error on second order mesh""" 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 pytest.raises(RuntimeError): FidesWriter(mesh.comm, filename, mesh)
def test_custom_partitioner(tempdir, Nx, cell_type): mpi_comm = MPI.COMM_WORLD Lx = mpi_comm.size points = [np.array([0, 0, 0]), np.array([Lx, Lx, Lx])] mesh = dolfinx.BoxMesh(mpi_comm, points, [Nx, Nx, Nx], cell_type, GhostMode.shared_facet) filename = os.path.join(tempdir, "u1_.xdmf") with XDMFFile(mpi_comm, filename, "w") as file: file.write_mesh(mesh) # Read all geometry data on all processes with XDMFFile(MPI.COMM_SELF, filename, "r") as file: x_global = file.read_geometry_data() # Read topology data with XDMFFile(MPI.COMM_WORLD, filename, "r") as file: cell_type = file.read_cell_type() x = file.read_geometry_data() topo = file.read_topology_data() num_local_coor = x.shape[0] all_sizes = mpi_comm.allgather(num_local_coor) all_sizes.insert(0, 0) all_ranges = np.cumsum(all_sizes) # Testing the premise: coordinates are read contiguously in chunks rank = mpi_comm.rank assert (np.all(x_global[all_ranges[rank]:all_ranges[rank + 1]] == x)) cell = ufl.Cell(dolfinx.cpp.mesh.to_string(cell_type[0])) domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell, cell_type[1])) # Partition mesh in layers, capture geometrical data and topological # data from outer scope def partitioner(*args): midpoints = np.mean(x_global[topo], axis=1) dest = np.floor(midpoints[:, 0] % mpi_comm.size) return dolfinx.cpp.graph.AdjacencyList_int32(dest) ghost_mode = GhostMode.none new_mesh = dolfinx.mesh.create_mesh(mpi_comm, topo, x, domain, ghost_mode, partitioner) new_mesh.topology.create_connectivity_all() tdim = new_mesh.topology.dim assert mesh.topology.index_map( tdim).size_global == new_mesh.topology.index_map(tdim).size_global num_cells = new_mesh.topology.index_map(tdim).size_local cell_midpoints = dolfinx.cpp.mesh.midpoints(new_mesh, tdim, range(num_cells)) assert num_cells > 0 assert np.all(cell_midpoints[:, 0] >= mpi_comm.rank) assert np.all(cell_midpoints[:, 0] <= mpi_comm.rank + 1)
def test_assemble_empty_rank_mesh(): """Assembly on mesh where some ranks are empty""" comm = MPI.COMM_WORLD cell_type = CellType.triangle domain = ufl.Mesh( ufl.VectorElement("Lagrange", ufl.Cell(cell_type.name), 1)) def partitioner(comm, nparts, local_graph, num_ghost_nodes, ghosting): """Leave cells on the curent rank""" dest = np.full(len(cells), comm.rank, dtype=np.int32) return graph.create_adjacencylist(dest) if comm.rank == 0: # Put cells on rank 0 cells = np.array([[0, 1, 2], [0, 2, 3]], dtype=np.int64) cells = graph.create_adjacencylist(cells) x = np.array([[0., 0.], [1., 0.], [1., 1.], [0., 1.]]) else: # No cells onm other ranks cells = graph.create_adjacencylist(np.empty((0, 3), dtype=np.int64)) x = np.empty((0, 2), dtype=np.float64) mesh = create_mesh(comm, cells, x, domain, GhostMode.none, partitioner) V = FunctionSpace(mesh, ("Lagrange", 2)) u, v = ufl.TrialFunction(V), ufl.TestFunction(V) f, k, zero = Function(V), Function(V), Function(V) f.x.array[:] = 10.0 k.x.array[:] = 1.0 zero.x.array[:] = 0.0 a = form(inner(k * u, v) * dx + inner(zero * u, v) * ds) L = form(inner(f, v) * dx + inner(zero, v) * ds) M = form(2 * k * dx + k * ds) sum = comm.allreduce(assemble_scalar(M), op=MPI.SUM) assert sum == pytest.approx(6.0) # Assemble A = assemble_matrix(a) A.assemble() b = assemble_vector(L) b.ghostUpdate(addv=PETSc.InsertMode.ADD, mode=PETSc.ScatterMode.REVERSE) # Solve ksp = PETSc.KSP() ksp.create(mesh.comm) ksp.setOperators(A) ksp.setTolerances(rtol=1.0e-9, max_it=50) ksp.setFromOptions() x = b.copy() ksp.solve(b, x) assert np.allclose(x.array, 10.0)
def test_cell_volume(self): "Testing assembly of volume for embedded meshes" # Boundary mesh not running in parallel if MPI.num_processes() > 1: return volume = ufl.Cell("interval", geometric_dimension=2).volume a = volume * dx b = assemble(a, mesh=self.bottom1) self.assertAlmostEqual(b, 1.0 / self.m) volume = ufl.Cell("interval", geometric_dimension=3).volume a = volume * dx b = assemble(a, mesh=self.bottom3) self.assertAlmostEqual(b, 1.0 / self.m) volume = ufl.Cell("triangle", geometric_dimension=3).volume a = volume * dx b = assemble(a, mesh=self.bottom2) self.assertAlmostEqual(b, 1.0 / (2 * self.m * self.m))
def ufl_mesh_from_gmsh(gmsh_cell: int, gdim: int) -> ufl.Mesh: """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) scalar_element = ufl.FiniteElement("Lagrange", cell, degree, variant="equispaced") return ufl.Mesh(ufl.VectorElement(scalar_element))
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_distance_triangle(): gdim, shape, degree = 2, "triangle", 1 cell = ufl.Cell(shape, geometric_dimension=gdim) domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell, degree)) x = [[0., 0., 0.], [0., 1., 0.], [1., 1., 0.]] cells = [[0, 1, 2]] mesh = create_mesh(MPI.COMM_WORLD, cells, x, domain) assert squared_distance(mesh, mesh.topology.dim, [0], [-1.0, -1.0, 0.0]) == pytest.approx(2.0) assert squared_distance(mesh, mesh.topology.dim, [0], [-1.0, 0.5, 0.0]) == pytest.approx(1.0) assert squared_distance(mesh, mesh.topology.dim, [0], [0.5, 0.5, 0.0]) == pytest.approx(0.0)
def test_make_2(): coords = np.array([[0, 0, 2], [1, 0, 2], [1, 1, 2], [0, 1., 2]]) cells = np.array([[0, 1], [1, 2], [2, 3], [3, 0], [0, 2]]) mesh = make_line_mesh(coords, cells=cells) assert np.linalg.norm(mesh.coordinates() - coords) < 1E-13 cells = np.array([[0, 1], [1, 2], [2, 3], [0, 3], [0, 2]]) cells0 = np.array(map(sorted, mesh.cells())) assert np.linalg.norm(cells0 - cells) < 1E-13, mesh.cells() assert mesh.ufl_cell() == ufl.Cell('interval', 3)
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_distance_tetrahedron(): gdim = 3 shape = "tetrahedron" degree = 1 cell = ufl.Cell(shape, geometric_dimension=gdim) domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell, degree)) x = numpy.array([[0., 0., 0.], [0., 1., 0.], [0., 1., 1.], [1, 1., 1]]) cells = numpy.array([[0, 1, 2, 3]], dtype=numpy.int32) mesh = create_mesh(MPI.COMM_WORLD, cells, x, domain) assert cpp.geometry.squared_distance(mesh, mesh.topology.dim, 0, numpy.array([-1.0, -1.0, -1.0])) == pytest.approx(3.0) assert cpp.geometry.squared_distance(mesh, mesh.topology.dim, 0, numpy.array([-1.0, 0.5, 0.5])) == pytest.approx(1.0) assert cpp.geometry.squared_distance(mesh, mesh.topology.dim, 0, numpy.array([0.5, 0.5, 0.5])) == pytest.approx(0.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 = cells[:, perm_vtk(CellType.quadrilateral, cells.shape[1])] cell = ufl.Cell("quadrilateral", 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, ("CG", 3)) u = Function(V) u.interpolate(e2) intu = assemble_scalar(u * dx(mesh)) intu = mesh.mpi_comm().allreduce(intu, op=MPI.SUM) nodes = [0, 3, 10, 11] ref = sympy_scipy(points, nodes, 2 * L, H) assert ref == pytest.approx(intu, rel=1e-6)
def Mesh(comm, cell_type, x, cells, ghosts, degree=1, ghost_mode=cpp.mesh.GhostMode.none): """Create a mesh from topology and geometry data Note: this function is deprecated in favour of mesh.create """ cell = ufl.Cell(cpp.mesh.to_string(cell_type), geometric_dimension=x.shape[1]) domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell, degree)) return create_mesh(comm, cells, x, domain, ghost_mode)