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_add_field(): n = 20 x = np.random.rand(n, 3) p = pyleopart.Particles(x, [0] * n) cp = p.cell_particles() assert (len(cp[0]) == n) p.add_field("w", [3]) assert (p.field("w").value_shape == [3]) p.add_field("u", [3, 2]) u = p.field("u") assert (u.value_shape == [3, 2]) assert (u.value_size == 6) with pytest.raises(IndexError): r = p.field("r")
def test_add_delete_particles(): n = 20 x = np.random.rand(n, 3) p = pyleopart.Particles(x, list(range(n))) x = np.random.rand(3) # Add to cell 12 p.add_particle(x, 12) cp = p.cell_particles() assert (len(cp[12]) == 2) # Delete from cell 1 p.delete_particle(0, 0) cp = p.cell_particles() assert (len(cp[0]) == 0) # Add to cell 0 p.add_particle(x, 1) cp = p.cell_particles() assert (cp[1][1] == 0)
def test_simple_create(): x = np.array([[1, 2, 3]], dtype=np.float64) p = pyleopart.Particles(x, [0]) cp = p.cell_particles() assert (cp[0][0] == 0) assert ((p.field("x").data(0) == [1, 2, 3]).all())
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