Example #1
0
def test_spherical_index():
    """test the conversion of the spherical index"""
    # check initial state
    assert spherical.spherical_index_lm(0) == (0, 0)
    assert spherical.spherical_index_k(0, 0) == 0

    # check conversion
    for k in range(20):
        l, m = spherical.spherical_index_lm(k)
        assert spherical.spherical_index_k(l, m) == k

    # check order
    k = 0
    for l in range(4):
        for m in range(-l, l + 1):
            assert spherical.spherical_index_k(l, m) == k
            k += 1

    for l in range(4):
        k_max = spherical.spherical_index_k(l, l)
        assert spherical.spherical_index_count(l) == k_max + 1

    for l in range(4):
        for m in range(-l, l + 1):
            is_optimal = m == l
            k = spherical.spherical_index_k(l, m)
            assert spherical.spherical_index_count_optimal(k + 1) == is_optimal
Example #2
0
 def __init__(
     self,
     position: np.ndarray,
     radius: float,
     interface_width: float = None,
     amplitudes: np.ndarray = None,
 ):
     r"""
     Args:
         position (:class:`~numpy.ndarray`):
             Position of the droplet center
         radius (float):
             Radius of the droplet
         interface_width (float, optional):
             Width of the interface
         amplitudes (:class:`~numpy.ndarray`):
             Perturbation amplitudes :math:`\epsilon_{l,m}`. Note that the zero-th
             mode, which would only change the radius, is skipped. Consequently, the
             length of the array needs to be 0, 3, 8, 15, 24, ... to capture
             perturbations of the highest mode consistently.
     """
     super().__init__(position, radius, interface_width, amplitudes)
     num_modes = len(self.amplitudes) + 1
     if not spherical.spherical_index_count_optimal(num_modes):
         logger = logging.getLogger(self.__class__.__name__)
         l, _ = spherical.spherical_index_lm(num_modes)
         opt_modes = spherical.spherical_index_count(l) - 1
         logger.warning(
             "The length of `amplitudes` should be such that all orders are "
             f"captured for the perturbations with the highest degree ({l}). "
             f"Consider increasing the size of the array to {opt_modes}.")
Example #3
0
    def interface_curvature(self, θ, φ):
        r"""calculates the mean curvature of the interface of the droplet

        For simplicity, the effect of the perturbations are only included to
        linear order in the perturbation amplitudes :math:`\epsilon_{l,m}`.

        Args:
            θ (float or array): Azimuthal angle (in :math:`[0, \pi]`)
            φ (float or array): Polar angle (in :math:`[0, 2\pi]`)

        Returns:
            An array with the curvature at the interfacial points associated
            with the angles
        """
        Yk = spherical.spherical_harmonic_real_k
        correction = 0
        for k, a in enumerate(self.amplitudes, 1):  # skip zero-th mode!
            if a != 0:
                l, _ = spherical.spherical_index_lm(k)
                hk = (l**2 + l - 2) / 2
                correction = a * hk * Yk(k, θ, φ)
        return 1 / self.radius + correction / self.radius**2