def test_facet_integral(cell_type): """Test that the integral of a function over a facet is correct""" for count in range(5): mesh = unit_cell(cell_type) tdim = mesh.topology.dim V = FunctionSpace(mesh, ("Lagrange", 2)) v = Function(V) map_f = mesh.topology.index_map(tdim - 1) num_facets = map_f.size_local + map_f.num_ghosts indices = np.arange(0, num_facets) values = np.arange(0, num_facets, dtype=np.intc) marker = MeshTags(mesh, tdim - 1, indices, values) # Functions that will have the same integral over each facet if cell_type == CellType.triangle: root = 3 ** 0.25 # 4th root of 3 v.interpolate(lambda x: (x[0] - 1 / root) ** 2 + (x[1] - root / 3) ** 2) elif cell_type == CellType.quadrilateral: v.interpolate(lambda x: x[0] * (1 - x[0]) + x[1] * (1 - x[1])) elif cell_type == CellType.tetrahedron: s = 2 ** 0.5 * 3 ** (1 / 3) # side length v.interpolate(lambda x: (x[0] - s / 2) ** 2 + (x[1] - s / 2 / np.sqrt(3)) ** 2 + (x[2] - s * np.sqrt(2 / 3) / 4) ** 2) elif cell_type == CellType.hexahedron: v.interpolate(lambda x: x[0] * (1 - x[0]) + x[1] * (1 - x[1]) + x[2] * (1 - x[2])) # assert that the integral of these functions over each face are equal out = [] for j in range(num_facets): a = v * ds(subdomain_data=marker, subdomain_id=j) result = fem.assemble_scalar(a) out.append(result) assert np.isclose(result, out[0])
def test_interpolate_subset(order, dim, affine): if dim == 2: ct = CellType.triangle if affine else CellType.quadrilateral mesh = create_unit_square(MPI.COMM_WORLD, 3, 4, ct) elif dim == 3: ct = CellType.tetrahedron if affine else CellType.hexahedron mesh = create_unit_cube(MPI.COMM_WORLD, 3, 2, 2, ct) V = FunctionSpace(mesh, ("DG", order)) u = Function(V) cells = locate_entities(mesh, mesh.topology.dim, lambda x: x[1] <= 0.5 + 1e-10) num_local_cells = mesh.topology.index_map(mesh.topology.dim).size_local cells_local = cells[cells < num_local_cells] x = ufl.SpatialCoordinate(mesh) f = x[1]**order expr = Expression(f, V.element.interpolation_points) u.interpolate(expr, cells_local) mt = MeshTags(mesh, mesh.topology.dim, cells_local, np.ones(cells_local.size, dtype=np.int32)) dx = ufl.Measure("dx", domain=mesh, subdomain_data=mt) assert np.isclose( np.abs(form(assemble_scalar(form(ufl.inner(u - f, u - f) * dx(1))))), 0) integral = mesh.comm.allreduce(assemble_scalar(form(u * dx)), op=MPI.SUM) assert np.isclose(integral, 1 / (order + 1) * 0.5**(order + 1), 0)
def test_facet_normals(cell_type): """Test that FacetNormal is outward facing""" for count in range(5): mesh = unit_cell(cell_type) tdim = mesh.topology.dim V = VectorFunctionSpace(mesh, ("Lagrange", 1)) normal = FacetNormal(mesh) v = Function(V) map_f = mesh.topology.index_map(tdim - 1) num_facets = map_f.size_local + map_f.num_ghosts indices = np.arange(0, num_facets) values = np.arange(0, num_facets, dtype=np.intc) marker = MeshTags(mesh, tdim - 1, indices, values) # For each facet, check that the inner product of the normal and # the vector that has a positive normal component on only that facet # is positive for i in range(num_facets): if cell_type == CellType.interval: co = mesh.geometry.x[i] v.interpolate(lambda x: x[0] - co[0]) if cell_type == CellType.triangle: co = mesh.geometry.x[i] # Vector function that is zero at `co` and points away from `co` # so that there is no normal component on two edges and the integral # over the other edge is 1 v.interpolate(lambda x: ((x[0] - co[0]) / 2, (x[1] - co[1]) / 2)) elif cell_type == CellType.tetrahedron: co = mesh.geometry.x[i] # Vector function that is zero at `co` and points away from `co` # so that there is no normal component on three faces and the integral # over the other edge is 1 v.interpolate(lambda x: ((x[0] - co[0]) / 3, (x[1] - co[1]) / 3, (x[2] - co[2]) / 3)) elif cell_type == CellType.quadrilateral: # function that is 0 on one edge and points away from that edge # so that there is no normal component on three edges v.interpolate(lambda x: tuple(x[j] - i % 2 if j == i // 2 else 0 * x[j] for j in range(2))) elif cell_type == CellType.hexahedron: # function that is 0 on one face and points away from that face # so that there is no normal component on five faces v.interpolate(lambda x: tuple(x[j] - i % 2 if j == i // 3 else 0 * x[j] for j in range(3))) # assert that the integrals these functions dotted with the normal over a face # is 1 on one face and 0 on the others ones = 0 for j in range(num_facets): a = inner(v, normal) * ds(subdomain_data=marker, subdomain_id=j) result = fem.assemble_scalar(a) if np.isclose(result, 1): ones += 1 else: assert np.isclose(result, 0) assert ones == 1
def test_assembly_dx_domains(mode): mesh = create_unit_square(MPI.COMM_WORLD, 10, 10, ghost_mode=mode) V = FunctionSpace(mesh, ("Lagrange", 1)) u, v = ufl.TrialFunction(V), ufl.TestFunction(V) # Prepare a marking structures # indices cover all cells # values are [1, 2, 3, 3, ...] cell_map = mesh.topology.index_map(mesh.topology.dim) num_cells = cell_map.size_local + cell_map.num_ghosts indices = np.arange(0, num_cells) values = np.full(indices.shape, 3, dtype=np.intc) values[0] = 1 values[1] = 2 marker = MeshTags(mesh, mesh.topology.dim, indices, values) dx = ufl.Measure('dx', subdomain_data=marker, domain=mesh) w = Function(V) w.x.array[:] = 0.5 # Assemble matrix a = form(w * ufl.inner(u, v) * (dx(1) + dx(2) + dx(3))) A = assemble_matrix(a) A.assemble() a2 = form(w * ufl.inner(u, v) * dx) A2 = assemble_matrix(a2) A2.assemble() assert (A - A2).norm() < 1.0e-12 bc = dirichletbc(Function(V), range(30)) # Assemble vector L = form(ufl.inner(w, v) * (dx(1) + dx(2) + dx(3))) b = assemble_vector(L) apply_lifting(b, [a], [[bc]]) b.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES, mode=PETSc.ScatterMode.REVERSE) set_bc(b, [bc]) L2 = form(ufl.inner(w, v) * dx) b2 = assemble_vector(L2) apply_lifting(b2, [a], [[bc]]) b2.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES, mode=PETSc.ScatterMode.REVERSE) set_bc(b2, [bc]) assert (b - b2).norm() < 1.0e-12 # Assemble scalar L = form(w * (dx(1) + dx(2) + dx(3))) s = assemble_scalar(L) s = mesh.comm.allreduce(s, op=MPI.SUM) assert s == pytest.approx(0.5, 1.0e-12) L2 = form(w * dx) s2 = assemble_scalar(L2) s2 = mesh.comm.allreduce(s2, op=MPI.SUM) assert s == pytest.approx(s2, 1.0e-12)
def test_3d(tempdir, cell_type, encoding): filename = os.path.join(tempdir, "meshtags_3d.xdmf") comm = MPI.COMM_WORLD mesh = UnitCubeMesh(comm, 4, 4, 4, cell_type) bottom_facets = locate_entities(mesh, 2, lambda x: np.isclose(x[1], 0.0)) bottom_values = np.full(bottom_facets.shape, 1, dtype=np.intc) left_facets = locate_entities(mesh, 2, lambda x: np.isclose(x[0], 0.0)) left_values = np.full(left_facets.shape, 2, dtype=np.intc) indices, pos = np.unique(np.hstack((bottom_facets, left_facets)), return_index=True) mt = MeshTags(mesh, 2, indices, np.hstack((bottom_values, left_values))[pos]) mt.name = "facets" top_lines = locate_entities(mesh, 1, lambda x: np.isclose(x[2], 1.0)) top_values = np.full(top_lines.shape, 3, dtype=np.intc) right_lines = locate_entities(mesh, 1, lambda x: np.isclose(x[0], 1.0)) right_values = np.full(right_lines.shape, 4, dtype=np.intc) indices, pos = np.unique(np.hstack((top_lines, right_lines)), return_index=True) mt_lines = MeshTags(mesh, 1, indices, np.hstack((top_values, right_values))[pos]) mt_lines.name = "lines" with XDMFFile(comm, filename, "w", encoding=encoding) as file: mesh.topology.create_connectivity_all() file.write_mesh(mesh) file.write_meshtags(mt) file.write_meshtags(mt_lines) file.write_information("units", "mm") with XDMFFile(comm, filename, "r", encoding=encoding) as file: mesh_in = file.read_mesh() mesh_in.topology.create_connectivity_all() mt_in = file.read_meshtags(mesh_in, "facets") mt_lines_in = file.read_meshtags(mesh_in, "lines") units = file.read_information("units") assert units == "mm" assert mt_in.name == "facets" assert mt_lines_in.name == "lines" with XDMFFile(comm, os.path.join(tempdir, "meshtags_3d_out.xdmf"), "w", encoding=encoding) as file: file.write_mesh(mesh_in) file.write_meshtags(mt_lines_in) file.write_meshtags(mt_in) # Check number of owned and marked entities lines_local = comm.allreduce((mt_lines.indices < mesh.topology.index_map(1).size_local).sum(), op=MPI.SUM) lines_local_in = comm.allreduce( (mt_lines_in.indices < mesh_in.topology.index_map(1).size_local).sum(), op=MPI.SUM) assert lines_local == lines_local_in # Check that only owned data is written to file facets_local = comm.allreduce((mt.indices < mesh.topology.index_map(2).size_local).sum(), op=MPI.SUM) parser = ElementTree.XMLParser() tree = ElementTree.parse(os.path.join(tempdir, "meshtags_3d_out.xdmf"), parser) num_lines = int(tree.findall(".//Grid[@Name='lines']/Topology")[0].get("NumberOfElements")) num_facets = int(tree.findall(".//Grid[@Name='facets']/Topology")[0].get("NumberOfElements")) assert(num_lines == lines_local) assert(num_facets == facets_local)
def plot_meshtags(): # MeshTags and using subplots # =========================== mesh = create_unit_square(MPI.COMM_WORLD, 12, 12, cell_type=CellType.quadrilateral) # We continue using the mesh from the previous section, and find all # cells satisfying the condition below def in_circle(x): """True for points inside circle with radius 2""" return np.array((x.T[0] - 0.5)**2 + (x.T[1] - 0.5)**2 < 0.2**2, dtype=np.int32) # Create a dolfinx.MeshTag for all cells. If midpoint is inside the # circle, it gets value 1, otherwise 0. num_cells = mesh.topology.index_map(mesh.topology.dim).size_local midpoints = compute_midpoints(mesh, mesh.topology.dim, list(np.arange(num_cells, dtype=np.int32))) cell_tags = MeshTags(mesh, mesh.topology.dim, np.arange(num_cells), in_circle(midpoints)) cells, types, x = plot.create_vtk_mesh(mesh, mesh.topology.dim) grid = pyvista.UnstructuredGrid(cells, types, x) # As the dolfinx.MeshTag contains a value for every cell in the # geometry, we can attach it directly to the grid grid.cell_data["Marker"] = cell_tags.values grid.set_active_scalars("Marker") # We create a plotter consisting of two windows, and add a plot of the # Meshtags to the first window. subplotter = pyvista.Plotter(shape=(1, 2)) subplotter.subplot(0, 0) subplotter.add_text("Mesh with markers", font_size=14, color="black", position="upper_edge") subplotter.add_mesh(grid, show_edges=True, show_scalar_bar=False) subplotter.view_xy() # We can also visualize subsets of data, by creating a smaller topology, # only consisting of those entities that has value one in the # dolfinx.MeshTag cells, types, x = plot.create_vtk_mesh( mesh, mesh.topology.dim, cell_tags.indices[cell_tags.values == 1]) # We add this grid to the second plotter sub_grid = pyvista.UnstructuredGrid(cells, types, x) subplotter.subplot(0, 1) subplotter.add_text("Subset of mesh", font_size=14, color="black", position="upper_edge") subplotter.add_mesh(sub_grid, show_edges=True, edge_color="black") if pyvista.OFF_SCREEN: subplotter.screenshot("2D_markers.png", transparent_background=transparent, window_size=[2 * figsize, figsize]) else: subplotter.show()
def merge_meshtags(mts, dim): """ Merge multiple MeshTags into one. Parameters ---------- mts: List of meshtags dim: Dimension of MeshTags which should be merged. Note it is not possible to merge MeshTags with different dimensions into one MeshTags object. """ mts = [(mt, name) for name, mt in mts.items() if mt.dim == dim] if len(mts) == 0: raise RuntimeError(f"Cannot find MeshTags of dimension {dim}") indices = numpy.hstack([mt.indices for mt, name in mts]) values = numpy.hstack([mt.values for mt, name in mts]) keys = {} for mt, name in mts: comm = mt.mesh.mpi_comm() # In some cases this process could receive a MeshTags which are empty # We need to return correct "keys" mapping on each process, so this # communicates the value from processes which don't have empty meshtags if len(mt.values) == 0: value = -1 else: if numpy.max(mt.values) < 0: raise RuntimeError( "Not expecting negative values for MeshTags") value = int(mt.values[0]) value = comm.allreduce(value, op=MPI.MAX) keys[name] = value indices, pos = numpy.unique(indices, return_index=True) mt = MeshTags(mts[0][0].mesh, dim, indices, values[pos]) return mt, keys
def test_3d(tempdir, cell_type, encoding): filename = os.path.join(tempdir, "meshtags_3d.xdmf") comm = MPI.COMM_WORLD mesh = UnitCubeMesh(comm, 4, 4, 4, cell_type) bottom_facets = locate_entities(mesh, 2, lambda x: np.isclose(x[1], 0.0)) bottom_values = np.full(bottom_facets.shape, 1, dtype=np.intc) left_facets = locate_entities(mesh, 2, lambda x: np.isclose(x[0], 0.0)) left_values = np.full(left_facets.shape, 2, dtype=np.intc) indices, pos = np.unique(np.hstack((bottom_facets, left_facets)), return_index=True) mt = MeshTags(mesh, 2, indices, np.hstack((bottom_values, left_values))[pos]) mt.name = "facets" top_lines = locate_entities(mesh, 1, lambda x: np.isclose(x[2], 1.0)) top_values = np.full(top_lines.shape, 3, dtype=np.intc) right_lines = locate_entities(mesh, 1, lambda x: np.isclose(x[0], 1.0)) right_values = np.full(right_lines.shape, 4, dtype=np.intc) indices, pos = np.unique(np.hstack((top_lines, right_lines)), return_index=True) mt_lines = MeshTags(mesh, 1, indices, np.hstack((top_values, right_values))[pos]) mt_lines.name = "lines" with XDMFFile(comm, filename, "w", encoding=encoding) as file: mesh.topology.create_connectivity_all() file.write_mesh(mesh) file.write_meshtags(mt) file.write_meshtags(mt_lines) with XDMFFile(comm, filename, "r", encoding=encoding) as file: mesh_in = file.read_mesh() mesh_in.topology.create_connectivity_all() mt_in = file.read_meshtags(mesh_in, "facets") mt_lines_in = file.read_meshtags(mesh_in, "lines") assert mt_in.name == "facets" assert mt_lines_in.name == "lines" with XDMFFile(comm, os.path.join(tempdir, "meshtags_3d_out.xdmf"), "w", encoding=encoding) as file: file.write_mesh(mesh_in) file.write_meshtags(mt_lines_in) file.write_meshtags(mt_in) # Check number of owned and marked entities lines_local = comm.allreduce((mt_lines.indices < mesh.topology.index_map(1).size_local).sum(), op=MPI.SUM) lines_local_in = comm.allreduce( (mt_lines_in.indices < mesh_in.topology.index_map(1).size_local).sum(), op=MPI.SUM) assert lines_local == lines_local_in
[np.array([0.0, 0.0, 0.0]), np.array([xdim, ydim, zdim])], [Nx, Ny, Nz]) def right_side(x): return np.isclose(x[1], ydim) def left_side(x): return np.isclose(x[1], 0.0) left_side_facets = locate_entities_boundary(mesh, 2, left_side) right_side_facets = locate_entities_boundary(mesh, 2, right_side) mt = MeshTags(mesh, 2, right_side_facets, 1) # External boundary facets ds = ufl.Measure("ds", domain=mesh, subdomain_data=mt) dx = ufl.Measure("dx", domain=mesh) load_area = mesh.mpi_comm().allreduce( assemble_scalar(1.0 * ds(1, domain=mesh)), MPI.SUM) if rank == 0: logger.info("Mesh hmin={} hmax={}".format(mesh.hmin(), mesh.hmax())) logger.info(f"Load area = {load_area}") assert np.isclose(xdim * zdim, load_area) w0, w1, intern_var0, intern_var1 = fecoda.main.initialize_functions(mesh)
u, v = ufl.TrialFunction(U), ufl.TestFunction(U) def free_end(x): """Marks the leftmost points of the cantilever""" return np.isclose(x[0], 48.0) def left(x): """Marks left part of boundary, where cantilever is attached to wall""" return np.isclose(x[0], 0.0) # Locate all facets at the free end and assign them value 1 free_end_facets = locate_entities_boundary(mesh, 1, free_end) mt = MeshTags(mesh, 1, free_end_facets, 1) ds = ufl.Measure("ds", subdomain_data=mt) # Homogeneous boundary condition in displacement u_bc = Function(U) u_bc.x.array[:] = 0.0 # Displacement BC is applied to the left side left_facets = locate_entities_boundary(mesh, 1, left) bdofs = locate_dofs_topological(U, 1, left_facets) bc = dirichletbc(u_bc, bdofs) # Elastic stiffness tensor and Poisson ratio E, nu = 1.0, 1.0 / 3.0
def bottom_left_corner(x): return np.logical_and(np.isclose(x[1], 0.0), np.isclose(x[2], zdim - 0.1)) def bottom_right_corner(x): return np.logical_and(np.isclose(x[1], 0.0), np.isclose(x[2], 0.1)) line_load_facets = locate_entities_boundary(mesh, 2, line_load) bottom_left_lines = locate_entities_boundary(mesh, 1, bottom_left_corner) bottom_right_lines = locate_entities_boundary(mesh, 1, bottom_right_corner) top_load_facets = locate_entities_boundary(mesh, 2, top_load) mt_line_load = MeshTags(mesh, 2, line_load_facets, 1) # External boundary facets ds = ufl.Measure("ds", domain=mesh, subdomain_data=mt_line_load) dx = ufl.Measure("dx", domain=mesh, subdomain_data=mt_cell) load_area = mesh.mpi_comm().allreduce( assemble_scalar(1.0 * ds(1, domain=mesh)), MPI.SUM) if rank == 0: logger.info(f"[Timer] Mesh reading {time() - t0}") logger.info(f"Mesh hmin={mesh.hmin()} hmax={mesh.hmax()}") w0, w1, intern_var0, intern_var1 = fecoda.main.initialize_functions(mesh) # Beginning time for simulation
def plot_higher_order(): # Plotting higher order Functions # =============================== # In the previous sections we have considered degree 1 Lagrange spaces. # We can also plot higher degree functions. mesh = create_unit_square(MPI.COMM_WORLD, 12, 12, cell_type=CellType.quadrilateral) # We continue using the mesh from the previous section, and find all # cells satisfying the condition below def in_circle(x): """Mark sphere with radius < sqrt(2)""" return np.array((x.T[0] - 0.5)**2 + (x.T[1] - 0.5)**2 < 0.2**2, dtype=np.int32) # Create a dolfinx.MeshTag for all cells. If midpoint is inside the # circle, it gets value 1, otherwise 0. num_cells = mesh.topology.index_map(mesh.topology.dim).size_local midpoints = compute_midpoints(mesh, mesh.topology.dim, list(np.arange(num_cells, dtype=np.int32))) cell_tags = MeshTags(mesh, mesh.topology.dim, np.arange(num_cells), in_circle(midpoints)) # We start by interpolating a discontinuous function into a second order # discontinuous Lagrange space Note that we use the `cell_tags` from # the previous section to get the cells for each of the regions cells0 = cell_tags.indices[cell_tags.values == 0] cells1 = cell_tags.indices[cell_tags.values == 1] V = FunctionSpace(mesh, ("Discontinuous Lagrange", 2)) u = Function(V, dtype=np.float64) u.interpolate(lambda x: x[0], cells0) u.interpolate(lambda x: x[1] + 1, cells1) # To get a topology that has a 1-1 correspondence with the # degrees-of-freedom in the function space, we call # `dolfinx.plot.create_vtk_mesh`. cells, types, x = plot.create_vtk_mesh(V) # Create a pyvista mesh from the topology and geometry, and attach # the coefficients of the degrees of freedom grid = pyvista.UnstructuredGrid(cells, types, x) grid.point_data["u"] = u.x.array grid.set_active_scalars("u") # We would also like to visualize the underlying mesh and obtain # that as we have done previously num_cells = mesh.topology.index_map(mesh.topology.dim).size_local cell_entities = np.arange(num_cells, dtype=np.int32) cells, types, x = plot.create_vtk_mesh(mesh, mesh.topology.dim, cell_entities) org_grid = pyvista.UnstructuredGrid(cells, types, x) # We visualize the data plotter = pyvista.Plotter() plotter.add_text("Second-order (P2) discontinuous elements", position="upper_edge", font_size=14, color="black") sargs = dict(height=0.1, width=0.8, vertical=False, position_x=0.1, position_y=0, color="black") plotter.add_mesh(grid, show_edges=False, scalar_bar_args=sargs, line_width=0) plotter.add_mesh(org_grid, color="white", style="wireframe", line_width=5) plotter.add_mesh(grid.copy(), style="points", point_size=15, render_points_as_spheres=True, line_width=0) plotter.view_xy() if pyvista.OFF_SCREEN: plotter.screenshot(f"DG_{MPI.COMM_WORLD.rank}.png", transparent_background=transparent, window_size=[figsize, figsize]) else: plotter.show()
def test_assembly_ds_domains(mode): mesh = create_unit_square(MPI.COMM_WORLD, 10, 10, ghost_mode=mode) V = FunctionSpace(mesh, ("Lagrange", 1)) u, v = ufl.TrialFunction(V), ufl.TestFunction(V) def bottom(x): return np.isclose(x[1], 0.0) def top(x): return np.isclose(x[1], 1.0) def left(x): return np.isclose(x[0], 0.0) def right(x): return np.isclose(x[0], 1.0) bottom_facets = locate_entities_boundary(mesh, mesh.topology.dim - 1, bottom) bottom_vals = np.full(bottom_facets.shape, 1, np.intc) top_facets = locate_entities_boundary(mesh, mesh.topology.dim - 1, top) top_vals = np.full(top_facets.shape, 2, np.intc) left_facets = locate_entities_boundary(mesh, mesh.topology.dim - 1, left) left_vals = np.full(left_facets.shape, 3, np.intc) right_facets = locate_entities_boundary(mesh, mesh.topology.dim - 1, right) right_vals = np.full(right_facets.shape, 6, np.intc) indices = np.hstack((bottom_facets, top_facets, left_facets, right_facets)) values = np.hstack((bottom_vals, top_vals, left_vals, right_vals)) indices, pos = np.unique(indices, return_index=True) marker = MeshTags(mesh, mesh.topology.dim - 1, indices, values[pos]) ds = ufl.Measure('ds', subdomain_data=marker, domain=mesh) w = Function(V) w.x.array[:] = 0.5 bc = dirichletbc(Function(V), range(30)) # Assemble matrix a = form(w * ufl.inner(u, v) * (ds(1) + ds(2) + ds(3) + ds(6))) A = assemble_matrix(a) A.assemble() norm1 = A.norm() a2 = form(w * ufl.inner(u, v) * ds) A2 = assemble_matrix(a2) A2.assemble() norm2 = A2.norm() assert norm1 == pytest.approx(norm2, 1.0e-12) # Assemble vector L = form(ufl.inner(w, v) * (ds(1) + ds(2) + ds(3) + ds(6))) b = assemble_vector(L) apply_lifting(b, [a], [[bc]]) b.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES, mode=PETSc.ScatterMode.REVERSE) set_bc(b, [bc]) L2 = form(ufl.inner(w, v) * ds) b2 = assemble_vector(L2) apply_lifting(b2, [a2], [[bc]]) b2.ghostUpdate(addv=PETSc.InsertMode.ADD_VALUES, mode=PETSc.ScatterMode.REVERSE) set_bc(b2, [bc]) assert b.norm() == pytest.approx(b2.norm(), 1.0e-12) # Assemble scalar L = form(w * (ds(1) + ds(2) + ds(3) + ds(6))) s = assemble_scalar(L) s = mesh.comm.allreduce(s, op=MPI.SUM) L2 = form(w * ds) s2 = assemble_scalar(L2) s2 = mesh.comm.allreduce(s2, op=MPI.SUM) assert (s == pytest.approx(s2, 1.0e-12) and 2.0 == pytest.approx(s, 1.0e-12))
def top_load(x): return np.isclose(x[1], ydim) left_support_lines = locate_entities_boundary(mesh, 1, left_support) right_support_lines = locate_entities_boundary(mesh, 1, right_support) top_load_facets = locate_entities_boundary(mesh, 2, top_load) replaced_part_cells = locate_entities( mesh, 3, lambda x: np.greater_equal(x[2], zdim - alpha * zdim)) replaced_part_interface = locate_entities( mesh, 2, lambda x: np.isclose(x[2], zdim - alpha * zdim)) right_side_facets = locate_entities_boundary(mesh, 2, lambda x: np.isclose(x[2], zdim)) mt_top_load = MeshTags(mesh, 2, top_load_facets, 1) # External boundary facets ds = ufl.Measure("ds", domain=mesh, subdomain_data=mt_top_load, metadata={"quadrature_degree": 2}) dx = ufl.Measure("dx", domain=mesh, subdomain_data=mt_cell, metadata={"quadrature_degree": 6}) load_area = mesh.mpi_comm().allreduce( assemble_scalar(1.0 * ds(1, domain=mesh)), MPI.SUM) if rank == 0: