def charged_nucleation_in_2D(writer,
                             args,
                             R=30,
                             D=25,
                             weights=(0, -10, -8, 8)):
    dx = 2 * R / args.height
    x = (np.arange(args.width) - args.width // 2) * dx
    y = (np.arange(args.height) - args.height // 2) * dx
    x, y = np.meshgrid(x, y, indexing='ij')

    def source_G(t):
        amount = np.exp(-0.5 * (t - 5)**2)
        return (np.exp(-0.5 *
                       ((x - D)**2 + y * y)) * weights[0] + np.exp(-0.5 * (
                           (x + D)**2 + y * y)) * weights[1]) * amount

    def source_X(t):
        amount = np.exp(-0.5 * (t - 5)**2)
        return (np.exp(-0.5 *
                       ((x - D)**2 + y * y)) * weights[2] + np.exp(-0.5 * (
                           (x + D)**2 + y * y)) * weights[3]) * amount

    source_functions = {
        'G': source_G,
        'X': source_X,
    }

    noise_scale = 1e-4
    model_g = ModelG(
        bl_noise(x.shape) * noise_scale,
        bl_noise(x.shape) * noise_scale,
        bl_noise(x.shape) * noise_scale,
        dx,
        dt=args.dt,
        params=args.model_params,
        source_functions=source_functions,
    )

    print("Rendering 'Charged nucleation in 2D'")
    print("Lattice constant dx = {}, time step dt = {}".format(
        model_g.dx, model_g.dt))
    min_G = -4.672736908320116
    max_G = 0.028719261862332906
    min_X = -3.8935243721220334
    max_X = 1.2854028081816122
    min_Y = -0.7454193158963579
    max_Y = 4.20524950766914
    for n in progressbar.progressbar(range(args.num_frames)):
        model_g.step()
        if n % args.oversampling == 0:
            rgb = [
                6 * (-model_g.G + max_G) / (max_G - min_G),
                5 * (model_g.Y - min_Y) / (max_Y - min_Y),
                0.7 * (model_g.X - min_X) / (max_X - min_X),
            ]
            zero_line = 1 - tf.exp(-600 * model_g.Y**2)
            frame = make_video_frame([c * zero_line for c in rgb])
            writer.append_data(frame)
Exemple #2
0
def soliton_in_g_well_2D(writer, args, R=25, D=15):
    dx = 2 * R / args.height
    x = (np.arange(args.width) - args.width // 2) * dx
    y = (np.arange(args.height) - args.height // 2) * dx
    x, y = np.meshgrid(x, y, indexing='ij')

    def source_G(t):
        nucleator = -np.exp(-0.5 * (t - 5)**2)
        #potential = 0.015 * (np.tanh(t-25) + 1)
        #potential = 0.0003 * (np.tanh(t-25) + 1)   # gradient = (1+np.tanh(t-30)) * 0.0003 # see above

        #u = x / R
        #u = x/10 - 5  # see: "soliton_in_g_well_2D___1_seed__gradient_1__2a.mp4"
        #u = x/15 # see: "soliton_in_g_well_2D___1_seed__gradient_2__2b.mp4"
        #u = x/25
        return (
            #np.exp(-0.5*((x-D)**2+y*y)) * nucleator +
            #(u*u - 1) * potential
            np.exp(-0.5 * ((x)**2 + y * y)) * nucleator  #+ (x+8) * potential
            #(u*u - 1) * potential #+ (x+8) * gradient
        )

    source_functions = {
        'G': source_G,
    }

    noise_scale = 1e-4
    model_g = ModelG(
        bl_noise(x.shape) * noise_scale,
        bl_noise(x.shape) * noise_scale,
        bl_noise(x.shape) * noise_scale,
        dx,
        dt=args.dt,
        params=args.model_params,
        source_functions=source_functions,
    )

    print("Rendering 'Soliton in G-well in 2D'")
    print("Lattice constant dx = {}, time step dt = {}".format(
        model_g.dx, model_g.dt))
    G_scale = 0.02
    X_scale = 0.25
    Y_scale = 0.5
    for n in progressbar.progressbar(range(args.num_frames)):
        model_g.step()
        if n % args.oversampling == 0:
            rgb = [
                (G_scale * 0.5 - model_g.G) / G_scale,
                (model_g.Y - Y_scale * 0.5) / Y_scale,
                (model_g.X - X_scale * 0.5) / X_scale,
            ]
            zero_line = 1 - tf.exp(-600 * model_g.Y**2)
            frame = make_video_frame([c * zero_line for c in rgb])
            writer.append_data(frame)
def random_1D_fields():
    x = linspace(-20, 20, 512)
    dx = x[1] - x[0]
    noise_scale = 1.0

    fig, axs = subplots(2, 3)
    for ax_ in axs:
        for ax in ax_:
            while True:
                params = {
                    "A": rand() * 20,
                    "B": rand() * 20,
                    "k2": rand() * 2,
                    "k-2": rand() * 2,
                    "k5": rand() * 2,
                    "Dx": rand() * 4,
                    "Dy": rand() * 4,
                }
                model_g = ModelG(bl_noise(x.shape) * noise_scale,
                                 bl_noise(x.shape) * noise_scale,
                                 bl_noise(x.shape) * noise_scale,
                                 dx,
                                 params=params)

                while model_g.t < 20:
                    model_g.step()
                    if rand() < 0.05:
                        G, X, Y = model_g.numpy()
                        if abs(X).max() >= 100:
                            break

                G, X, Y = model_g.numpy()
                if abs(X).max() < 100:
                    break
                print("Rejected", params)

            print("Done", params)

            G /= abs(G).max()
            X /= abs(X).max()
            Y /= abs(Y).max()

            ax.plot(x, G)
            ax.plot(x, X)
            ax.plot(x, Y)
    show()
def nucleation_3D(writer, args, R=20):
    raise NotImplementedError("Needs some work")
    params = {
        "A": 3.4,
        "B": 13.5,
        "k2": 1.0,
        "k-2": 0.1,
        "k5": 0.9,
        "D_G": 1.0,
        "D_X": 1.0,
        "D_Y": 1.95,
        "density_G": 1.0,
        "density_X": 0.0002,
        "density_Y": 0.043,
        "base-density": 9.0,
        "viscosity": 0.3,
        "speed-of-sound": 1.0,
    }

    dx = 2 * R / args.height
    x = (np.arange(args.width) - args.width // 2) * dx
    y = (np.arange(args.height) - args.height // 2) * dx
    z = y
    x, y, z = np.meshgrid(x, y, z, indexing='ij')

    def source_G(t):
        center = np.exp(-0.3 * (t - 6)**2) * 10
        return -np.exp(-0.5 * (x * x + y * y + z * z)) * center

    source_functions = {
        'G': source_G,
    }

    # We need some noise to break spherical symmetry
    noise_scale = 1e-4
    G = bl_noise(x.shape) * noise_scale
    X = bl_noise(x.shape) * noise_scale
    Y = bl_noise(x.shape) * noise_scale
    flow = [
        bl_noise(x.shape) * noise_scale,
        bl_noise(x.shape) * noise_scale,
        bl_noise(x.shape) * noise_scale
    ]

    fluid_model_g = FluidModelG(
        G,
        X,
        Y,
        flow,
        dx,
        dt=args.dt,
        params=params,
        source_functions=source_functions,
    )

    flow_particle_origins = []
    for _ in range(1000):
        flow_particle_origins.append([np.random.rand() * s for s in x.shape])

    flow_particles = tf.constant(flow_particle_origins, dtype='float64')
    flow_streaks = 0 * x[:, :, 0]

    print("Rendering 'Nucleation and Motion in G gradient in 3D'")
    print("Lattice constant dx = {}, time step dt = {}".format(
        fluid_model_g.dx, fluid_model_g.dt))
    for n in progressbar.progressbar(range(args.num_frames)):
        fluid_model_g.step()
        for _ in range(20):
            indices = tf.cast(flow_particles, 'int32')
            for index in indices.numpy():
                flow_streaks[index[0], index[1]] += 0.15 / args.oversampling
            dx = tf.gather_nd(fluid_model_g.u, indices)
            dy = tf.gather_nd(fluid_model_g.v, indices)
            dz = tf.gather_nd(fluid_model_g.w, indices)
            flow_particles = (flow_particles +
                              tf.stack([dx, dy, dz], axis=1) * 400) % x.shape
        if n % args.oversampling == 0:
            rgb = [
                tf.reduce_mean(
                    (7 * fluid_model_g.G)**2, axis=2) + flow_streaks,
                tf.reduce_mean((4 * fluid_model_g.Y)**2, axis=2),
                tf.reduce_mean((2 * fluid_model_g.X)**2, axis=2),
            ]
            frame = make_video_frame(rgb)
            writer.append_data(frame)
            flow_streaks *= 0
            flow_particles = tf.constant(flow_particle_origins,
                                         dtype='float64')
Exemple #5
0
def nucleation_3D(animated=False, N=128, R=20):
    params = {
        "A": 3.4,
        "B": 13.5,
        "k2": 1.0,
        "k-2": 0.1,
        "k5": 0.9,
        "D_G": 1.0,
        "D_X": 1.0,
        "D_Y": 1.95,
        "density_G": 1.0,
        "density_X": 0.0002,
        "density_Y": 0.043,
        "base-density": 20.0,
        "viscosity": 0.4,
        "speed-of-sound": 1.0,
    }

    x = np.linspace(-R, R, N)
    dx = x[1] - x[0]
    x, y, z = np.meshgrid(x, x, x, indexing='ij')

    def source_G(t):
        center = np.exp(-0.5 * (t - 5)**2) * 10
        return -np.exp(-0.5 * (x * x + y * y + z * z)) * center

    source_functions = {
        'G': source_G,
    }

    # We need some noise to break spherical symmetry
    noise_scale = 1e-4
    G = bl_noise(x.shape) * noise_scale
    X = bl_noise(x.shape) * noise_scale
    Y = bl_noise(x.shape) * noise_scale
    flow = [
        bl_noise(x.shape) * noise_scale,
        bl_noise(x.shape) * noise_scale,
        bl_noise(x.shape) * noise_scale
    ]

    dt = 0.2 * dx
    fluid_model_g = FluidModelG(
        G,
        X,
        Y,
        flow,
        dx,
        dt=dt,
        params=params,
        source_functions=source_functions,
    )

    if animated:

        def get_data():
            G, X, Y, (u, v, w) = fluid_model_g.numpy()

            x_scale = 0.1
            y_scale = 0.1
            return (
                G[N // 2, N // 2],
                X[N // 2, N // 2] * x_scale,
                Y[N // 2, N // 2] * y_scale,
                u[N // 2, N // 2],
                v[N // 2, N // 2],
                w[N // 2, N // 2],
            )

        G, X, Y, u, v, w = get_data()
        plots = []
        plots.extend(pylab.plot(z[0, 0], G))
        plots.extend(pylab.plot(z[0, 0], X))
        plots.extend(pylab.plot(z[0, 0], Y))
        plots.extend(pylab.plot(z[0, 0], u))
        plots.extend(pylab.plot(z[0, 0], v))
        pylab.ylim(-0.1, 0.1)

        def update(frame):
            fluid_model_g.step()
            G, X, Y, u, v, w = get_data()
            print(fluid_model_g.t, abs(G).max(), abs(u).max())
            plots[0].set_ydata(G)
            plots[1].set_ydata(X)
            plots[2].set_ydata(Y)
            plots[3].set_ydata(u)
            plots[4].set_ydata(v)
            plots[4].set_ydata(w)
            return plots

        FuncAnimation(pylab.gcf(),
                      update,
                      frames=range(100),
                      init_func=lambda: plots,
                      blit=True,
                      repeat=True,
                      interval=20)
        pylab.show()
    else:
        from datetime import datetime
        from pathlib import Path
        start = datetime.now()

        num_steps = int(1.0 / dt)
        print("Starting simulation {} steps at a time".format(num_steps))

        path = Path("/tmp/model_g")
        path.mkdir(exist_ok=True)
        while True:
            for _ in range(num_steps):
                fluid_model_g.step()
            print("Saving a snapshot into {}".format(path))
            G, X, Y, (u, v, w) = fluid_model_g.numpy()
            np.save(path / 'G.npy', G)
            np.save(path / 'X.npy', X)
            np.save(path / 'Y.npy', Y)
            np.save(path / 'u.npy', u)
            np.save(path / 'v.npy', v)
            np.save(path / 'w.npy', w)
            print("Saved everything")

            wall_clock_time = (datetime.now() - start).total_seconds()
            print("t={}, wall clock time={} s, efficiency={}".format(
                fluid_model_g.t, wall_clock_time,
                fluid_model_g.t / wall_clock_time))
            print("max|G|={}, max|u|={}".format(abs(G).max(), abs(u).max()))
def nucleation_3D(writer, args, R=12):
    #    raise NotImplementedError("Needs some work")
    params = {
        "A": 3.4,
        "B": 13.5,
        "k2": 1.0,
        "k-2": 0.1,
        "k5": 0.9,
        "D_G": 1.0,
        "D_X": 1.0,
        "D_Y": 1.95,
        "density_G": 1.0,
        "density_X": 0.0002,
        "density_Y": 0.043,
        "base-density": 9.0,
        "viscosity": 0.3,
        "speed-of-sound": 1.0,
    }
    c1 = 0  # BJD added this on 22.4.2021
    dx = 2 * R / args.height
    x = (np.arange(args.width) - args.width // 2) * dx
    y = (np.arange(args.height) - args.height // 2) * dx
    z = y
    x, y, z = np.meshgrid(x, y, z, indexing='ij')

    def source_G(t):
        center = np.exp(-0.3 * (t - 6)**2) * 10
        return -np.exp(-0.5 * (x * x + y * y + z * z)) * center

    source_functions = {
        'G': source_G,
    }

    # We need some noise to break spherical symmetry
    noise_scale = 1e-4
    G = bl_noise(x.shape) * noise_scale
    X = bl_noise(x.shape) * noise_scale
    Y = bl_noise(x.shape) * noise_scale
    flow = [
        bl_noise(x.shape) * noise_scale,
        bl_noise(x.shape) * noise_scale,
        bl_noise(x.shape) * noise_scale
    ]

    fluid_model_g = FluidModelG(
        G,
        X,
        Y,
        flow,
        dx,
        dt=args.dt,
        params=params,
        source_functions=source_functions,
    )

    flow_particle_origins = []
    for _ in range(1000):
        flow_particle_origins.append([np.random.rand() * s for s in x.shape])

    flow_particles = tf.constant(flow_particle_origins, dtype='float64')
    flow_streaks = 0 * x[:, :, 0]

    print("Rendering 'Nucleation and Motion in G gradient in 3D'")
    print("Lattice constant dx = {}, time step dt = {}".format(
        fluid_model_g.dx, fluid_model_g.dt))
    for n in progressbar.progressbar(range(args.num_frames)):
        fluid_model_g.step()
        for _ in range(20):
            indices = tf.cast(flow_particles, 'int32')
            for index in indices.numpy():
                flow_streaks[index[0], index[1]] += 0.15 / args.oversampling
            dx = tf.gather_nd(fluid_model_g.u, indices)
            dy = tf.gather_nd(fluid_model_g.v, indices)
            dz = tf.gather_nd(fluid_model_g.w, indices)
            flow_particles = (flow_particles +
                              tf.stack([dx, dy, dz], axis=1) * 400) % x.shape
        if n % args.oversampling == 0:
            rgb = [
                tf.reduce_mean(
                    (7 * fluid_model_g.G)**2, axis=2) + flow_streaks,
                tf.reduce_mean((4 * fluid_model_g.Y)**2, axis=2),
                tf.reduce_mean((2 * fluid_model_g.X)**2, axis=2),
            ]
            frame = make_video_frame(rgb)
            writer.append_data(frame)
            flow_streaks *= 0
            flow_particles = tf.constant(flow_particle_origins,
                                         dtype='float64')
            #=====================BJD 20.4.2021==========================================
            #-------------------------BJD 22.4.2021----rough code at present-----------------------------------------
            if n == 200:
                print("n = ", n)
                break
            #c1 = c1 + 1
            print("H E L L O")
            #y1 = np.loadtxt("/home/brendan/software/tf2-model-g/arrays/quiver_array14/u.txt") #, delimiter=" :-) ", usecols=(120))  # (426, 240)
            #y2 = np.loadtxt("/home/brendan/software/tf2-model-g/arrays/quiver_array14/v.txt") #, delimiter=" :-) ", usecols=(120))  # (426, 240)

            c1 = c1 + 1
            # Set up grid and test data
            #nx, ny = 256, 1024
            nx, ny, nz = 240, 426, 426
            #nx, ny = 426, 240  # changed round to check!
            #(426,240)
            x1 = range(nx)
            y1 = range(ny)
            z1 = range(nz)
            #data = numpy.random.random((nx, ny))
            U = np.loadtxt(
                "/home/brendan/software/tf2-model-g/arrays/quiver3D_array31/u.txt"
            )  #, delimiter=" :-) ", usecols=(120))  # (426, 240)
            V = np.loadtxt(
                "/home/brendan/software/tf2-model-g/arrays/quiver3D_array31/v.txt"
            )  #, delimiter=" :-) ", usecols=(120))  # (426, 240)
            W = np.loadtxt(
                "/home/brendan/software/tf2-model-g/arrays/quiver3D_array31/w.txt"
            )  #, delimiter=" :-) ", usecols=(120))  # (426, 240)
            # BJD 28.1.2021: u and v are saved as arrays in fluid_model_g.py as fllows:
            # np.savetxt("/home/brendan/software/tf2-model-g/arrays/quiver_array18/u.txt", self.u)
            # np.savetxt("/home/brendan/software/tf2-model-g/arrays/quiver_array18/v.txt", self.v)

            #data = np.loadtxt("/home/brendan/software/tf2-model-g/arrays/array12/Y.txt")

            #hf = plt.figure(figsize=(10,10))
            #ha = hf.add_subplot(111, projection='3d')
            #ha = hf.add_subplot(111, projection='2d')

            X1, Y1, Z1 = np.meshgrid(
                x1, y1, z1)  # `plot_surface` expects `x` and `y` data to be 2D
            #x, y, z = np.meshgrid(np.arange(-0.8, 1, 0.2),
            #          np.arange(-0.8, 1, 0.2),
            #          np.arange(-0.8, 1, 0.8))
            #ha.plot_surface(X, Y, data)
            #ha.plot_surface(X, Y, data, rstride=1, cstride=1, cmap=cm.coolwarm,
            #                       linewidth=0, antialiased=False)
            #ha.plot_surface(X.T, Y.T, data)

            #surf = ha.plot_surface(X1, Y1, data, rstride=1, cstride=1, cmap=cm.coolwarm,
            #           linewidth=0, antialiased=False)
            #ha.set_zlim(-1, 3)
            #hf.colorbar(surf, shrink=0.5, aspect=10)
            #hf = plt.figure(figsize=(10,10))
            """
            
            fig, hf = plt.subplots(figsize=(10,10))
            #ax3.set_title("pivot='tip'; scales with x view")
            hf.set_title("pivot='tip'; scales with x view" + str(c1))
            M = np.hypot(U, V)
            Q = hf.quiver(X1, Y1, U, V, M, units='x', pivot='tip', width=0.022,
               scale=1 / 0.15)
            qk = hf.quiverkey(Q, 0.9, 0.9, 1, r'$1 \frac{m}{s}$', labelpos='E',
                   coordinates='figure')
            hf.scatter(X1, Y1, color='0.5', s=1)

            # Below, from Color_Quiver_Plot.py 17.4.2021 - BJD 
            color = np.sqrt(((dx-n)/2)*2 + ((dy-n)/2)*2)  
  
            ax2.quiver(X, Y, dx, dy, color) 
            ax2.xaxis.set_ticks([]) 
            ax2.yaxis.set_ticks([]) 
            ax2.set_aspect('equal') 
            ax2.set_title('gradient') 
            plt.tight_layout() 
            plt.show()

            #also arrow head 17.4.2021 BJD:
            Q = hf.quiver(X1[::10, ::10], Y1[::10, ::10], U[::10, ::10], V[::10, ::10], units='width',
                pivot='mid', scale=0.005)#pivot='mid', units='inches')#, scale=1)#, scale=5)
            """
            #fig, hf = plt.subplots(figsize=(10,10))
            fig = plt.figure(figsize=(10, 10))
            ax = fig.gca(projection='3d')
            ax.set_title(
                "pivot='mid'; every 10th arrow; units='velocity vector' time="
                + str(c1))
            #Q = ax.quiver(X1[::10, ::10], Y1[::10, ::10], Z1[::10, ::10], U[::10, ::10],
            #    V[::10, ::10], W[::10, ::10], pivot='mid', units='inches')
            Q = ax.quiver(X1[::10, ::10, ::10],
                          Y1[::10, ::10, ::10],
                          Z1[::10, ::10, ::10],
                          U[::10, ::10, ::10],
                          V[::10, ::10, ::10],
                          W[::10, ::10, ::10],
                          pivot='mid',
                          units='inches')

            #hf.set_title("pivot='mid'; every 10th arrow; units='velocity vector' time=" + str(c1))
            #Q = hf.quiver(X1[::10, ::10], Y1[::10, ::10], U[::10, ::10], V[::10, ::10], pivot='mid',
            #units='inches')

            #q = ax.quiver(x, y, z, u, v, w, length=0.1, cmap='Reds', lw=2)
            #q.set_array(np.random.rand(np.prod(x.shape)))
            Q.set_array(np.random.rand(np.prod(
                x.shape)))  # may need this? BJD 22.4.2021
            #plt.show()
            #qk = ax.quiverkey(Q, 0.9, 0.9, 5, r'$1 \frac{m}{s}$', labelpos='E',
            #coordinates='figure')
            #Q = hf.quiver(X1[::10, ::10], Y1[::10, ::10], U[::10, ::10], V[::10, ::10], units='width',
            #pivot='mid', scale=0.1, headwidth=7)
            #ax1.quiver(X, Y, u, v, color, alpha = 0.8) # from Color_Quiver_Plot.py
            #qk = hf.quiverkey(Q, 0.9, 0.9, 5, r'$1 \frac{m}{s}$', labelpos='E',
            #coordinates='figure')
            #hf.scatter(X1[::10, ::10], Y1[::10, ::10], color='r', s=5)
            #hf.scatter(X1[::10, ::10], Y1[::10, ::10], color='c', alpha = 0.8)
            #hf.scatter(X1[::10, ::10], Y1[::10, ::10], color='c', s=0)
            #ax.scatter(X1[::10, ::10], Y1[::10, ::10], Z1[::10, ::10], color='c', s=0)
            ax.scatter(X1[::10, ::10, ::10],
                       Y1[::10, ::10, ::10],
                       Z1[::10, ::10, ::10],
                       color='c',
                       s=0)
            plt.tight_layout()
            plt.savefig(
                '/home/brendan/software/tf2-model-g/plots/3D_video37/3D_video_velocity_'
                + str(c1) + '.png')
def self_stabilizing_soliton_2D():
    params = {
        "A": 4.2,
        "B": 18,
        "k2": 1.0,
        "k-2": 0.2,
        "k5": 0.9,
        "D_G": 1.0,
        "D_X": 1.0,
        "D_Y": 2.0,
    }

    x = np.linspace(-16, 16, 256)
    dx = x[1] - x[0]
    x, y = np.meshgrid(x, x)

    r2 = x * x + y * y
    model_g = ModelG(
        -np.exp(-0.1 * r2) * 1.0,
        np.exp(-r2) * 0.01,
        np.exp(-r2) * 0.01 + bl_noise(x.shape) * 0.02,
        dx,
        0.1 * dx,
        params,
    )

    def get_data():
        G, X, Y = model_g.numpy()
        x_scale = 0.2
        y_scale = 0.1
        return (
            G[64],
            X[64] * x_scale,
            Y[64] * y_scale,
        )

    G, X, Y = get_data()
    plots = []
    plots.extend(pylab.plot(x[0], G))
    plots.extend(pylab.plot(x[0], X))
    plots.extend(pylab.plot(x[0], Y))
    pylab.ylim(-0.03, 0.03)

    def update(frame):
        for _ in range(5):
            model_g.step()
        G, X, Y = get_data()
        plots[0].set_ydata(G)
        plots[1].set_ydata(X)
        plots[2].set_ydata(Y)
        return plots

    FuncAnimation(pylab.gcf(),
                  update,
                  frames=range(100),
                  init_func=lambda: plots,
                  blit=True,
                  repeat=True,
                  interval=20)
    pylab.show()

    G, X, Y = model_g.numpy()
    pylab.imshow(Y)
    pylab.show()
def random_3D():
    r = np.random.randn
    params = {
        "A": 2 + r() * 0.1,
        "B": 10 + r(),
        "k2": 1.0 + 0.1 * r(),
        "k-2": 0.1 + 0.01 * r(),
        "k5": 0.9 + 0.1 * r(),
        "D_G": 1.0,
        "D_X": 1.0 + 0.1 * r(),
        "D_Y": 2.0 + 0.1 * r(),
    }
    print(params)

    x = np.linspace(-16, 16, 128)
    dx = x[1] - x[0]
    x, y, z = np.meshgrid(x, x, x)

    def source_G(t):
        center = np.exp(-0.5 * (t - 20)**2) * 10
        gradient = (1 + np.tanh(t - 40)) * 0.0005
        print("t = {}\tcenter potential = {}\tx-gradient = {}".format(
            t, center, gradient))
        return -np.exp(-0.5 * (x * x + y * y + z * z)) * center + x * gradient

    source_functions = {
        'G': source_G,
    }

    model_g = ModelG(
        bl_noise(x.shape) * 0.01,
        bl_noise(x.shape) * 0.01,
        bl_noise(x.shape) * 0.01,
        dx,
        params,
        source_functions=source_functions,
    )

    def get_data():
        G, X, Y = model_g.numpy()
        x_scale = 0.1
        y_scale = 0.1
        return (
            G[64, 64],
            X[64, 64] * x_scale,
            Y[64, 64] * y_scale,
        )

    G, X, Y = get_data()
    plots = []
    plots.extend(pylab.plot(z[0, 0], G))
    plots.extend(pylab.plot(z[0, 0], X))
    plots.extend(pylab.plot(z[0, 0], Y))
    pylab.ylim(-0.5, 0.5)

    def update(frame):
        model_g.step()
        G, X, Y = get_data()
        plots[0].set_ydata(G)
        plots[1].set_ydata(X)
        plots[2].set_ydata(Y)
        return plots

    FuncAnimation(pylab.gcf(),
                  update,
                  frames=range(100),
                  init_func=lambda: plots,
                  blit=True,
                  repeat=True,
                  interval=20)
    pylab.show()

    G, X, Y = model_g.numpy()
    plots = [pylab.imshow(X[64])]

    def update(frame):
        model_g.step()
        G, X, Y = model_g.numpy()
        plots[0].set_data(X[64])
        return plots

    FuncAnimation(pylab.gcf(),
                  update,
                  frames=range(100),
                  init_func=lambda: plots,
                  blit=True,
                  repeat=True,
                  interval=20)
    pylab.show()

    fig = pylab.figure()
    ax = fig.add_subplot(111, projection='3d')

    G, X, Y = model_g.numpy()
    m = X.max() - (X.max() - X.min()) * 0.3
    points = []
    for _ in range(1000000):
        px = np.random.randint(x.shape[0])
        py = np.random.randint(y.shape[1])
        pz = np.random.randint(z.shape[2])

        c = X[px, py, pz]

        if c > m:
            points.append((px, py, pz, c))
            if len(points) > 20000:
                break

    xs, ys, zs, cs = zip(*points)
    ax.scatter3D(xs, ys, zs, c=cs)
    pylab.show()
def random_2D():
    r = np.random.randn
    params = {
        "A": 2 + r() * 0.1,
        "B": 10 + r(),
        "k2": 1.0 + 0.1 * r(),
        "k-2": 0.1 + 0.01 * r(),
        "k5": 0.9 + 0.1 * r(),
        "D_G": 1.0,
        "D_X": 1.0 + 0.1 * r(),
        "D_Y": 2.0 + 0.1 * r(),
    }
    print(params)

    x = np.linspace(-16, 16, 256)
    dx = x[1] - x[0]
    x, y = np.meshgrid(x, x)

    def source_G(t):
        center = np.exp(-0.5 * (t - 20)**2) * 10
        gradient = (1 + np.tanh(t - 40)) * 0.0005
        print("t = {}\tcenter potential = {}\tx-gradient = {}".format(
            t, center, gradient))
        return -np.exp(-0.5 * (x * x + y * y)) * center + x * gradient

    source_functions = {
        'G': source_G,
    }

    model_g = ModelG(
        bl_noise(x.shape) * 0.01,
        bl_noise(x.shape) * 0.01,
        bl_noise(x.shape) * 0.01,
        dx,
        0.1 * dx,
        params,
        source_functions=source_functions,
    )

    def get_data():
        G, X, Y = model_g.numpy()
        x_scale = 0.1
        y_scale = 0.1
        return (
            G[64],
            X[64] * x_scale,
            Y[64] * y_scale,
        )

    G, X, Y = get_data()
    plots = []
    plots.extend(pylab.plot(x[0], G))
    plots.extend(pylab.plot(x[0], X))
    plots.extend(pylab.plot(x[0], Y))
    pylab.ylim(-0.5, 0.5)

    def update(frame):
        model_g.step()
        G, X, Y = get_data()
        plots[0].set_ydata(G)
        plots[1].set_ydata(X)
        plots[2].set_ydata(Y)
        return plots

    FuncAnimation(pylab.gcf(),
                  update,
                  frames=range(100),
                  init_func=lambda: plots,
                  blit=True,
                  repeat=True,
                  interval=20)
    pylab.show()

    G, X, Y = model_g.numpy()
    plots = [pylab.imshow(X)]

    def update(frame):
        model_g.step()
        G, X, Y = model_g.numpy()
        plots[0].set_data(X)
        return plots

    FuncAnimation(pylab.gcf(),
                  update,
                  frames=range(100),
                  init_func=lambda: plots,
                  blit=True,
                  repeat=True,
                  interval=20)
    pylab.show()