mathr / blog / #

Atom domain coordinates

Previously I wrote about atom domain size estimates in the Mandelbrot set. A logical step given \(G(c) = 0\) at the center and \(|G(c)| = 1\) on the boundary is to take \(G(c)\) as the atom domain coordinate for \(c\). It turns out to make sense to make \(1 \le q \lt p\) arguments to the function, and evaluate them at the central nucleus, because otherwise the assumption that \(p, q\) are constant throughout the domain can be violated (particularly with neighbouring domains in embedded Julia sets, where the higher period one is not "influenced" by the medium period one it overlaps, but instead by the lower period "parent" of both):

\[G(c, q, p) = \frac{F^p(0, c)}{F^q(0, c)}\]

In my efficient automated Julia morphing experiments recently I used the atom domain coordinates for guessing an initial point for Newton's method to find Misiurewicz points. This worked because each next level of morph had an atom domain coordinate approximately the previous raised to the power \(\frac{3}{2}\). To do this I needed to implement Newton's method iterations to find \(c\) given \(G(c), p, q\). Pseudo-code for that looks like this:

double _Complex m_domain_coord
( double _Complex c0
, double _Complex G
, int q
, int p
, int n
) {
  double _Complex c = c0;
  for (int j = 0; j < n; ++j)
  {
    double _Complex zp = 0;
    double _Complex dcp = 0;
    double _Complex z = 0;
    double _Complex dc = 0;
    for (int i = 1; i <= p; ++i)
    {
      dc = 2 * z * dc + 1;
      z = z * z + c;
      if (i == q)
      {
        zp = z;
        dcp = dc;
      }
    }
    double _Complex f = z / zp - G;
    double _Complex df = (dc * zp - z * dcp) / (zp * zp);
    c = c - f / df;
  }
  return c;
}

You can find fuller implementations (including arbitrary precision) in my mandelbrot-numerics repository.