粒子法

9月21日(金) 流体シミュレータ計算部分の作成

今週からようやく粒子法の計算を行う部分を実装していきます。計算部分は半陰的に解かず、陽的に解いて粒子が近づきすぎたときは、剛体としてはじきとばすという荒技を行いました。それでもなんかそれっぽいのができたので、体調もあまりよくないので今週はここまでで来週以降半陰的な部分を実装していこうと思います。


public void calc(){
    for(int i = 0; i < pNum; i++){
        //壁は計算しない
        if(element[i].q != 4 element[i].q != 2)continue;
        element[i].vx += deltat * grav;
        element[i].x += deltat * element[i].vx;
        element[i].y += deltat * element[i].vy;
    }

    double r2lim = parcSize * parcSize * minlen * minlen;
    //粒子が近づきすぎたとき剛体的にはじき返す
}

今後の課題

  • 粒子が完全に重なったときは粒子を生成しないように設定したい。
  • 半陰的に解いて物性値を考慮する。
  • 画面から消えた粒子は計算しない。

今週のミーティングにて、粒子の生成方法についてだめだしが多かったので、粒子を一つずつ生成する方法と、ペイントソフトで矩形を描くときみたいにして粒子を生成させることができるようにしたい。来週は実家に帰予定なので、実家でゆっくり実装していきたいと思う。やっぱり粘性に関する項はしっかり解かなくては水っぽくならないとわかったので、バグ取りを早めにやりたいと思う。

9月13日(金) 流体シミュレータのはりぼて作り

今週はソフトウェアの外観部分を作成しました。とりあえずシミュレーションを行いたい状況を絵を描くように作るところまでです(あまり進んでない…)。
[expand title=”Trigger Text”]
統合開発環境であるNetBeansでまずは張りぼて作りです。NetBeansではソフトウェアの外観をマウス操作のみ(ドラッグ&ドロップ)で作成することができます。中央にラベルを配置し、左下に生成させる粒子のボタン、右下にアニメーションの開始ボタンと停止ボタンを作りました。とりあえず機能はこれぐらいにしておきます。張りぼてはこれで完成です。これだけでは実行してもボタンしか表示されないので、マウス操作や、ボタンを押したときの操作を記述していきます。

haribote

プログラムは以下のようになりました。


import javax.swing.JPanel;
import java.awt.BorderLayout;

public class MainFrame extends javax.swing.JFrame {

    public MainFrame() {

        initComponents();
        GraphicComponent gc = new GraphicComponent();
        lbl.setLayout(new BorderLayout());
        lbl.add(gc);
        pack();
    }
    //JPanelクラスを継承した内部クラス(描画)
    class GraphicComponent extends JPanel {
        @Override
        public void paintComponent(Graphics g) {
            Graphics2D g2 = (Graphics2D) g;
            g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                      RenderingHints.VALUE_ANTIALIAS_ON);
            g.setColor(Color.WHITE);
            g.fillRect(0, 0, getWidth(), getHeight());//背景を白く塗りつぶす

            for(int i = 0; i < pNum ; i++){
                if(!wallSt&&!waterSt&&!jellySt&&!inWallSt)break;
                if(element[i].q == 0)g.setColor(Color.blue);//条件に応じて粒子を描画
                else if(element[i].q == 1)g.setColor(Color.green);
                else if(element[i].q == 2)g.setColor(Color.yellow);
                else if(element[i].q == 3)g.setColor(Color.black);
                g.fillOval((int)element[i].x*10, (int)element[i].y*10, 10, 10);
                g.setColor(Color.black);//粒子の輪郭を描画
                g.drawOval((int)element[i].x*10, (int)element[i].y*10, 10, 10);
            }
        }
    }
    //水ボタンが押された時の処理
    private void btnWtActionPerformed(java.awt.event.ActionEvent evt) {
        waterSt = true;
        wallSt = false;
        inWallSt = false;
        jellySt = false;
    }
    //壁ボタンが押された時の処理
    private void btnWlActionPerformed(java.awt.event.ActionEvent evt) {
        waterSt = false;
        wallSt = true;
        inWallSt = false;
        jellySt = false;
    }
    //ゼリーボタンが押された時の処理
    private void btnGlActionPerformed(java.awt.event.ActionEvent evt) {
        waterSt = false;
        wallSt = false;
        inWallSt = false;
        jellySt = true;
    }
    //マウスをドラッグした時
    public int drawX;//X座標
    public int drawY;//Y座標
    public static int pNum = 0;//粒子の数
    int bfx, bfy;
    private void lblMouseDragged(java.awt.event.MouseEvent evt) {

        Point point = evt.getPoint();//マウスの座標を取得
        drawX = (Integer) (point.x/10);
        drawY = (Integer) (point.y/10);

        if(drawX!=bfx || drawY!=bfy) {
            if(waterSt)element[pNum++] = new kouzou(drawX, drawY, 0, 0);//水粒子を生成
            else if(wallSt)element[pNum++] = new kouzou(drawX, drawY, 1, 0);
            else if(jellySt)element[pNum++] = new kouzou(drawX, drawY, 2, 0);
            else if(inWallSt)element[pNum++] = new kouzou(drawX, drawY, 3, 0);
        repaint();//再描画
        }
        bfx = drawX;
        bfy = drawY;
    }
    public static void main(String args[]) {
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new MainFrame().setVisible(true);
           }
       });
    }
}

ここまででで粒子法のシミュレーションを行う前段階として、練習問題の状況に合わせて粒子を自由に生成できるようになりました。粒子法(MPS法)では、だいたい粒子自身の直径の2倍程度の範囲にある粒子と相互に作用しあうので、壁は三重にする必要があります。おそらくこのままシミュレーションをスタートさせると計算が安定せずに爆発を起こしそうなので、いろいろ調節が必要だと思います。これから計算部分を実装していく予定です。

haribote2

[/expand]

9月6日(金) 流体シミュレータの構想

arkoakの活動の一環としてCAIソフトウェアの開発を現在行っています。CAIソフトウェアとは、Computer Aided Instructionのことで、学校教育の支援を行うためのソフトウェアのことです。大学で行われている講義の問題点を挙げ、その問題点を解決することを目標としたソフトウェアを提案しました。
[expand title=”Trigger Text”]
私の場合は流体工学の講義で、練習問題を解く際に問題に示されている状況をイメージすることが難しいと感じた経験から、問題に応じてその状況の簡易的なシミュレーションが可能なできるだけ汎用性の高いソフトウェアを作ることを考えています。問題に応じた状況を絵で描いて作り、STARTボタンを押すとリアルタイムにシミュレーション結果をアニメーションで表示します。流体のシミュレーションには粒子法と呼ばれるメッシュレスな手法を用いるつもりです。有限要素法と比較したとき計算量が少なくなることが知られています。今月末に完成させることを目標に開発を進めていくつもりです。

ソフト外観書き方よくわからないけど一応シーケンス図。ちなみに開発言語はJavaで、NetBeansという統合開発環境を使って開発を進めていきます。GraphicComponentクラスが描画用のクラスでJPanelクラスを継承しています。AnimeクラスがThreadクラスを継承したクラスで、オーバーライドしたrun()メソッドの中に制御する処理を記述していきます。MainFrameクラスでそれぞれのクラスをインスタンス化します。イベントを処理するためのクラスとします。sdg

[/expand]

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>