def imgseq2funvec(img: np.array) -> np.array: """Takes a 3D array and returns an array suited to assign to piecewise linear approximation on a triangle grid. Each pixel corresponds to one vertex of a triangle mesh. Args: img (np.array): The input array. Returns: np.array: A vector. """ # Create mesh. [m, n, o] = img.shape mesh = UnitCubeMesh(m-1, n-1, o-1) mc = mesh.coordinates().reshape((-1, 3)) # Evaluate function at vertices. hx, hy, hz = 1./(m-1), 1./(n-1), 1./(o-1) x = np.array(np.round(mc[:, 0]/hx), dtype=int) y = np.array(np.round(mc[:, 1]/hy), dtype=int) z = np.array(np.round(mc[:, 2]/hz), dtype=int) fv = img[x, y, z] # Create function space. V = FunctionSpace(mesh, 'CG', 1) # Map pixel values to vertices. d2v = dof_to_vertex_map(V) return fv[d2v]
def generate_cube(Nelements, length, refinements=0): """ Creates a square mesh of given elements and length with markers on the sides: left, bottom, right and top """ from dolfin import UnitCubeMesh, SubDomain, MeshFunction, Measure, near, refine mesh = UnitCubeMesh(Nelements, Nelements, Nelements) for i in range(refinements): mesh = refine(mesh) mesh.coordinates()[:] *= length # Subdomains: Solid class Xp(SubDomain): def inside(self, x, on_boundary): return near(x[0], length) and on_boundary class Xm(SubDomain): def inside(self, x, on_boundary): return near(x[0], 0.0) and on_boundary class Yp(SubDomain): def inside(self, x, on_boundary): return near(x[1], length) and on_boundary class Ym(SubDomain): def inside(self, x, on_boundary): return near(x[1], 0.0) and on_boundary class Zp(SubDomain): def inside(self, x, on_boundary): return near(x[2], length) and on_boundary class Zm(SubDomain): def inside(self, x, on_boundary): return near(x[2], 0.0) and on_boundary xp, xm, yp, ym, zp, zm = Xp(), Xm(), Yp(), Ym(), Zp(), Zm() XP, XM, YP, YM, ZP, ZM = 1, 2, 3, 4, 5, 6 # Set numbering markers = MeshFunction("size_t", mesh, 2) markers.set_all(0) boundaries = (xp, xm, yp, ym, zp, zm) def_names = (XP, XM, YP, YM, ZP, ZM) for side, num in zip(boundaries, def_names): side.mark(markers, num) return mesh, markers, XP, XM, YP, YM, ZP, ZM
def test_vertex_3d(self): mesh = UnitCubeMesh(8, 8, 8) x = mesh.coordinates() min_ = np.min(x, axis=0) max_ = np.max(x, axis=0) tol = 1E-9 # The precision in gmsh isn't great, probably why DOLFIN's # periodic boundary computation is not working # Check x periodicity master = CompiledSubDomain('near(x[1], A, tol)', A=min_[1], tol=tol) slave = CompiledSubDomain('near(x[1], A, tol)', A=max_[1], tol=tol) shift_x = np.array([0, max_[1]-min_[1], 0]) to_master = lambda x, shift=shift_x: x - shift error, mapping = compute_vertex_periodicity(mesh, master, slave, to_master) self.assertTrue(error < 10*tol) _, mapping = compute_entity_periodicity(2, mesh, master, slave, to_master) self.assertTrue(len(list(mapping.keys())) == 128)
def funvec2imgseq(v: np.array, m: int, n: int, o: int) -> np.array: """Takes values of piecewise linear interpolation of a function at the vertices and returns a 3-dimensional array. Each degree of freedom corresponds to one pixel in the array of size (m, n, o). Args: v (np.array): Values at vertices of triangle mesh. m (int): The number of rows. n (int): The number of columns. Returns: np.array: An array of size (m, n, o). """ # Create image. img = np.zeros((m, n, o)) # Create mesh and function space. mesh = UnitCubeMesh(m-1, n-1, o-1) mc = mesh.coordinates().reshape((-1, 3)) # Evaluate function at vertices. hx, hy, hz = 1./(m-1), 1./(n-1), 1./(o-1) x = np.array(np.round(mc[:, 0]/hx), dtype=int) y = np.array(np.round(mc[:, 1]/hy), dtype=int) z = np.array(np.round(mc[:, 2]/hz), dtype=int) # Create function space and function. V = FunctionSpace(mesh, 'CG', 1) # Create image from function. v2d = vertex_to_dof_map(V) values = v[v2d] for (i, j, k, v) in zip(x, y, z, values): img[i, j, k] = v return img