def test_surface(): """test whether the surface is calculated correctly""" for dim in [1, 2, 3]: radius = 1 + random.random() eps = 1e-10 vol1 = spherical.volume_from_radius(radius + eps, dim=dim) vol0 = spherical.volume_from_radius(radius, dim=dim) surface_approx = (vol1 - vol0) / eps surface = spherical.surface_from_radius(radius, dim=dim) assert surface == pytest.approx(surface_approx, rel=1e-3) r2s = spherical.make_surface_from_radius_compiled(dim) assert surface == pytest.approx(r2s(radius)) if dim == 1: with pytest.raises(RuntimeError): spherical.radius_from_surface(surface, dim=dim) else: assert spherical.radius_from_surface( surface, dim=dim) == pytest.approx(radius)
def get_triangulation(self, resolution: float = 1) -> Dict[str, Any]: """obtain a triangulated shape of the droplet surface Args: resolution (float): The length of a typical triangulation element. This affects the resolution of the triangulation. Returns: dict: A dictionary containing information about the triangulation. The exact details depend on the dimension of the problem. """ if self.dim == 2: num = max(3, int(np.ceil(self.surface_area / resolution))) angles = np.linspace(0, 2 * np.pi, num + 1, endpoint=True) vertices = self.interface_position(angles) lines = np.c_[np.arange(num), np.arange(1, num + 1) % num] return {"vertices": vertices, "lines": lines} elif self.dim == 3: # estimate the number of triangles covering the surface try: surface_area = self.surface_area except (NotImplementedError, AttributeError): # estimate surface area from 3d spherical droplet surface_area = spherical.surface_from_radius(self.radius, dim=3) num_est = (4 * surface_area) / (np.sqrt(3) * resolution**2) tri = triangulated_spheres.get_triangulation(num_est) φ, θ = tri["angles"][:, 0], tri["angles"][:, 1] return { "vertices": self.interface_position(θ, φ), "triangles": tri["cells"], } else: raise NotImplementedError( f"Triangulation not implemented for {self.dim}d")
def surface_area(self) -> float: """float: surface area of the droplet""" return spherical.surface_from_radius(self.radius, self.dim)