def xtest_assembly_dS_domains(mode): N = 10 mesh = dolfinx.UnitSquareMesh(MPI.COMM_WORLD, N, N, ghost_mode=mode) one = dolfinx.Constant(mesh, 1) val = dolfinx.fem.assemble_scalar(one * ufl.dS) val = mesh.mpi_comm().allreduce(val, op=MPI.SUM) assert val == pytest.approx(2 * (N - 1) + N * numpy.sqrt(2), 1.0e-7)
def test_mpi_comm_wrapper(): """Test MPICommWrapper <-> mpi4py.MPI.Comm conversion""" w1 = MPI.COMM_WORLD m = dolfinx.UnitSquareMesh(w1, 4, 4) w2 = m.mpi_comm() assert isinstance(w1, MPI.Comm) assert isinstance(w2, MPI.Comm)
def test_additivity(mode): mesh = dolfinx.UnitSquareMesh(MPI.COMM_WORLD, 12, 12, ghost_mode=mode) V = dolfinx.FunctionSpace(mesh, ("CG", 1)) f1 = dolfinx.Function(V) f2 = dolfinx.Function(V) f3 = dolfinx.Function(V) with f1.vector.localForm() as f1_local: f1_local.set(1.0) with f2.vector.localForm() as f2_local: f2_local.set(2.0) with f3.vector.localForm() as f3_local: f3_local.set(3.0) j1 = ufl.inner(f1, f1) * ufl.dx(mesh) j2 = ufl.inner(f2, f2) * ufl.ds(mesh) j3 = ufl.inner(ufl.avg(f3), ufl.avg(f3)) * ufl.dS(mesh) # Assemble each scalar form separately J1 = mesh.mpi_comm().allreduce(dolfinx.fem.assemble_scalar(j1), op=MPI.SUM) J2 = mesh.mpi_comm().allreduce(dolfinx.fem.assemble_scalar(j2), op=MPI.SUM) J3 = mesh.mpi_comm().allreduce(dolfinx.fem.assemble_scalar(j3), op=MPI.SUM) # Sum forms and assemble the result J12 = mesh.mpi_comm().allreduce(dolfinx.fem.assemble_scalar(j1 + j2), op=MPI.SUM) J13 = mesh.mpi_comm().allreduce(dolfinx.fem.assemble_scalar(j1 + j3), op=MPI.SUM) J23 = mesh.mpi_comm().allreduce(dolfinx.fem.assemble_scalar(j2 + j3), op=MPI.SUM) J123 = mesh.mpi_comm().allreduce(dolfinx.fem.assemble_scalar(j1 + j2 + j3), op=MPI.SUM) # Compare assembled values assert (J1 + J2) == pytest.approx(J12) assert (J1 + J3) == pytest.approx(J13) assert (J2 + J3) == pytest.approx(J23) assert (J1 + J2 + J3) == pytest.approx(J123)
def test_l2_project(k): npart = 20 mesh = dolfinx.UnitSquareMesh(MPI.COMM_WORLD, 5, 5) ncells = mesh.topology.index_map(2).size_local x, c = pyleopart.mesh_fill(mesh, ncells * npart) p = pyleopart.Particles(x, c) p.add_field("v", [2]) vp = p.field("v") Q = dolfinx.function.VectorFunctionSpace(mesh, ("DG", k)) pbasis = pyleopart.get_particle_contributions(p, Q._cpp_object) def sq_val(x): return [x[0]**k, x[1]**k] u = dolfinx.function.Function(Q) u.interpolate(sq_val) # Transfer from Function "u" to (particle) field "v" pyleopart.transfer_to_particles(p, vp, u._cpp_object, pbasis) #Init and conduct l2projection v = dolfinx.function.Function(Q) l2project = pyleopart.L2Project(p, v._cpp_object, "v") l2project.solve() l2_error = mesh.mpi_comm().allreduce(assemble_scalar( dot(u - v, u - v) * dx), op=MPI.SUM) assert l2_error < 1e-15
def test_interpolate_project_dg_vector(k): npart = 20 mesh = dolfinx.UnitSquareMesh(MPI.COMM_WORLD, 5, 5) ncells = mesh.topology.index_map(2).size_local x, c = pyleopart.mesh_fill(mesh, ncells * npart) p = pyleopart.Particles(x, c) Q = dolfinx.function.VectorFunctionSpace(mesh, ("DG", k)) pbasis = pyleopart.get_particle_contributions(p, Q._cpp_object) def sq_val(x): return [x[0]**k, x[1]**k] u = dolfinx.function.Function(Q) u.interpolate(sq_val) p.add_field("v", [2]) v = p.field("v") # Transfer from Function "u" to field "v" pyleopart.transfer_to_particles(p, v, u._cpp_object, pbasis) # Transfer from field "v" back to Function "u" pyleopart.transfer_to_function(u._cpp_object, p, v, pbasis) p.add_field("w", [2]) w = p.field("w") # Transfer from Function "u" to field "w" pyleopart.transfer_to_particles(p, w, u._cpp_object, pbasis) # Compare fields "w" and "x"(squared) for pidx in range(len(x)): expected = p.field("x").data(pidx)**k assert np.isclose(p.field("w").data(pidx), expected).all()
def test_simple_mesh_fill(): np = 20 mesh = dolfinx.UnitSquareMesh(MPI.COMM_WORLD, 5, 5) ncells = mesh.topology.index_map(2).size_local x, c = pyleopart.mesh_fill(mesh, ncells * np) x0 = x[0, :] p = pyleopart.Particles(x, c) assert ((p.field("x").data(0) == x0).all())
def test_vector_assemble_matrix_interior(): mesh = dolfinx.UnitSquareMesh(MPI.COMM_WORLD, 3, 3) V = dolfinx.VectorFunctionSpace(mesh, ("CG", 1)) u, v = ufl.TrialFunction(V), ufl.TestFunction(V) a = ufl.inner(ufl.jump(u), ufl.jump(v)) * ufl.dS A = dolfinx.fem.assemble_matrix(a) A.assemble()
def xtest_assembly_dS_domains(mode): N = 10 mesh = dolfinx.UnitSquareMesh(dolfinx.MPI.comm_world, N, N, ghost_mode=mode) one = dolfinx.Constant(mesh, 1) val = dolfinx.fem.assemble_scalar(one * ufl.dS) val = dolfinx.MPI.sum(mesh.mpi_comm(), val) assert val == pytest.approx(2 * (N - 1) + N * numpy.sqrt(2), 1.0e-7)
def test_dof_coords_2d(degree): mesh = dolfinx.UnitSquareMesh(MPI.COMM_WORLD, 10, 10) V = dolfinx.FunctionSpace(mesh, ("CG", degree)) u = dolfinx.Function(V) u.interpolate(lambda x: x[0]) u.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD) x = V.tabulate_dof_coordinates() val = u.vector.array for i in range(len(val)): assert np.isclose(x[i, 0], val[i], rtol=1e-3)
window_size=[figsize, figsize]) else: plotter.show() # Plotting a 2D dolfinx.Function with pyvista using warp by scalar # ================================================================ # As in the previous section, we interpolate a function into a CG # function space def int_2D(x): return np.sin(np.pi * x[0]) * np.sin(2 * x[1] * np.pi) mesh = dolfinx.UnitSquareMesh( MPI.COMM_WORLD, 12, 12, cell_type=dolfinx.cpp.mesh.CellType.quadrilateral) V = dolfinx.FunctionSpace(mesh, ("Lagrange", 1)) u = dolfinx.Function(V) u.interpolate(int_2D) # As in the previous section, we extract the geometry and topology of # the mesh, and attach values to the vertices num_cells = mesh.topology.index_map(mesh.topology.dim).size_local cells = np.arange(num_cells, dtype=np.int32) pyvista_cells, cell_types = dolfinx.plot.create_vtk_topology( mesh, mesh.topology.dim, cells) grid = pyvista.UnstructuredGrid(pyvista_cells, cell_types, mesh.geometry.x) point_values = u.compute_point_values() if np.iscomplexobj(point_values): point_values = point_values.real grid.point_arrays["u"] = point_values
def test_assembly_into_quadrature_function(): """Test assembly into a Quadrature function. This test evaluates a UFL Expression into a Quadrature function space by evaluating the Expression on all cells of the mesh, and then inserting the evaluated values into a PETSc Vector constructed from a matching Quadrature function space. Concretely, we consider the evaluation of: e = B*(K(T)))**2 * grad(T) where K = 1/(A + B*T) where A and B are Constants and T is a Coefficient on a P2 finite element space with T = x + 2*y. The result is compared with interpolating the analytical expression of e directly into the Quadrature space. In parallel, each process evaluates the Expression on both local cells and ghost cells so that no parallel communication is required after insertion into the vector. """ mesh = dolfinx.UnitSquareMesh(MPI.COMM_WORLD, 3, 6) quadrature_degree = 2 quadrature_points = basix.make_quadrature(basix.CellType.triangle, quadrature_degree) Q_element = ufl.VectorElement("Quadrature", ufl.triangle, quadrature_degree, quad_scheme="default") Q = dolfinx.FunctionSpace(mesh, Q_element) def T_exact(x): return x[0] + 2.0 * x[1] P2 = dolfinx.FunctionSpace(mesh, ("P", 2)) T = dolfinx.Function(P2) T.interpolate(T_exact) A = dolfinx.Constant(mesh, 1.0) B = dolfinx.Constant(mesh, 2.0) K = 1.0 / (A + B * T) e = B * K**2 * ufl.grad(T) e_expr = dolfinx.Expression(e, quadrature_points) map_c = mesh.topology.index_map(mesh.topology.dim) num_cells = map_c.size_local + map_c.num_ghosts cells = np.arange(0, num_cells, dtype=np.int32) e_eval = e_expr.eval(cells) # Assemble into Function e_Q = dolfinx.Function(Q) with e_Q.vector.localForm() as e_Q_local: e_Q_local.setBlockSize(e_Q.function_space.dofmap.bs) e_Q_local.setValuesBlocked(Q.dofmap.list.array, e_eval, addv=PETSc.InsertMode.INSERT) def e_exact(x): T = x[0] + 2.0 * x[1] K = 1.0 / (A.value + B.value * T) grad_T = np.zeros((2, x.shape[1])) grad_T[0, :] = 1.0 grad_T[1, :] = 2.0 e = B.value * K**2 * grad_T return e e_exact_Q = dolfinx.Function(Q) e_exact_Q.interpolate(e_exact) assert np.isclose((e_exact_Q.vector - e_Q.vector).norm(), 0.0)
def test_assembly_into_quadrature_function(): """Test assembly into a Quadrature function. This test evaluates a UFL Expression into a Quadrature function space by evaluating the Expression on all cells of the mesh, and then inserting the evaluated values into a PETSc Vector constructed from a matching Quadrature function space. Concretely, we consider the evaluation of: e = B*(K(T)))**2 * grad(T) where K = 1/(A + B*T) where A and B are Constants and T is a Coefficient on a P2 finite element space with T = x + 2*y. The result is compared with interpolating the analytical expression of e directly into the Quadrature space. In parallel, each process evaluates the Expression on both local cells and ghost cells so that no parallel communication is required after insertion into the vector. """ mesh = dolfinx.UnitSquareMesh(MPI.COMM_WORLD, 3, 6) quadrature_degree = 2 quadrature_points, wts = basix.make_quadrature("default", basix.CellType.triangle, quadrature_degree) Q_element = ufl.VectorElement("Quadrature", ufl.triangle, quadrature_degree, quad_scheme="default") Q = dolfinx.FunctionSpace(mesh, Q_element) def T_exact(x): return x[0] + 2.0 * x[1] P2 = dolfinx.FunctionSpace(mesh, ("P", 2)) T = dolfinx.Function(P2) T.interpolate(T_exact) A = dolfinx.Constant(mesh, 1.0) B = dolfinx.Constant(mesh, 2.0) K = 1.0 / (A + B * T) e = B * K**2 * ufl.grad(T) e_expr = dolfinx.Expression(e, quadrature_points) map_c = mesh.topology.index_map(mesh.topology.dim) num_cells = map_c.size_local + map_c.num_ghosts cells = np.arange(0, num_cells, dtype=np.int32) e_eval = e_expr.eval(cells) # Assemble into Function e_Q = dolfinx.Function(Q) with e_Q.vector.localForm() as e_Q_local: e_Q_local.setBlockSize(e_Q.function_space.dofmap.bs) e_Q_local.setValuesBlocked(Q.dofmap.list.array, e_eval, addv=PETSc.InsertMode.INSERT) def e_exact(x): T = x[0] + 2.0 * x[1] K = 1.0 / (A.value + B.value * T) grad_T = np.zeros((2, x.shape[1])) grad_T[0, :] = 1.0 grad_T[1, :] = 2.0 e = B.value * K**2 * grad_T return e # FIXME: Below is only for testing purposes, # never to be used in user code! # # Replace when interpolation into Quadrature element works. coord_dofs = mesh.geometry.dofmap x_g = mesh.geometry.x tdim = mesh.topology.dim Q_dofs = Q.dofmap.list.array.reshape(num_cells, quadrature_points.shape[0]) bs = Q.dofmap.bs Q_dofs_unrolled = bs * np.repeat(Q_dofs, bs).reshape(-1, bs) + np.arange(bs) Q_dofs_unrolled = Q_dofs_unrolled.reshape( -1, bs * quadrature_points.shape[0]).astype(Q_dofs.dtype) with e_Q.vector.localForm() as local: e_exact_eval = np.zeros_like(local.array) for cell in range(num_cells): xg = x_g[coord_dofs.links(cell), :tdim] x = mesh.geometry.cmap.push_forward(quadrature_points, xg) e_exact_eval[Q_dofs_unrolled[cell]] = e_exact(x.T).T.flatten() assert np.allclose(local.array, e_exact_eval)
import scipy as scp from scipy import sparse from scipy.sparse.linalg import spsolve from mpi4py import MPI from petsc4py import PETSc import matplotlib.pyplot as plt import csv from multigrid import Interpolation2D, Restriction2D_direct num_elems_fine = 8 num_elems_coarse = num_elems_fine // 2 element_size_coarse = 1 / num_elems_coarse element_size_fine = 1 / num_elems_fine mesh_fine = dolfinx.UnitSquareMesh(MPI.COMM_WORLD, num_elems_fine, num_elems_fine, dolfinx.cpp.mesh.CellType.triangle) V_fine = dolfinx.FunctionSpace(mesh_fine, ("CG", 1)) mesh_coarse = dolfinx.UnitSquareMesh(MPI.COMM_WORLD, num_elems_coarse, num_elems_coarse, dolfinx.cpp.mesh.CellType.triangle) V_coarse = dolfinx.FunctionSpace(mesh_coarse, ("CG", 1)) mesh_dof_dict_fine = {} mesh_dof_dict_coarse = {} V_dof_coord_fine = V_fine.tabulate_dof_coordinates() V_dof_coord_coarse = V_coarse.tabulate_dof_coordinates() for j in range(0, V_fine.dofmap.index_map.size_local *
def test_l2_project_bounded(k, lb, ub): npart = 20 mesh = dolfinx.UnitSquareMesh(MPI.COMM_WORLD, 20, 20) ncells = mesh.topology.index_map(2).size_local x, c = pyleopart.mesh_fill(mesh, ncells * npart) p = pyleopart.Particles(x, c) p.add_field("v", [1]) vp = p.field("v") Q = dolfinx.function.FunctionSpace(mesh, ("DG", k)) pbasis = pyleopart.get_particle_contributions(p, Q._cpp_object) class SlottedDisk: def __init__(self, radius, center, width, depth, lb=0.0, ub=1.0, **kwargs): self.r = radius self.width = width self.depth = depth self.center = center self.lb = lb self.ub = ub def eval(self, x): values = np.empty((x.shape[1], )) xc = self.center[0] yc = self.center[1] # The mask is True within region of slotted disk and False elsewhere mask = (((x[0] - xc)**2 + (x[1] - yc)**2 <= self.r**2)) & np.invert( ((x[0] > (xc - self.width)) & (x[0] <= (xc + self.width)) & (x[1] >= yc + self.depth))) return mask * self.ub + np.invert(mask) * self.lb # Add disturbance to lower and upper bound, to make sure the bounded projection return the # original bounds slotted_disk = SlottedDisk(radius=0.15, center=[0.5, 0.5], width=0.05, depth=0.0, degree=3, lb=lb - 0.1, ub=ub + 0.1) u = dolfinx.function.Function(Q) u.interpolate(slotted_disk.eval) # Transfer from Function "u" to (particle) field "v" pyleopart.transfer_to_particles(p, vp, u._cpp_object, pbasis) #Init and conduct l2projection vh = dolfinx.function.Function(Q) l2project = pyleopart.L2Project(p, vh._cpp_object, "v") l2project.solve(lb, ub) # Assert if it stays within bounds assert np.min(vh.x.array()) < ub + 1e-12 assert np.max(vh.x.array()) > lb - 1e-12
def test_expression(): """ Test UFL expression evaluation """ mesh = dolfinx.UnitSquareMesh(MPI.COMM_WORLD, 10, 10) V = dolfinx.FunctionSpace(mesh, ("CG", 2)) def f(x): return 2 * x[0]**2 + x[1]**2 def gradf(x): return numpy.asarray([4 * x[0], 2 * x[1]]) u = dolfinx.Function(V) u.interpolate(f) u.x.scatter_forward() grad_u = ufl.grad(u) points = numpy.array([[0.15, 0.3, 0], [0.953, 0.81, 0]]) gdim = mesh.geometry.dim tdim = mesh.topology.dim bb = dolfinx.geometry.BoundingBoxTree(mesh, mesh.topology.dim) # Find colliding cells on proc closest_cell = [] local_map = [] for i, p in enumerate(points): cells = dolfinx.geometry.compute_collisions_point(bb, p) if len(cells) > 0: actual_cells = dolfinx.geometry.select_colliding_cells( mesh, cells, p, 1) if len(actual_cells) > 0: local_map.append(i) closest_cell.append(actual_cells[0]) num_dofs_x = mesh.geometry.dofmap.links( 0).size # NOTE: Assumes same cell geometry in whole mesh t_imap = mesh.topology.index_map(tdim) num_cells = t_imap.size_local + t_imap.num_ghosts x = mesh.geometry.x x_dofs = mesh.geometry.dofmap.array.reshape(num_cells, num_dofs_x) cell_geometry = numpy.zeros((num_dofs_x, gdim), dtype=numpy.float64) points_ref = numpy.zeros((len(local_map), tdim)) # Map cells on process back to reference element for i, cell in enumerate(closest_cell): cell_geometry[:] = x[x_dofs[cell], :gdim] point_ref = mesh.geometry.cmap.pull_back( points[local_map[i]][:gdim].reshape(1, -1), cell_geometry) points_ref[i] = point_ref # Eval using Expression expr = dolfinx.Expression(grad_u, points_ref) grad_u_at_x = expr.eval(closest_cell).reshape(len(closest_cell), points_ref.shape[0], gdim) # Compare solutions for i, cell in enumerate(closest_cell): point = points[local_map[i]] assert numpy.allclose(grad_u_at_x[i, i], gradf(point))
A_sp_dict = {} # Stores A mat sparse for all levels b_dict = {} # Stores the RHS of Au=b for all levels A_jacobi_sp_dict = {} # Stores the matrices for Jacobi smoother for all levels # Defining the operators for finest level solution using Dolfinx a_fine_dolfx = None # Stores the bilinear operator for finest level L_fine_dolfx = None # Stores the linear operator for finest level bcs_fine_dolfinx = None # Stores the BCs for finest level b_fine_dolfx = None # Stores the b object for finest level V_fine_dolfx = None # Stores the CG1 Function space for finest level # Assembling the dictionaries and operators defined above using Dolfinx Functions for i in range(coarsest_level, finest_level + 1): num_elems_i = coarsest_level_elements_per_dim * 2**i element_size[i] = 1 / num_elems_i mesh_i = dolfinx.UnitSquareMesh(MPI.COMM_WORLD, num_elems_i, num_elems_i, dolfinx.cpp.mesh.CellType.triangle) V_i = dolfinx.FunctionSpace(mesh_i, ("CG", 1)) V_dof_coord_i = V_i.tabulate_dof_coordinates() dof_dict_i = {} for j in range(0, V_i.dofmap.index_map.size_local * V_i.dofmap.index_map_bs): cord_tup = tuple(round(cor, 9) for cor in V_dof_coord_i[j]) dof_dict_i[j] = cord_tup dof_dict_i[cord_tup] = j mesh_dof_list_dict[i] = dof_dict_i # Stores the dofs at a level in dict del dof_dict_i uD_i = dolfinx.Function(V_i) uD_i.interpolate(lambda x: 1 + x[0]**2 + 2 * x[1]**2) uD_i.vector.ghostUpdate(addv=PETSc.InsertMode.INSERT, mode=PETSc.ScatterMode.FORWARD)