/************************************************** 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);