%pip install --quiet phiflow
from phi.jax.flow import *
# from phi.flow import * # If JAX is not installed. You can use phi.torch or phi.tf as well.
A Julia set $J_c$, where $c \in \mathbb C$ is defined as all points $z\in\mathbb C$ for which iterating the map $z \rightarrow z^2 + c$ does not diverge towards infinity. Plotting the number of iterations it takes for the sequence to diverge results in a more pleasing rendering. Therefore, we introduce a counter that increases until the sequence reaches $|z|=2$ at which point divergence is guaranteed.
def julia_map(z, counter, c):
next_z = z ** 2 + c
counter += abs(z) < 2
return next_z, counter
def belongs_to_julia_set(z, c, iter_count: int):
final_z, final_counter = iterate(julia_map, iter_count, z, 0, c=c)
return final_counter
We can now sample the Julia on a CenteredGrid
by passing the above function to the constructor, along with the desired resolution and size.
In order to plot a set of Julia sets, we vary $c$ over time: $c = 0.7885 \cdot e^{it}, t\in [0, 2\pi]$.
c = 0.7885 * math.exp(1j*math.linspace(0, 2*PI, batch(time=100)))
sampled = CenteredGrid(lambda re, im: belongs_to_julia_set(re + im*1j, c, 50), re=256, im=256, bounds=Box(re=(-2, 2), im=(-2, 2)))
Let's plot the result as an animation! On the left, we show the current $c$ and on the right the corresponding $J_c$.
plot({"c": vec(re=c.real, im=c.imag), "$J_c$": sampled}, animate='time')
c:\phd\phiflow2\phi\vis\_vis_base.py:507: UserWarning: bounds argument is deprecated since 2.5 and will be ignored. return PointCloud(math.expand(obj, instance(points=1)), bounds=Cuboid(obj, half_size=math.const_vec(1e-3, obj.shape['vector'])).box())