算法_气体分子模型_Processing

气体分子小球模型Processing代码运行界面

参考文章:Experiments in statistical mechanics

Main function
float ball_l=80;
int N = 3;
Particle [] ps= new Particle[N];
Bar bar = new Bar (int(ball_l)*5);
float heigh = ball_l*4;
float widt = ball_l*8;
//parameters for statistics
float timeBoxWidth=ball_l*4; //the width of time box
float timeBoxHeight=ball_l*2;
float timeBoxOriginX=ball_l*8; //leftupper corner x of time box
float timeBoxOriginY=ball_l*0; //leftupper corner y of time box
int counter = 0; //time step counter
float [] ts = {}; //time steps
float [] ys = {}; //bar locations
float histBoxWidth = ball_l*4; //the width of histogram box
float histBoxHeight = ball_l*2; //the height of histogram box
float histBoxOriginX=ball_l*8; //leftupper corner x of hist box
float histBoxOriginY=ball_l*2; //leftupper corner y of hist box
 
void setup() {
  size(int(ball_l)*12,int(ball_l)*4);
  /*
  for (int i=0; i<ps.length; i++){
    ps[i] = new Particle(new PVector(random(width),random(height)),ball_l/2);
  }
  */
  ps[0] = new Particle(new PVector(ball_l*1.5,ball_l*1.5),ball_l/2);
  ps[1] = new Particle(new PVector(ball_l*6.5,ball_l*3.5),ball_l/2);
  ps[2] = new Particle(new PVector(ball_l*7.5,ball_l*0.5),ball_l/2);
  //ps[3] = new Particle(new PVector(ball_l*7.5,ball_l*1.5),ball_l/2);
}
void draw() {
  background(240);
  counter+=1;
  
  //plot lattice
  for (int x=0; x<=8; x++){
    line(x*ball_l,0,x*ball_l,heigh);
  }
  for (int y=0; y<4; y++){
    line(0,y*ball_l,widt,y*ball_l);
  }
  
  //display particles
  for (Particle p: ps){
    p.run();
  }
  
  //display bar
  bar.run();
  
  //collision between particles
  for (int i=0; i<ps.length; i++){
    for (int j=i+1; j<N; j++){
      PVector dl = PVector.sub(ps[j].location, ps[i].location);
      float dis = dl.mag();
      if (dis < (ps[i].r+ps[j].r)){
        //balls have contact so push back 
        //https://channel9.msdn.com/Series/Sketchbooktutorial/Simple-Collision-Detection-and-Response
        PVector normal = PVector.div(dl,dis);
        PVector midpoint = PVector.div(PVector.add(ps[i].location, ps[j].location),2);
        ps[i].location = PVector.sub(midpoint,PVector.mult(normal,ps[i].r));
        ps[j].location = PVector.add(midpoint,PVector.mult(normal,ps[j].r));
        float scale = PVector.sub(ps[i].velocity, ps[j].velocity).dot(normal);
        PVector dv = PVector.mult(normal,scale);
        ps[i].velocity.sub(dv);
        ps[j].velocity.add(dv);
      }
    }
  }
  
  // collision between particles and the bar
  for (int i=0; i<ps.length; i++){
    float dx = bar.x - ps[i].location.x;
    if (abs(dx) < ps[i].r){
      //print (dx+"___");
      //contact so push back
      float normalX;
      if (dx > 0){normalX = 1;}
      else {normalX=-1;}
      float midpointX = (ps[i].location.x+ps[i].r*normalX+bar.x)/2;
      ps[i].location.x = midpointX - normalX*ps[i].r;
      bar.x = midpointX;
      float dvx = ps[i].velocity.x - bar.velocity;
      ps[i].velocity.x -= dvx;
      bar.velocity  += dvx;
    }  
  }
  
  //calculate total energy
  float E=0;
  for (int i=0; i<ps.length; i++){
    E+=sq(ps[i].velocity.mag());
  }
  E+=sq(bar.velocity);
  //print (E+"_____");
  
  
  
  //-------------------time box-------------------
  fill(255);
  rect(timeBoxOriginX,timeBoxOriginY,timeBoxWidth,timeBoxHeight);
  fill(100);
  text("Time = "+counter,timeBoxOriginX+timeBoxWidth-80,timeBoxOriginY+timeBoxHeight-10);//print counter
  text("Bar location",timeBoxOriginX+10,timeBoxOriginY+20);
  //add a new data point
  ts=(float[]) append(ts,counter);
  ys=(float[]) append(ys,bar.x);
  //obtain rescaled xs and ts
  float [] rts = new float[ts.length];
  float [] rys = new float[ys.length];
  for (int i=0; i<ts.length; i++){
    rts[i]=timeBoxOriginX+timeBoxWidth*ts[i]/( max(ts)+1);
    rys[i]=timeBoxOriginY+timeBoxHeight*(1-ys[i]/( max(ys)+1));// change y direction
  }
  //draw lines connecting time points 
  if (rts.length>1){
    for (int i=0;i<rts.length-1; i++){
      float x1=rts[i];
      float x2=rts[i+1];
      float y1=rys[i];
      float y2=rys[i+1];
      strokeWeight(0.5);
      fill(100,100);
      line(x1,y1,x2,y2);
      //point(x1,y1);
      fill(200);
    }
  }
  
  
  //-------------------histogram-------------------
  fill(255);
  rect(histBoxOriginX,histBoxOriginY,histBoxWidth,histBoxHeight);
  fill(100);
  text("Bar location distribution",histBoxOriginX+10,histBoxOriginY+20);
  int Nbars = 20;
  int [] histData = new int[Nbars];
  float bin = histBoxWidth/Nbars;
  for (int i=0;i<ys.length; i++){
    int n = int(Nbars*(ys[i]-min(ys))/( (max(ys)-min(ys))+0.001)); //the ith element belongs to the nth bin
    histData[n]+=1;
  }
  for (int i=0;i<Nbars;i++){
    float h = histBoxHeight*histData[i]/float(ys.length);
    rect(histBoxOriginX+i*bin,histBoxOriginY+histBoxHeight-h,bin,h);
  }
Particle Class
class Particle {
  
  PVector location;
  PVector velocity;
  //PVector acceleration;
  float mass;
  float r;
 
  Particle(PVector l, float radius) {
    mass = 1;
    //acceleration = new PVector(0,0);
    velocity = new PVector(5,5);
    location = l.get();
    r = radius;
  }
 
  void run() {
    update();
    display();
    checkEdges();
  }
 
  void update() {
    //velocity.add(acceleration);
    location.add(velocity);
  }
 
  void display() {
    stroke(0);
    fill(175);
    ellipse(location.x,location.y,r*2,r*2);
  }
  
    void checkEdges() {
      if (location.x < r){
        location.x = r;
        velocity.x *= -1;
      }
      if (location.x > widt-r){
        location.x = widt-r;
        velocity.x *= -1;
      }      
      if (location.y < r){
        location.y = r;
        velocity.y *= -1;
      }
      if (location.y > heigh-r){
        location.y = heigh-r;
        velocity.y *= -1;
      }
  }
}
Bar class
class Bar {
  
  float x;
  float velocity;
  //float acceleration;
  float mass;
 
  Bar(float l_) {
    mass = 1;
    //acceleration = 0;
    velocity = 0;
    x = l_;
  }
 
  void run() {
    update();
    display();
    checkEdges();
  }
 
  void update() {
    //velocity+=acceleration;
    x+=velocity;
  }
 
  void display() {
    stroke(0);
    fill(100);
    strokeWeight(2);
    line(x,0,x,heigh);
    strokeWeight(1);
  }
  
  void checkEdges() {
    if (x < 0){
      x = 0;
      velocity *= -1;
    }
    if (x > widt){
      x = widt;
      velocity *= -1;
    }
  }
  
}



}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,458评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,454评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,171评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,062评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,440评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,661评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,906评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,609评论 0 200
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,379评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,600评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,085评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,409评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,072评论 3 237
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,088评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,860评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,704评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,608评论 2 270

推荐阅读更多精彩内容