HOME > natural science Laboratory > コンピュータ・シミュレーション講座 > 仮想物理実験室

雪の結晶シミュレーション(2次元DLA)

文責:遠藤 理平 (2016年5月12日) カテゴリ:仮想物理実験室(247)

【アルゴリズム】水分子(水色)の運動をランダムウォークとみなしランダムな位置からスタートさせます。 中心部分にある核(赤)に接触すると、水分子は吸着して固まります。 固まった後は、核と同様に水分子を吸着していく。 その結果、数珠繋ぎに成長していくことになります。

本シミュレーションは拡散律則凝集と呼ばれ、結晶成長の単純なモデルとして考えられています。
参考:DLAによる樹木状クラスタのシミュレーションDLAによる樹木状クラスタのフラクタル次元

20160512.png

実際のシミュレーションはこちらをご覧ください。

プログラムソース(HTML5, JavaScript)

//////////////////////////////////////////////
// 雪の結晶シミュレーション
//////////////////////////////////////////////
//DLAクラス
var DLA2D = function () {

	//粒子数
	this.N = 20000;
	//初期位置の最小値
	this.L0 = 100;
	//初期位置の最大値
	this.Lmax = 500;

	//内部プロパティ
	this.perticles = [];         //粒子情報が格納される配列
	this.fixPerticleIndex = [];  //吸着された粒子インデックスが格納される配列
	this.maxLengthSq = 1;        //原点からの最大距離の2乗

	//形状オブジェクトの宣言と生成
	this.geometry = new THREE.PlaneGeometry(1, 1);
	//材質オブジェクトの宣言と生成
	this.material = new THREE.MeshBasicMaterial( {color:0x0000FF} );		
	//材質オブジェクトの宣言と生成
	this.fixedMaterial = new THREE.MeshBasicMaterial( {color:0xFF0000} );		

	//初期化
	this.init = function() {

		//分布密度関数の係数
		var A =  2 / ( this.L0*this.L0 + this.Lmax*this.Lmax );

		for( var i = 0; i <= 100; i++ ) this.fixPerticleIndex[ i ] = [ ];

		for( var n = 0; n < this.N; n++ ){

			//積分分布密度
			var F = Math.random();

			//積分分布密度から得られる距離
			var L = Math.sqrt( this.L0*this.L0 + 2 * F / A );

			//偏角
			var theta =  2 * Math.PI * Math.random();

			var x = L * Math.cos( theta ) ;
			var y = L * Math.sin( theta ) ;

			x = Math.round(x);
			y = Math.round(y);

			//平面オブジェクトの生成
			this.perticles[n] = new THREE.Mesh( this.geometry, this.material );

			//初期値を指定
			this.perticles[n].position.set( x, y, 0 );

			//平面オブジェクトのシーンへの追加
			scene.add( this.perticles[n] );

			//固定フラグ
			this.perticles[n].fixed = false;

		}

		//核を設定
		this.perticles[0].position.set( 0, 0, 0 );
		this.perticles[0].fixed = true;
		this.fixPerticleIndex[ 0 ].push( 0 );

		//描画色を変更
		this.perticles[0].material = this.fixedMaterial;;
		this.perticles[0].needsUpdate = true;
	}

	//時間発展
	this.timeEvolution = function() {

		var x, y, r, lengthSq;

		return function() {
			for( var i = 0; i < this.N; i++ ){

				if( this.perticles[i].fixed ) continue;

				x = this.perticles[i].position.x;
				y = this.perticles[i].position.y;

				r = Math.random();
				if( r < 0.25 )  x += 1.0;
				else if( r < 0.50 )  x -= 1.0;
				else if( r< 0.75 )  y += 1.0;
				else y -= 1.0;

				this.perticles[i].position.x = x;
				this.perticles[i].position.y = y;

				lengthSq = x*x + y*y;

				//吸着テスト
				if( lengthSq <= this.maxLengthSq ) this.checkCollision( i , lengthSq);
			}
		}
	}();

	//吸着テスト
	this.checkCollision = function ( n, lengthSq ){

		var v = new THREE.Vector3();
		var lengthIndex, M, index;
		var i, j;

		return function( n, lengthSq ){

			//距離配列要素番号
			lengthIndex = Math.floor( Math.sqrt( lengthSq ) );

			for( j = lengthIndex - 1; j <= lengthIndex + 1; j++ ){

				if( j < 0 ) continue;

				M = this.fixPerticleIndex[ j ].length;

				for( i = 0; i < M ; i++ ){

					index = this.fixPerticleIndex[ j ][ i ];

					lengthSq = v.copy( this.perticles[ n ].position ).sub( this.perticles[ index ].position ).lengthSq();

					if( lengthSq <= 1.0 ) {

						this.perticles[n].fixed = true;
						this.fixPerticleIndex[ lengthIndex ].push( n );

						//描画色を変更
						this.perticles[n].material = this.fixedMaterial;
						this.perticles[n].needsUpdate = true;

						//最大半径の更新
						if( this.perticles[ n ].position.lengthSq() >= this.maxLengthSq ) {
							this.maxLengthSq = Math.pow( this.perticles[ n ].position.length() + 1, 2);
							//console.log( this.maxLengthSq );
						}

						return;
					}
				}
			}

		}

	}();

}


タグ: ,

▲このページのトップNPO法人 natural science トップ

関連記事

仮想物理実験室







▲このページのトップNPO法人 natural science トップ