PythonでDLAを描く(1)
DLAって何ぞや??
DLAとは、ブラウン運動する粒子が核にくっついていくことでできていく枝分かれした結晶のことです。
拡散律速凝集(Diffusion Limited Aggregation)の略です。DNAじゃないよ。
DLAができる現象はいくつかあるのですが、詳しくは拡散律速凝集 - Wikipediaで。
前に一度、C言語でDLAのプログラムを書こうとしたのですが、そのときは挫折してしまいました。
今回はそのリベンジを兼ねてPythonで作っていきます。何回かにわけて記事にしようと思います。
基本的なルール
- 場の中心に核(seed)となる粒子が置かれる。
- 他の粒子は場の境界線に置かれ、ランダムウォークをする。
- 粒子が核に触れると核とくっつき、その粒子も核となる。
- 核が場の境界に達すると終了する。
今日やること
今日は細部まで作りこむ前に、粒子がランダムウォークをして核にくっつくという部分を作りたいと思います。
長めになるのでSpyderを使用しました。
import random import numpy as np import matplotlib.pyplot as plt class Diffusion(): def __init__(self): self.seed = [[0,0]] def randomwalk(self,x,y): a = random.choice([[1,0],[-1,0],[0,1],[0,-1]]) return x+a[0],y+a[1] def contact(self,x,y): for i,j in self.seed: if (x-i==0 and abs(y-j)==1) or (abs(x-i)==1 and y-j==0): self.seed.append([x,y]) return False return True def ini_posi(self): ini = [[i,j] for i in range(-10,11) for j in range(-10,11) if abs(i)+abs(j) == 15] return random.choice(ini) def out_range(self,x,y): out_posi = [[i,j] for i in range(-20,21) for j in range(-20,21) if abs(i)+abs(j) == 30] for i,j in out_posi: if x==i and y==j: return False return True def diffusion(self): start = self.ini_posi() x,y = self.randomwalk(start[0],start[1]) flag = True while flag: x,y = self.randomwalk(x,y) flag = self.contact(x,y) flag = self.out_range(x,y) if abs(x)+abs(y)>15: flag = False print(self.seed) d = Diffusion() flag = True while flag: d.diffusion() if len(d.seed)>10: break plt.plot(*np.array(d.seed).T,"o") plt.savefig("DLA_test.png", bbox_inches="tight", pad_inches=0.0)
計算時間短縮のため、粒子を核の近くから発射するようにしています。
また粒子が核から離れすぎるとループを終了して、新しく粒子を発射しなおすようにもしています。
で、できたのがこちらです。
範囲を狭くしているのでまだまだ枝は細かくないですね。
次回はもっと範囲を大きくするために、粒子の発射位置を更新するプログラムを加えていきたいと思います。
6/23追記
後から気づいたのですが、このプログラム致命的なミスがあります。
どこだかわかりますか?
woodhero2357.hatenablog.com