def test_compute_closest_entity_1d(dim): ref_distance = 0.75 N = 16 points = np.array([[-ref_distance, 0, 0], [2 / N, 2 * ref_distance, 0]]) mesh = create_unit_interval(MPI.COMM_WORLD, N) tree = BoundingBoxTree(mesh, dim) num_entities_local = mesh.topology.index_map(dim).size_local + mesh.topology.index_map(dim).num_ghosts entities = np.arange(num_entities_local, dtype=np.int32) midpoint_tree = create_midpoint_tree(mesh, dim, entities) closest_entities = compute_closest_entity(tree, midpoint_tree, mesh, points) # Find which entity is colliding with known closest point on mesh p_c = np.array([[0, 0, 0], [2 / N, 0, 0]]) colliding_entity_bboxes = compute_collisions(tree, p_c) # Refine search by checking for actual collision if the entities are # cells if dim == mesh.topology.dim: colliding_cells = compute_colliding_cells(mesh, colliding_entity_bboxes, p_c) for i in range(points.shape[0]): # If colliding entity is on process if colliding_cells.links(i).size > 0: assert np.isin(closest_entities[i], colliding_cells.links(i)) else: for i in range(points.shape[0]): # Only check closest entity if any bounding box on the # process intersects with the point if colliding_entity_bboxes.links(i).size > 0: assert np.isin(closest_entities[i], colliding_entity_bboxes.links(i))
def test_ghost_facet_1d(): N = 40 mesh = create_unit_interval(MPI.COMM_WORLD, N, ghost_mode=GhostMode.shared_facet) assert mesh.topology.index_map(0).size_global == N + 1 assert mesh.topology.index_map(1).size_global == N
def mesh_factory(tdim, n, ghost_mode=GhostMode.shared_facet): if tdim == 1: return create_unit_interval(MPI.COMM_WORLD, n, ghost_mode=ghost_mode) elif tdim == 2: return create_unit_square(MPI.COMM_WORLD, n, n, ghost_mode=ghost_mode) elif tdim == 3: return create_unit_cube(MPI.COMM_WORLD, n, n, n, ghost_mode=ghost_mode)
def mesh_1d(): """Create 1D mesh with degenerate cell""" mesh1d = create_unit_interval(MPI.COMM_WORLD, 4) i1 = np.where((mesh1d.geometry.x == (0.75, 0, 0)).all(axis=1))[0][0] i2 = np.where((mesh1d.geometry.x == (1, 0, 0)).all(axis=1))[0][0] mesh1d.geometry.x[i2] = mesh1d.geometry.x[i1] return mesh1d
def test_save_1d_scalar(tempdir): mesh = create_unit_interval(MPI.COMM_WORLD, 32) u = Function(FunctionSpace(mesh, ("Lagrange", 2))) u.interpolate(lambda x: x[0]) filename = os.path.join(tempdir, "u.pvd") with VTKFile(MPI.COMM_WORLD, filename, "w") as vtk: vtk.write_function(u, 0.)
def mesh_factory(tdim, n): if tdim == 1: return create_unit_interval(MPI.COMM_WORLD, n) elif tdim == 2: return create_unit_square(MPI.COMM_WORLD, n, n) elif tdim == 3: return create_unit_cube(MPI.COMM_WORLD, n, n, n)
def test_save_1d_tensor(tempdir): mesh = create_unit_interval(MPI.COMM_WORLD, 32) element = ufl.TensorElement("Lagrange", mesh.ufl_cell(), 2, shape=(2, 2)) u = Function(FunctionSpace(mesh, element)) u.x.array[:] = 1.0 filename = os.path.join(tempdir, "u.pvd") with VTKFile(mesh.comm, filename, "w") as vtk: vtk.write_function(u, 0.)
def test_save_and_load_1d_mesh(tempdir, encoding): filename = os.path.join(tempdir, "mesh.xdmf") mesh = create_unit_interval(MPI.COMM_WORLD, 32) with XDMFFile(mesh.comm, filename, "w", encoding=encoding) as file: file.write_mesh(mesh) with XDMFFile(MPI.COMM_WORLD, filename, "r", encoding=encoding) as file: mesh2 = file.read_mesh() assert mesh.topology.index_map(0).size_global == mesh2.topology.index_map(0).size_global assert mesh.topology.index_map(mesh.topology.dim).size_global == mesh2.topology.index_map( mesh.topology.dim).size_global
def test_save_1d_scalar(tempdir, encoding, use_pathlib): filename2 = (Path(tempdir).joinpath("u1_.xdmf") if use_pathlib else os.path.join(tempdir, "u1_.xdmf")) mesh = create_unit_interval(MPI.COMM_WORLD, 32) V = FunctionSpace(mesh, ("Lagrange", 2)) u = Function(V) u.vector.set(1.0 + ( 1j if np.issubdtype(PETSc.ScalarType, np.complexfloating) else 0)) with XDMFFile(mesh.comm, filename2, "w", encoding=encoding) as file: file.write_mesh(mesh) file.write_function(u)
def test_facet_area1D(): mesh = create_unit_interval(MPI.COMM_WORLD, 10) # NOTE: Area of a vertex is defined to 1 in ufl c0 = ufl.FacetArea(mesh) c = Constant(mesh, ScalarType(1)) ds = ufl.Measure("ds", domain=mesh) a0 = mesh.comm.allreduce(assemble_scalar(form(c * ds)), op=MPI.SUM) a = mesh.comm.allreduce(assemble_scalar(form(c0 * ds)), op=MPI.SUM) assert numpy.isclose(a.real, 2) assert numpy.isclose(a0.real, 2)
def test_save_1d_vector(tempdir): mesh = create_unit_interval(MPI.COMM_WORLD, 32) def f(x): vals = np.zeros((2, x.shape[1])) vals[0] = x[0] vals[1] = 2 * x[0] * x[0] return vals element = ufl.VectorElement("Lagrange", mesh.ufl_cell(), 2, dim=2) u = Function(FunctionSpace(mesh, element)) u.interpolate(f) filename = os.path.join(tempdir, "u.pvd") with VTKFile(MPI.COMM_WORLD, filename, "w") as vtk: vtk.write_function(u, 0.)
def test_compute_collisions_tree_1d(point): mesh_A = create_unit_interval(MPI.COMM_WORLD, 16) def locator_A(x): return x[0] >= point[0] # Locate all vertices of mesh A that should collide vertices_A = _cpp.mesh.locate_entities(mesh_A, 0, locator_A) mesh_A.topology.create_connectivity(0, mesh_A.topology.dim) v_to_c = mesh_A.topology.connectivity(0, mesh_A.topology.dim) # Find all cells connected to vertex in the collision bounding box cells_A = np.sort(np.unique(np.hstack([v_to_c.links(vertex) for vertex in vertices_A]))) mesh_B = create_unit_interval(MPI.COMM_WORLD, 16) bgeom = mesh_B.geometry.x bgeom += point def locator_B(x): return x[0] <= 1 # Locate all vertices of mesh B that should collide vertices_B = _cpp.mesh.locate_entities(mesh_B, 0, locator_B) mesh_B.topology.create_connectivity(0, mesh_B.topology.dim) v_to_c = mesh_B.topology.connectivity(0, mesh_B.topology.dim) # Find all cells connected to vertex in the collision bounding box cells_B = np.sort(np.unique(np.hstack([v_to_c.links(vertex) for vertex in vertices_B]))) # Find colliding entities using bounding box trees tree_A = BoundingBoxTree(mesh_A, mesh_A.topology.dim) tree_B = BoundingBoxTree(mesh_B, mesh_B.topology.dim) entities = compute_collisions(tree_A, tree_B) entities_A = np.sort(np.unique([q[0] for q in entities])) entities_B = np.sort(np.unique([q[1] for q in entities])) assert np.allclose(entities_A, cells_A) assert np.allclose(entities_B, cells_B)
def test_compute_collisions_point_1d(): N = 16 p = np.array([0.3, 0, 0]) mesh = create_unit_interval(MPI.COMM_WORLD, N) dx = 1 / N cell_index = int(p[0] // dx) # Vertices of cell we should collide with vertices = np.array([[dx * cell_index, 0, 0], [dx * (cell_index + 1), 0, 0]]) # Compute collision tdim = mesh.topology.dim tree = BoundingBoxTree(mesh, tdim) entities = compute_collisions(tree, p) assert len(entities.array) == 1 # Get the vertices of the geometry geom_entities = _cpp.mesh.entities_to_geometry(mesh, tdim, entities.array, False)[0] x = mesh.geometry.x cell_vertices = x[geom_entities] # Check that we get the cell with correct vertices assert np.allclose(cell_vertices, vertices)
def test_distance_interval(): mesh = create_unit_interval(MPI.COMM_SELF, 1) assert squared_distance(mesh, mesh.topology.dim, [0], [-1.0, 0, 0]) == pytest.approx(1.0) assert squared_distance(mesh, mesh.topology.dim, [0], [0.5, 0, 0]) == pytest.approx(0.0)
def test_ghost_vertex_1d(): mesh = create_unit_interval(MPI.COMM_WORLD, 20, ghost_mode=GhostMode.shared_vertex) assert mesh.topology.index_map(0).size_global == 21 assert mesh.topology.index_map(1).size_global == 20
def test_block_size_real(mesh): mesh = create_unit_interval(MPI.COMM_WORLD, 12) V = FiniteElement('DG', mesh.ufl_cell(), 0) R = FiniteElement('R', mesh.ufl_cell(), 0) X = FunctionSpace(mesh, V * R) assert X.dofmap.index_map_bs == 1
def test_diff_then_integrate(): # Define 1D geometry n = 21 mesh = create_unit_interval(MPI.COMM_WORLD, n) # Shift and scale mesh x0, x1 = 1.5, 3.14 mesh.coordinates()[:] *= (x1 - x0) mesh.coordinates()[:] += x0 x = SpatialCoordinate(mesh)[0] xs = 0.1 + 0.8 * x / x1 # scaled to be within [0.1,0.9] # Define list of expressions to test, and configure # accuracies these expressions are known to pass with. # The reason some functions are less accurately integrated is # likely that the default choice of quadrature rule is not perfect F_list = [] def reg(exprs, acc=10): for expr in exprs: F_list.append((expr, acc)) # FIXME: 0*dx and 1*dx fails in the ufl-ffcx-jit framework somewhere # reg([Constant(0.0, cell=cell)]) # reg([Constant(1.0, cell=cell)]) monomial_list = [x**q for q in range(2, 6)] reg(monomial_list) reg([2.3 * p + 4.5 * q for p in monomial_list for q in monomial_list]) reg([x**x]) reg([x**(x**2)], 8) reg([x**(x**3)], 6) reg([x**(x**4)], 2) # Special functions: reg([atan(xs)], 8) reg([sin(x), cos(x), exp(x)], 5) reg([ln(xs), pow(x, 2.7), pow(2.7, x)], 3) reg([asin(xs), acos(xs)], 1) reg([tan(xs)], 7) try: import scipy except ImportError: scipy = None if hasattr(math, 'erf') or scipy is not None: reg([erf(xs)]) else: print( "Warning: skipping test of erf, old python version and no scipy.") # if 0: # print("Warning: skipping tests of bessel functions, doesn't build on all platforms.") # elif scipy is None: # print("Warning: skipping tests of bessel functions, missing scipy.") # else: # for nu in (0, 1, 2): # # Many of these are possibly more accurately integrated, # # but 4 covers all and is sufficient for this test # reg([bessel_J(nu, xs), bessel_Y(nu, xs), bessel_I(nu, xs), bessel_K(nu, xs)], 4) # To handle tensor algebra, make an x dependent input tensor # xx and square all expressions def reg2(exprs, acc=10): for expr in exprs: F_list.append((inner(expr, expr), acc)) xx = as_matrix([[2 * x**2, 3 * x**3], [11 * x**5, 7 * x**4]]) x3v = as_vector([3 * x**2, 5 * x**3, 7 * x**4]) cc = as_matrix([[2, 3], [4, 5]]) reg2([xx]) reg2([x3v]) reg2([cross(3 * x3v, as_vector([-x3v[1], x3v[0], x3v[2]]))]) reg2([xx.T]) reg2([tr(xx)]) reg2([det(xx)]) reg2([dot(xx, 0.1 * xx)]) reg2([outer(xx, xx.T)]) reg2([dev(xx)]) reg2([sym(xx)]) reg2([skew(xx)]) reg2([elem_mult(7 * xx, cc)]) reg2([elem_div(7 * xx, xx + cc)]) reg2([elem_pow(1e-3 * xx, 1e-3 * cc)]) reg2([elem_pow(1e-3 * cc, 1e-3 * xx)]) reg2([elem_op(lambda z: sin(z) + 2, 0.03 * xx)], 2) # pretty inaccurate... # FIXME: Add tests for all UFL operators: # These cause discontinuities and may be harder to test in the # above fashion: # 'inv', 'cofac', # 'eq', 'ne', 'le', 'ge', 'lt', 'gt', 'And', 'Or', 'Not', # 'conditional', 'sign', # 'jump', 'avg', # 'LiftingFunction', 'LiftingOperator', # FIXME: Test other derivatives: (but algorithms for operator # derivatives are the same!): # 'variable', 'diff', # 'Dx', 'grad', 'div', 'curl', 'rot', 'Dn', 'exterior_derivative', # Run through all operators defined above and compare integrals debug = 0 for F, acc in F_list: # Apply UFL differentiation f = diff(F, SpatialCoordinate(mesh))[..., 0] if debug: print(F) print(x) print(f) # Apply integration with DOLFINx # (also passes through form compilation and jit) M = f * dx f_integral = assemble_scalar(M) # noqa f_integral = mesh.comm.allreduce(f_integral, op=MPI.SUM) # Compute integral of f manually from anti-derivative F # (passes through pybind11 interface and uses UFL evaluation) F_diff = F((x1, )) - F((x0, )) # Compare results. Using custom relative delta instead # of decimal digits here because some numbers are >> 1. delta = min(abs(f_integral), abs(F_diff)) * 10**-acc assert f_integral - F_diff <= delta
def test_empty_tree(): mesh = create_unit_interval(MPI.COMM_WORLD, 16) bbtree = BoundingBoxTree(mesh, mesh.topology.dim, []) assert bbtree.num_bboxes == 0
def test_save_1d_mesh(tempdir): filename = os.path.join(tempdir, "mesh.pvd") mesh = create_unit_interval(MPI.COMM_WORLD, 32) with VTKFile(MPI.COMM_WORLD, filename, "w") as vtk: vtk.write_mesh(mesh) vtk.write_mesh(mesh, 1)
def interval(): return create_unit_interval(MPI.COMM_WORLD, 18)
cell = ufl.Cell(shape, geometric_dimension=gdim) domain = ufl.Mesh(ufl.VectorElement("Lagrange", cell, degree)) x = [[0., 0., 0.], [0., 1., 0.], [0., 1., 1.], [1, 1., 1]] cells = [[0, 1, 2, 3]] mesh = create_mesh(MPI.COMM_WORLD, cells, x, domain) assert squared_distance(mesh, mesh.topology.dim, [0], [-1.0, -1.0, -1.0]) == pytest.approx(3.0) assert squared_distance(mesh, mesh.topology.dim, [0], [-1.0, 0.5, 0.5]) == pytest.approx(1.0) assert squared_distance(mesh, mesh.topology.dim, [0], [0.5, 0.5, 0.5]) == pytest.approx(0.0) @pytest.mark.skip("volume_entities needs fixing") @pytest.mark.parametrize('mesh', [ create_unit_interval(MPI.COMM_WORLD, 18), create_unit_square(MPI.COMM_WORLD, 8, 9, CellType.triangle), create_unit_square(MPI.COMM_WORLD, 8, 9, CellType.quadrilateral), create_unit_cube(MPI.COMM_WORLD, 8, 9, 5, CellType.tetrahedron) ]) def test_volume_cells(mesh): tdim = mesh.topology.dim map = mesh.topology.index_map(tdim) num_cells = map.size_local v = _cpp.mesh.volume_entities(mesh, range(num_cells), mesh.topology.dim) assert mesh.comm.allreduce(v.sum(), MPI.SUM) == pytest.approx(1.0, rel=1e-9) @pytest.mark.skip("volume_entities needs fixing") def test_volume_quadrilateralR2():