/**************************************************
gasdiffusion.cc
セルオートマトンによるガス拡散シミュレーション
***************************************************/
#define TIMES 20
vs_module
gasdiffusion(iImage cell, iImage gas, iImage rand)
{
fprintf(stderr,"process start.\n");
// テンポラリ変数
iImage neighbors(cell);
iImage shadow(gas);
int times = 0;
do {
ImgCopy(neighbors, rand);
// 径1の外周(全領域中での)は処理からはずす
vsSetBoundary2D(1);
parallel_ie(x,y) {
if(times % 2) {
switch(cell[][]) {
case 0:
neighbors[][] += rand[+1][];
neighbors[][] += rand[][-1];
neighbors[][] += rand[+1][-1];
break;
case 1:
neighbors[][] += rand[][-1];
neighbors[][] += rand[-1][];
neighbors[][] += rand[-1][-1];
break;
case 3:
neighbors[][] += rand[-1][];
neighbors[][] += rand[][+1];
neighbors[][] += rand[-1][+1];
break;
default:
neighbors[][] += rand[][+1];
neighbors[][] += rand[+1][];
neighbors[][] += rand[+1][+1];
}
} else {
switch(cell[][]) {
case 3:
neighbors[][] += rand[+1][];
neighbors[][] += rand[][-1];
neighbors[][] += rand[+1][-1];
break;
case 2:
neighbors[][] += rand[][-1];
neighbors[][] += rand[-1][];
neighbors[][] += rand[-1][-1];
break;
case 0:
neighbors[][] += rand[-1][];
neighbors[][] += rand[][+1];
neighbors[][] += rand[-1][+1];
break;
default:
neighbors[][] += rand[][+1];
neighbors[][] += rand[+1][];
neighbors[][] += rand[+1][+1];
}
}
}
vsSetBoundary2D(0);
parallel_ie(x,y) {
if((x > 1) && (x < (width -1)) && (y > 1) && (y < (heigh -1))) {
if(neighbors[][] % 2) {
// 偶数の場合 - - - - - - - - - - - - - - - - -
if(times % 2) {
switch(cell[][]) {
case 0:
shadow[][] = gas[][-1]; break;
case 1:
shadow[][] = gas[-1][]; break;
case 3:
shadow[][] = gas[][+1]; break;
default:
shadow[][] = gas[+1][];
}
} else {
switch(cell[][]) {
case 3:
shadow[][] = gas[][-1]; break;
case 2:
shadow[][] = gas[-1][]; break;
case 0:
shadow[][] = gas[][+1]; break;
default:
shadow[][] = gas[+1][];
}
}
} else {
// 奇数の場合 - - - - - - - - - - - - - - - - -
if(times % 2) {
switch(cell[][]) {
case 0:
shadow[][] = gas[+1][]; break;
case 1:
shadow[][] = gas[][-1]; break;
case 3:
shadow[][] = gas[-1][]; break;
default:
shadow[][] = gas[][+1];
}
} else {
switch(cell[][]) {
case 3:
shadow[][] = gas[+1][]; break;
case 2:
shadow[][] = gas[][-1]; break;
case 0:
shadow[][] = gas[-1][]; break;
default:
shadow[][] = gas[][+1];
}
}
}
} else {
shadow[][] = gas[][];
}
}
// 大域変数にコピー
ImgCopy(gas,shadow);
parallel_ie(x,y) {
if((x > 1) && (x < (width -1)) && (y > 1) && (y < (heigh -1))) {
neighbors[][] = \
(rand[+1][] + rand[][+1] + rand[-1][] + rand[][-1]) % 2;
} else {
neighbors[][] = rand[][];
}
}
} while(++times < TIMES);
}
/****************************************
* 実装実験用プログラムgasdiffusion.vpe *
****************************************/
// 通信処理初期化 -------------
#pragma host_name host1
#pragma host_name host2
#pragma host_name host3
#pragma host_name host4
#pragma use_intercomm
// データの初期化 -------------
int w,h;
w = 512;
h = w;
iImage cell(w,h);
iImage gas(w,h);
iImage rand(w,h);
int i, j;
// cellの初期値を入れる
for(j=0; j<h; j=j+2)
for(i=0; i<w; i=i+2) cell(i,j) = 3;
for(j=1; j<h; j=j+2)
for(i=0; i<w; i=i+2) cell(i,j) = 1;
for(j=0; j<h; j=j+2)
for(i=1; i<w; i=i+2) cell(i,j) = 2;
// gas の初期値を入れる
for(j=h/3; j<h/3*2; j=j+1)
for(i=w/3; i<w/3*2; i=i+1) gas(i,j) = 1;
// randの初期値を入れる
for(j=0; j<h; j=j+1)
for(i=0; i<w; i=i+1)
rand(i,j) = random() / (RAND_MAX / 5);
module("gasdiffusion", cell, gas, rand);
gather(gas);
imgSave("result.pgm", gas);