前提・実現したいこと
砂紋のパターン形成のシミュレーションを行いたい。
発生している問題・エラーメッセージ
上記のシミュレーションを行うプログラムを作成しています。
プログラム上で周期境界を再現したいのですが、やり方がどうしても分かりません。
簡単に言うと、x=50,y=50の幅の平面で2次元配列h[50][50]を扱う際に
[-1]など中身が負の数になってしまうとき、[-1]→[49]として[-1]をもう一方の端として扱うようにしたいです。
C言語に慣れておらず拙い説明で申し訳ありませんが、ご回答いただけると嬉しいです。
該当のソースコード
#include<stdio.h> #include<stdlib.h> #include<time.h> int main(void) { int x_scale, y_scale, step,ir,jr; x_scale = 50; //x方向長さ y_scale = 50; //y方向長さ step = 1; //計算回数 double yuragi, q, b, D, side, slant,v,w; yuragi = 0.3; // q = 0.1; //跳躍により移動する砂の量 b = 1.0; //跳躍距離のパラメータ D = 0.1; //転がりにより移動する砂の量のパラメータ(転がり出る砂の量=Dh) side = 2.0; //転がり計算の時に使うパラメータ slant = 1.0; //同上 srand(time(NULL)); int i,j,s, t, L, k, L_0;//L=L_0 + bh (跳躍距離) L_0 = 3; //風速に対応するパラメータ double h[50][50]; //[x,y]における砂の高さ(積載量) FILE*fp; fp=fopen("output.dat", "w"); for (j = 0;j < y_scale;j++) { for (i = 0;i < x_scale;i++) { h[i][j] = 2.85 + (yuragi * rand() / (double)RAND_MAX); //各座標のhの初期値を2.85~3.15の間で乱数で取る } } for (t = 1; t <= step; t++) { for (k = 1; k < 2500; k++) //跳躍計算 { v = (int)(50 * rand() / (double)RAND_MAX); w = (int)(50 * rand() / (double)RAND_MAX); ir = v; jr = w; // if (h[ir][jr] > 0) { L = L_0 + (b * (int)h[(ir)][(jr)]); h[(ir)][(jr)] -= q; h[(ir + L)][(jr)] += q; } else { continue; } } for (j = 1;j < y_scale - 1;j++) { for (i = 1;i < x_scale - 1;i++) { if (h[i][j] > h[(i - 1)][(j)] && h[i][j] > h[(i + 1)][(j)] && h[i][j] > h[(i)][(j - 1)] && h[i][j] > h[i][(j + 1)] && h[i][j] > h[(i - 1)][(j - 1)] && h[i][j] > h[i - 1][(j + 1)] && h[i][j] > h[(i + 1)][(j - 1)] && h[i][j] > h[i + 1][(j + 1)]) { h[(i - 1)][(j)] += D * h[i][j] * (1.0 / 4.0) * (side / (side + slant)); h[(i + 1)][(j)] += D * h[i][j] * (1.0 / 4.0) * (side / (side + slant)); h[(i)][(j - 1)] += D * h[i][j] * (1.0 / 4.0) * (side / (side + slant)); h[(i)][(j + 1)] += D * h[i][j] * (1.0 / 4.0) * (side / (side + slant)); h[(i - 1)][(j - 1)] += D * h[i][j] * (1.0 / 4.0) * (slant / (side + slant)); h[(i - 1)][(j + 1)] += D * h[i][j] * (1.0 / 4.0) * (slant / (side + slant)); h[(i + 1)][(j - 1)] += D * h[i][j] * (1.0 / 4.0) * (slant / (side + slant)); h[(i + 1)][(j + 1)] += D * h[i][j] * (1.0 / 4.0) * (slant / (side + slant)); h[i][j] -= D * h[i][j]; } else { continue; } } } for (j = 0;j < y_scale;j++) { for(i = 0; i < x_scale; i++ ){ printf("%f\n",h[i][j]); fprintf(fp, "%f\n",h[i][j]); } } } fclose(fp); }
変更後のソースコード
#include<stdio.h> #include<stdlib.h> #include<time.h> int main(void) { int x_scale, y_scale, step; x_scale = 50; //x方向長さ y_scale = 50; //y方向長さ step = 1; //計算回数 double yuragi, q, b, D, side, slant,v,w; yuragi = 0.3; // q = 0.1; //跳躍により移動する砂の量 b = 1.0; //跳躍距離のパラメータ D = 0.1; //転がりにより移動する砂の量のパラメータ(転がり出る砂の量=Dh) side = 2.0; //転がり計算の時に使うパラメータ slant = 1.0; //同上 srand(time(NULL)); int x,y,i,j,i_1,i_2,j_1,j_2,i_0,s, t, L, k, L_0;//L=L_0 + bh (跳躍距離) L_0 = 3; //風速に対応するパラメータ i = (x_scale + (x % x_scale))%(x_scale); j = (y_scale + (y % y_scale))%(y_scale); i_1 = (x_scale + ((x - 1) % x_scale))%(x_scale); i_2 = (x_scale + ((x + 1) % x_scale))%(x_scale); j_1 = (y_scale + ((y - 1) % y_scale))%(y_scale); j_2 = (y_scale + ((y + 1) % y_scale))%(y_scale); i_0 = (x_scale + ((x + L) % x_scale))%(x_scale); double h[50][50]; //[x,y]における砂の高さ(積載量) FILE*fp; fp=fopen("output.dat", "w"); for (y = 0;y < y_scale;y++) { for (x = 0;x < x_scale;x++) { h[x][y] = 2.85 + (yuragi * rand() / (double)RAND_MAX); //各座標のhの初期値を2.85~3.15の間で乱数で取る } } for (t = 1; t <= step; t++) { for (k = 1; k < 2500; k++) //跳躍計算 { v = (int)(50 * rand() / (double)RAND_MAX); w = (int)(50 * rand() / (double)RAND_MAX); x = v; y = w; L = L_0 + (b * (int)h[(i)][(j)]); if (h[i][j] > 0) { h[(i)][(j)] -= q; h[(i_0)][(j)] += q; } else { continue; } } for (y = 0;y < y_scale ;y++) { for (x = 0;x < x_scale ;x++) { if (h[i][j] > h[(i_1)][(j)] && h[i][j] > h[(i_2)][(j)] && h[i][j] > h[(i)][(j_1)] && h[i][j] > h[i][(j_2)] && h[i][j] > h[(i_1)][(j_1)] && h[i][j] > h[i_1][(j_2)] && h[i][j] > h[(i_2)][(j_1)] && h[i][j] > h[i_2][(j_2)]) { h[(i_1)][(j)] += D * h[i][j] * (1.0 / 4.0) * (side / (side + slant)); h[(i_2)][(j)] += D * h[i][j] * (1.0 / 4.0) * (side / (side + slant)); h[(i)][(j_1)] += D * h[i][j] * (1.0 / 4.0) * (side / (side + slant)); h[(i)][(j_2)] += D * h[i][j] * (1.0 / 4.0) * (side / (side + slant)); h[(i_1)][(j_1)] += D * h[i][j] * (1.0 / 4.0) * (slant / (side + slant)); h[(i_1)][(j_2)] += D * h[i][j] * (1.0 / 4.0) * (slant / (side + slant)); h[(i_2)][(j_1)] += D * h[i][j] * (1.0 / 4.0) * (slant / (side + slant)); h[(i_2)][(j_2)] += D * h[i][j] * (1.0 / 4.0) * (slant / (side + slant)); h[i][j] -= D * h[i][j]; } else { continue; } } } for (y = 0;y < y_scale;y++) { for(x = 0; x < x_scale; x++ ){ printf("%f\n",h[i][j]); fprintf(fp, "%f\n",h[i][j]); } } } fclose(fp); }
出力
-0.039956
-0.039956
-0.039956
-0.039956
↑これがずっと続きます
補足情報(FW/ツールのバージョンなど)
Visual Studio Codeで作成しています。