[Processing] 기체분자의 확산(1)

과학이야기/물리학 2013. 4. 2. 17:22

Processing Simulation : 기체분자의 확산(1)



브라우져에 따라 다른 시뮬레이션이 보이기도 하고 보이지 않기도 합니다.

테스트결과 시뮬레이션 결과가 크롬에서는 잘 보이는데 익스플로러 8에서는 잘 안보이네요. 스크립트 오류가 나옵니다. 익스플로러 10에서는 잘 보이는지 모르겠습니다.

익스플로러 말고 크롬에서 보시기 바랍니다.


크롬 다운받기 : https://www.google.com/intl/ko/chrome/browser/


이 시뮬레이션은 Processing을 이용하여 기체분자의 확산현상을 관찰해본 것입니다.


Processing 다운로드 받기 : http://processing.org/


[컨트롤기능 추가] 시뮬레이션 화면을 마우스로 클릭하시면 시뮬레이션을 다시시작합니다.



왼쪽에 몰려 있던 10,000개의 기체분자들이 기체가 들어있지 않던 오른쪽으로 확산하는 모습을 시뮬레이션해 봤습니다. 


[시뮬레이션 기본 가정]

1. 기체분자는 벽과 완전탄성충돌한다.(즉, 충돌했을 때 운동방향만 바뀌고, 속력은 변하지 않는다.)

2. 기체분자 자체의 충돌은 무시(충돌이 일어날 경우는 다음에 다시 시뮬레이션을 해 보도록 하겠습니다.)

3. 기체의 속력은 균일하다. - 실제로는 기체분자의 속력이 제각각 다르지만 이 시뮬레이션에서는 같다고 가정하고 진행했습니다.

4. 기체의 처음 운동방향은 각각 다르다. - 시뮬레이션 초기단계에서 각 기체의 운동방향을 랜덤하게 잡았습니다.


[시뮬레이션 결과]

확산 초기 - 확산이 시작되면서 많은 수의 분자들이 오른쪽으로 이동하는 것을 확인할 수 있었습니다. 또한 왼쪽으로 이동하던 분자들도 벽과 충돌하여 많은 분자들이 오른쪽으로 이동하였습니다.



분자들의 이동상황을 텍스트파일로 저장하여 엑셀에서 그래프를 그려본 결과는 다음과 같습니다.




그래프에서 볼 수 있는 것과 같이 왼쪽에 있던 분자들이 오른쪽으로 이동하면서 감쇠진동과 같은 형태를 이루면서 분자의 수가 변하는 것을 확인할 수 있었습니다. 데이터는 좀 더 분석을 해봐야 할 것 같습니다.


----------------------------------------------------------------

2014.03.25일 추가 : 이 포스트에서 사용한 시뮬레이션 소스는 아래와 같습니다. 복사하셔서 프로세싱에 넣고 실행하시면 시뮬레이션 모습을 보실 수 있습니다.


int rad=1;

int num = 10000;


float[] xpos = new float[num];

float[] ypos = new float[num];


float xspeed = 1;

float yspeed = 1;


float[] xdirection = new float[num];

float[] ydirection = new float[num];


float[] unitDirectionMagnitude = new float[num];


PrintWriter output;


void setup(){

  size(540, 360);

  noStroke();

  frameRate(30);


  background(0);

  rectMode(CORNER);

  fill(105);

  rect(0, 0, 430/2, height);


  for(int i=0; i < num; i++) {

    xpos[i] = random(0, 430/2);

    ypos[i] = random(0, height);

    xdirection[i] = random(-1, 1);

    ydirection[i] = random(-1, 1);

    unitDirectionMagnitude[i] = sqrt((xdirection[i]*xdirection[i] + ydirection[i]*ydirection[i]));

    ellipse(xpos[i], ypos[i], rad, rad);

  }

}


void draw(){

  int leftCount, rightCount;

  if (mousePressed && (mouseButton == LEFT)) {

    update();

  }

  background(0);

  rectMode(CORNER);

  fill(105);

  rect(0, 0, 430/2, height);

  

  leftCount = 0;

  rightCount = 0;

  

  for (int i=0; i < num; i++) {

    xpos[i] = xpos[i] + (xspeed * xdirection[i]/unitDirectionMagnitude[i]);

    ypos[i] = ypos[i] + (yspeed * ydirection[i]/unitDirectionMagnitude[i]);

    

    if (xpos[i] > 430 - rad || xpos[i] < rad) {

      xdirection[i] *= -1;

    }

    

    if ((ypos[i] > height - rad) || (ypos[i] < rad)) {

      ydirection[i] *= -1;

    }

    

    ellipseMode(RADIUS);

    fill(255);

    ellipse(xpos[i], ypos[i], rad, rad);

    

  }

    for (int i = 0; i < num; i++) {

      if (xpos[i] < 430/2) {

        leftCount += 1;

      }

    }

    rightCount = num - leftCount;

    stroke(255);

    rect(680, 20, 50, 150);

    rect(740, 20, 50, 150);

    

    noStroke();

    textSize(12);

    fill(105);

    rect(459, 20+(150-(150*leftCount/num)), 30, 150*leftCount/num);

    text("Left", 459, 190);

    fill(200);

    rect(500, 20+(150-(150*rightCount/num)), 30, 150*rightCount/num);

    text("Right", 500, 190);

    //output.print(leftCount);

    //output.print(",");

    //output.println(rightCount);

}


void update() {

    for(int i=0; i < num; i++) {

    xpos[i] = random(0, 430/2);

    ypos[i] = random(0, height);

    xdirection[i] = random(-1, 1);

    ydirection[i] = random(-1, 1);

    unitDirectionMagnitude[i] = sqrt((xdirection[i]*xdirection[i] + ydirection[i]*ydirection[i]));

    ellipse(xpos[i], ypos[i], rad, rad);

  }

}


[새길]


[이 글이 마음에 드시면 아래 손가락을 한번 꾹 눌러 주세요...^_^]


설정

트랙백

댓글