反応拡散系

提供:kuhalaboWiki
(版間での差分)
移動: 案内, 検索
(Gray-Scott Reaction and Diffusion(反応拡散系)モデル)
(初期状態の発生箇所をウィンドウ全体内でランダムにする)
 
(1人の利用者による、間の11版が非表示)
1行: 1行:
 
== Gray-Scott Reaction and Diffusion(反応拡散系)モデル ==
 
== Gray-Scott Reaction and Diffusion(反応拡散系)モデル ==
  
 +
;参照資料
 +
* [https://www.karlsims.com/rd.html Reaction-Diffusion Tutorial]
 +
* [https://mrob.com/pub/comp/xmorphia/ogl/index.html WebGL Gray-Scott Explorer]
 +
* http://pmneila.github.io/jsexp/grayscott/
 +
* [https://www.t-kougei.ac.jp/activity/extension/festa2020/ 芸術学部フェスタ2020] [https://youtu.be/jZLIpPs4zYw 「反応と拡散」] / [https://www.youtube.com/watch?v=cGF8EZ2W5mA Inspiration Creation]
 +
 +
;github
 +
* https://github.com/MStrandh/gray_scott_reaction_diffusion
 +
* https://github.com/Nekodigi/Reaction-Diffusion-Algorithm
 +
 +
 +
===概要===
 
物質は空間内で濃度の濃いところから薄いところへ拡散し、最終的に均一になります。
 
物質は空間内で濃度の濃いところから薄いところへ拡散し、最終的に均一になります。
 
2つの物質が反応しながら拡散するとき、物質の濃淡の波ができ、生物に見られる多種多様な模様が生成されます。
 
2つの物質が反応しながら拡散するとき、物質の濃淡の波ができ、生物に見られる多種多様な模様が生成されます。
24行: 36行:
  
 
[[ファイル:Rd-grid-cells.png]]
 
[[ファイル:Rd-grid-cells.png]]
 
 
;参照資料
 
* [https://www.karlsims.com/rd.html Reaction-Diffusion Tutorial]
 
* [https://mrob.com/pub/comp/xmorphia/ogl/index.html WebGL Gray-Scott Explorer]
 
 
;シミュレーション
 
* http://pmneila.github.io/jsexp/grayscott/
 
 
;ソース
 
* https://github.com/MStrandh/gray_scott_reaction_diffusion
 
* https://github.com/Nekodigi/Reaction-Diffusion-Algorithm
 
 
;[https://www.t-kougei.ac.jp/activity/extension/festa2020/ 芸術学部フェスタ2020]
 
* [https://youtu.be/jZLIpPs4zYw 「反応と拡散」]
 
  
 
=== ソース例 ===
 
=== ソース例 ===
 
<pre>
 
<pre>
int M = 640;
+
int M = 400;
int N = 480;
+
int N = 400;
  
 
//System parameters
 
//System parameters
double diffU;
+
double diffU; // U(A) diffuse rate
double diffV;
+
double diffV; // V(B) diffuse rate
double paramF;
+
double paramF; // Feed rate
double paramK;
+
double paramK; // Kill rate
  
 
boolean rndInitCondition;
 
boolean rndInitCondition;
90行: 87行:
 
void setup() {
 
void setup() {
 
   frameRate(48);
 
   frameRate(48);
  smooth();
+
//  smooth(); Processing 4以降ではエラーになる
 
   colorMode(HSB,1.0);
 
   colorMode(HSB,1.0);
 
    
 
    
96行: 93行:
 
   diffU = 0.16;
 
   diffU = 0.16;
 
   diffV = 0.08;
 
   diffV = 0.08;
   paramF = 0.035;
+
   paramF = 0.0545;
   paramK = 0.06;
+
   paramK = 0.062;
 
    
 
    
 
   rndInitCondition = true;
 
   rndInitCondition = true;
105行: 102行:
 
}
 
}
  
void timestep(double F, double K, double diffU, double diffV) {
+
void timestep() {
 
       for (int i = 0; i < M; i++) {
 
       for (int i = 0; i < M; i++) {
 
         for (int j = 0; j < N; j++) {
 
         for (int j = 0; j < N; j++) {
          int p = i + j*N;
+
//          int p = i + j*N;
 
            
 
            
 
           double u = U[i][j];
 
           double u = U[i][j];
122行: 119行:
 
           double lapV = (V[left][j] + V[right][j] + V[i][up] + V[i][down] - 4*v);
 
           double lapV = (V[left][j] + V[right][j] + V[i][up] + V[i][down] - 4*v);
 
            
 
            
           dU[i][j] = diffU*lapU  - uvv + F*(1 - u);
+
           dU[i][j] = diffU*lapU  - uvv + paramF*(1 - u);
           dV[i][j] = diffV*lapV + uvv - (K+F)*v;
+
           dV[i][j] = diffV*lapV + uvv - (paramK+paramF)*v;
 
         }
 
         }
 
       }
 
       }
135行: 132行:
  
 
void draw(){  
 
void draw(){  
     for (int k = 0; k < 10; k++) {
+
     for (int i = 0; i < 20; i++) {
       timestep(paramF, paramK, diffU, diffV);
+
       timestep();
 
     }
 
     }
 
    
 
    
212行: 209行:
 
}
 
}
 
</pre>
 
</pre>
 +
 +
=== 初期状態の発生箇所をウィンドウ全体内でランダムにする ===
 +
<pre>
 +
void generateInitialState() {
 +
    for (int i = 0; i < M; i++) {
 +
      for (int j = 0; j < N; j++) {
 +
        U[i][j] = 1.0;
 +
        V[i][j] = 0.0;
 +
      }
 +
    }
 +
   
 +
    if (rndInitCondition) {
 +
        for (int i = 0; i < M; i++) {
 +
            for (int j = 0; j < N; j++) {   
 +
              U[i][j] = 0.5*(1 + random(-1, 1));
 +
              V[i][j] = 0.25*( 1 + random(-1, 1));
 +
          }
 +
        }
 +
    } else {
 +
      for (int i = 0; i < M; i++) {
 +
            for (int j = 0; j < N; j++) {   
 +
              U[i][j] = 0.5;
 +
              V[i][j] = 0.25;
 +
          }
 +
        }
 +
    }
 +
}
 +
</pre>
 +
 +
=== 模様の発生場所を特定の矩形内に限定する ===
 +
*発生領域
 +
**X軸:M1からM2
 +
**Y軸:N1からN2
 +
 +
<pre>
 +
int M1 = 200;
 +
int N1 = 300;
 +
int M2 = 600;
 +
int N2 = 500;
 +
</pre>
 +
 +
<pre>
 +
void timestep() {
 +
      for (int i = M1; i < M2; i++) {
 +
        for (int j = N1; j < N2; j++) {
 +
//          int p = i + j*N;
 +
         
 +
          double u = U[i][j];
 +
          double v = V[i][j];
 +
          double uvv = u*v*v;
 +
         
 +
          int left = (i-1+M2) % M2;
 +
          int right = (i+1) % M2;
 +
          int up = (j-1+N2) % N2;
 +
          int down = (j+1) % N2;
 +
     
 +
          double lapU = (U[left][j] + U[right][j] + U[i][up] + U[i][down] - 4*u);
 +
          double lapV = (V[left][j] + V[right][j] + V[i][up] + V[i][down] - 4*v);
 +
         
 +
          dU[i][j] = diffU*lapU  - uvv + paramF*(1 - u);
 +
          dV[i][j] = diffV*lapV + uvv - (paramK+paramF)*v;
 +
        }
 +
      }
 +
    for (int i= 0; i < M; i++) {
 +
      for (int j = 0; j < N; j++){
 +
          U[i][j] += dU[i][j];
 +
          V[i][j] += dV[i][j];
 +
      }
 +
    }
 +
}
 +
</pre>
 +
 +
== 人工生命(ALife) ==
 +
 +
[[セルオートマトン]]
 +
 +
[[ラングトンのアリ]]
 +
 +
[[レイノルズのボイド]]
 +
 +
[[フラクタル]]
  
 
== 参考 ==
 
== 参考 ==

2024年12月4日 (水) 05:45時点における最新版

目次

[編集] Gray-Scott Reaction and Diffusion(反応拡散系)モデル

参照資料
github


[編集] 概要

物質は空間内で濃度の濃いところから薄いところへ拡散し、最終的に均一になります。 2つの物質が反応しながら拡散するとき、物質の濃淡の波ができ、生物に見られる多種多様な模様が生成されます。 これはチューリングパターンとして知られていて、シマウマの縞模様やヒョウの斑模様などがよい例です。

反応と拡散のアルゴリズム
  • 物質A:一定の割合で発生する(Feed)
  • 物質B:一定の割合で消滅する(Kill)
  • 1つのAと2つのBとが反応するとAがBに変化する。

Rd-reaction.png

反応拡散方程式
  • 2つの物質AとBが反応しながら、空間に拡散していく様子を反応拡散方程式で表わす。
  • Laplacian(ラプラシアン) = (上下左右の4方向から流入する量) - (4方向に流出する量)

Rd-diffusion.png Rd-equation.png

描画
  • 物質A,Bの濃淡を模様として描画する。
  • 物質Aの発生率と物質Bの消滅率を微妙に変化させるだけで、現れる模様は大きく変化する。

Rd-grid-cells.png

[編集] ソース例

int M = 400;
int N = 400;

//System parameters
double diffU; // U(A) diffuse rate
double diffV; // V(B) diffuse rate
double paramF; // Feed rate
double paramK; // Kill rate

boolean rndInitCondition;

double[][] U = new double[M][N];
double[][] V = new double[M][N];

double[][] dU = new double[M][N];
double[][] dV = new double[M][N];

void settings() {
  size(M,N);
}

void generateInitialState() {
    for (int i = 0; i < M; i++) {
      for (int j = 0; j < N; j++) { 
        U[i][j] = 1.0;
        V[i][j] = 0.0;
      }
    }
    
    if (rndInitCondition) {
        for (int i = M/3; i < 2*M/3; i++) {
            for (int j = N/3; j < 2*N/3; j++) {     
               U[i][j] = 0.5*(1 + random(-1, 1));
               V[i][j] = 0.25*( 1 + random(-1, 1));
          }
        }
    } else {
      for (int i = M/3; i < 2*M/3; i++) {
            for (int j = N/3; j < 2*N/3; j++) {     
               U[i][j] = 0.5;
               V[i][j] = 0.25;
          }
        }
    }
}

void setup() {
   frameRate(48);
//   smooth();  Processing 4以降ではエラーになる
   colorMode(HSB,1.0);
   
   //Set default parameters;
   diffU = 0.16;
   diffV = 0.08;
   paramF = 0.0545;
   paramK = 0.062;
   
   rndInitCondition = true;
   
   //Populate U and V with initial data
   generateInitialState();
}

void timestep() {
      for (int i = 0; i < M; i++) {
        for (int j = 0; j < N; j++) {
//          int p = i + j*N;
          
          double u = U[i][j];
          double v = V[i][j];
          double uvv = u*v*v;
          
          int left = (i-1+M) % M;
          int right = (i+1) % M;
          int up = (j-1+N) % N;
          int down = (j+1) % N;
       
          double lapU = (U[left][j] + U[right][j] + U[i][up] + U[i][down] - 4*u);
          double lapV = (V[left][j] + V[right][j] + V[i][up] + V[i][down] - 4*v);
          
          dU[i][j] = diffU*lapU  - uvv + paramF*(1 - u);
          dV[i][j] = diffV*lapV + uvv - (paramK+paramF)*v;
        }
      }
    for (int i= 0; i < M; i++) {
      for (int j = 0; j < N; j++){
          U[i][j] += dU[i][j];
          V[i][j] += dV[i][j];
      }
    }
}

void draw(){ 
    for (int i = 0; i < 20; i++) {
       timestep();
    }
   
    // Draw points
    for (int i = 0; i < M; i++) {
      for (int j = 0; j < N; j++) {
        set(i, j, color((float)(1-U[i][j]),0.9, 0.5 ));
      }
    }
}

[編集] キーボードでパラメータを変更

void keyPressed() {
  switch (key) {
    case '1':
          diffU = 0.16;
          diffV = 0.08;
          paramF = 0.035;
          paramK = 0.06;
          generateInitialState();
          break;
    case '2':
          diffU = 0.16;
          diffV = 0.08;
          paramF = 0.042;
          paramK = 0.065;
          generateInitialState();
          break;
    case '3':
          diffU = 0.18;
          diffV = 0.13;
          paramF = 0.025;
          paramK = 0.056;
          generateInitialState();
          break;
    case '4':
          diffU = 0.18;
          diffV = 0.09;
          paramF = 0.02;
          paramK = 0.056;
          generateInitialState();
          break;
    case '5':
          diffU = 0.14;
          diffV = 0.06;
          paramF = 0.035;
          paramK = 0.065;
          generateInitialState();
          break;
    case '6':
          diffU = 0.19;
          diffV = 0.09;
          paramF = 0.062;
          paramK = 0.062;
          generateInitialState();
          break;
     case '7':
          diffU = 0.16;
          diffV = 0.08;
          paramF = 0.05;
          paramK = 0.065;
          generateInitialState();
          break;
    case 'r':
          rndInitCondition = true;
          generateInitialState();
          break;
    case 'n':
          rndInitCondition = false;
          generateInitialState();
  }
}

[編集] 初期状態の発生箇所をウィンドウ全体内でランダムにする

void generateInitialState() {
    for (int i = 0; i < M; i++) {
      for (int j = 0; j < N; j++) { 
        U[i][j] = 1.0;
        V[i][j] = 0.0;
      }
    }
    
    if (rndInitCondition) {
        for (int i = 0; i < M; i++) {
            for (int j = 0; j < N; j++) {     
               U[i][j] = 0.5*(1 + random(-1, 1));
               V[i][j] = 0.25*( 1 + random(-1, 1));
          }
        }
    } else {
      for (int i = 0; i < M; i++) {
            for (int j = 0; j < N; j++) {     
               U[i][j] = 0.5;
               V[i][j] = 0.25;
          }
        }
    }
}

[編集] 模様の発生場所を特定の矩形内に限定する

  • 発生領域
    • X軸:M1からM2
    • Y軸:N1からN2
int M1 = 200;
int N1 = 300;
int M2 = 600;
int N2 = 500;
void timestep() {
      for (int i = M1; i < M2; i++) {
        for (int j = N1; j < N2; j++) {
//          int p = i + j*N;
          
          double u = U[i][j];
          double v = V[i][j];
          double uvv = u*v*v;
          
          int left = (i-1+M2) % M2;
          int right = (i+1) % M2;
          int up = (j-1+N2) % N2;
          int down = (j+1) % N2;
       
          double lapU = (U[left][j] + U[right][j] + U[i][up] + U[i][down] - 4*u);
          double lapV = (V[left][j] + V[right][j] + V[i][up] + V[i][down] - 4*v);
          
          dU[i][j] = diffU*lapU  - uvv + paramF*(1 - u);
          dV[i][j] = diffV*lapV + uvv - (paramK+paramF)*v;
        }
      }
    for (int i= 0; i < M; i++) {
      for (int j = 0; j < N; j++){
          U[i][j] += dU[i][j];
          V[i][j] += dV[i][j];
      }
    }
}

[編集] 人工生命(ALife)

セルオートマトン

ラングトンのアリ

レイノルズのボイド

フラクタル

[編集] 参考

スケーラブルアート論

個人用ツール
名前空間

変種
操作
案内
ツールボックス