0

According to Erwin Schrodinger (in What is Life?), diffusion can be explained entirely by the random motion of particles. I want to test this myself by create a program the creates a time-step visualization of the diffusion of "gas molecules" in a closed container. The initial conditions would have two partitions, one with low and one with high concentration. After t0 the partition is removed and the gas is allowed to diffuse. The only mechanism I want to use is adding displacement random vectors to each molecule. The initial conditions would look like this.

enter image description here

The part of the problem that I con't figure out is how to create a simple billiards type reflection when the molecule hits the bounding surfaces. I am assume simple symmetrical reflections (angle in = angle out at boundaries). I haven't started the code at all because I don't know how to deal with this part, while I know how to do the rest of it. I know this is more of a math question, but how can I create these boundary conditions in python? Ideally, I would like to have to program this functionality myself so that I can understand it, rather than using a pre-built package that could do this. This is what I am looking for, for any given molecule.

Ultimately, all I really need is this: given the initial location (x1,y2), a vector magnitude v, an angle theta, and the box size and location, what is the final resting position of the molecule (x2,y2).

enter image description here

bart cubrich
  • 1,184
  • 1
  • 14
  • 41
  • 1
    If it's all the same to you it's actually much easier to do a "proper" angle in equals angle out reflection. See, for example, [here](https://stackoverflow.com/a/48777868/7207392). – Paul Panzer Mar 06 '19 at 18:31
  • It is all the same to me! Thanks! That just shows how little I know about the problem. – bart cubrich Mar 06 '19 at 19:24
  • I can't quit get there with this though. I would to have continuous vector length for the displacement rather than integers, and I need to know the new location of every point in my array of points at each time step. Thanks for you reply though. It definitely gets me closer. – bart cubrich Mar 06 '19 at 19:59

3 Answers3

1

You don't need to calculate the reflection angle, just decompose the problem in two: one for x and one for y. In both cases, you need the particle to "go back" when it exceeds the boundary.

I've done this time ago for an excercise studying particle density in fluids. The easiest thing is to consider a (0, 1) boundary in both directions. The following code should do it (tip: a proper use of abs will create the equivalent of a reflection):

x0 = [.1, .9]
delta = [-0.2, 0.3]
x1 = [(1-abs(abs(xi + di)-1)) for xi, di in zip(x0, delta)]
print(x1)
# 0.1, 0.8
#or using numpy:
x1 = 1-np.abs(np.abs(np.asarray(x0) + np.asarray(delta))-1)
print(x1)
>> [0.09999999999999998, 0.8]
   array([0.1, 0.8])

I'm assuming from your question that you are neglecting particle-particle collision and particle-particle "non-superposition"

Tarifazo
  • 4,118
  • 1
  • 9
  • 22
  • Yes, I am trying to keep it as simple as possible at first. Friction-less, non-colliding, spheres which start with some random initial velocity and direction, and maintain their direction. Adding collisions and friction could be interesting later, but I really just want to make a visualization that mimics diffusion, but only deals in particle motion. Of course the other effect will make a big difference, but I think the visual will still work. – bart cubrich Mar 06 '19 at 21:27
  • This codes needs something recursive for multiple reflections right? – bart cubrich Mar 06 '19 at 21:53
  • Hrmmm, or I guess you could keep the time step really small so that not very much movement takes place each step. Then you just update the direction the particle is traveling in at each time step, which will change on bounces. – bart cubrich Mar 06 '19 at 22:43
  • Focus on small space "deltas" instead of time steps. If your delta is less than 1 (as it should be), you cannot get more than one reflection. Use something like `np.clip(np.random.normal(mu, sigma), -0.99, 0.99))`. On each step calculate the average position in x and y, and plot it versus number of steps: you should see it moving to (0.5, 0.5). – Tarifazo Mar 07 '19 at 11:51
  • Thanks! That is what I was thinking of. I will probably use even smaller time deltas because you could get some double reflections at the corners, where some of your billiard balls might escape. – bart cubrich Mar 07 '19 at 21:13
1

Here is a simple implementation. I change the movement vectors only every tenth step, that way one can visually check boundary reflections. Particles flash red when the movement vectors are updated.

The trick as described ħere is to "unroll" the bounding box. Instead we let the particles move unconstrained and then fold space into the bounding box.

import numpy as np
import pylab
from matplotlib.animation import FuncAnimation

xy = np.random.uniform(-1, 1, (2, 200))
xy[0, :160] = np.abs(xy[0, :160])
xy[0, 160:] = -np.abs(xy[0, 160:])
xy += 1

f, a = pylab.subplots()
pxy, = pylab.plot(*xy, 'o')

def init():
    a.set_xlim(0, 2)
    a.set_ylim(0, 2)
    return pxy,

def update(frame):
    global inc, xy
    if frame % 1 < 0.01:
        inc = np.random.normal(0, 0.01, xy.shape)
        pxy.set_markerfacecolor('red')
    elif frame % 1 < 0.11:
        pxy.set_markerfacecolor('blue')        
    xy += inc
    fxy = np.abs((xy+2)%4-2)
    pxy.set_data(*fxy)
    return pxy,

anim = FuncAnimation(f, update, frames=np.arange(1200) / 10,
                     init_func=init, blit=True)

pylab.show()
Paul Panzer
  • 51,835
  • 3
  • 54
  • 99
  • This seems to get the main idea very well. What is the idea behind giving the particles random motion every tenth step again? This is exactly the visual I wanted to create, except that I was imagining the particles continuing in their trajectory until they hit a wall. Can I just set the increment to be fixed? – bart cubrich Mar 06 '19 at 21:32
  • 1
    I'm not a physicist, but I think the accepted method is actually to generate a new displacement vector every time step. One way of thinking about it is that there are so many particle collisions that the displacement is essentially random, and the statistics of displacement are a function of temperature. – Paul Panzer Mar 06 '19 at 21:40
  • Thanks for that. his answer is very helpful, and addresses the whole idea that I am looking into, but the whole idea for me with this is to learn about the physics by building the model from scratch. @Mstaino's answer gives me a short usable snippet of code with which I can start to build up the rest of the functionality. But I really appreciate your reply as well, as I will likely use many components of it in the end product. – bart cubrich Mar 07 '19 at 00:29
0

So a couple things to keep in mind:

  1. You need a friction component or else the particle will keep moving forever (conservation of energy). Friction happens as a function of velocity in this case, and friction will also happen on bounces.

  2. If it's just a single particle, you can calculate it by defining bounding boxes like x is between 0 and 5, y is between 0 and 3 for example. Then you can calculate the intercept with a wall by plugging in the x = 5 value and then solving for y in the equation for the line.

For one particle, you don't have to do it parametrically with increments of t_0, you can calculate the intercepts and basically zoom it on over there. For multiple, you would have to calculate inter-molecular diffusion and collision forces...which is a much harder problem that should be done parametrically.

You would have to calculate collisions, which is when the centres of two molecules are 2*radius away from each other, then do a collision that conserves momentum.

Kaiwen Chen
  • 192
  • 1
  • 1
  • 12
  • These consideration are all very good, and I will consider them later, but I just want to create a simple visualization that explains the phenomena of diffusion in an overly simple way, to see if that actually works, since Schrodinger claims that it is this simple in his book. It won't be a good model of what would happen or what timescales are like, but I think it will give the right basic idea as a sort of instructional movie. – bart cubrich Mar 07 '19 at 00:30