二次元浅水方程式のwrangle

浅水方程式の先端の取り扱いに関する研究
https://www.jstage.jst.go.jp/article/jscejhe/72/4/72_I_325/_pdf

 

// シミュレーションパラメータ
float g = 9.81;  // 重力加速度
float dt = 0.01; // 時間ステップ
float dx = 0.1;  // x方向の空間ステップ
float dy = 0.1;  // y方向の空間ステップ
float nu = 0.001; // 数値的粘性(拡散)係数

int rows = chi("rows"); // グリッドの行数
int cols = chi("cols"); // グリッドの列数

// 現在のポイントの水の高さと流速
float h = @h;
float u = @u;
float v = @v;

// 境界条件の確認
int i = @ptnum % cols;
int j = @ptnum / cols;
if (i == 0 || j == 0 || i == cols - 1 || j == rows - 1) {
    // 境界での処理
    h = 0.0;
    u = 0.0;
    v = 0.0;
}
else {
    // 隣接ポイントの水の高さと流速
    float h_right = point(0, "h", @ptnum + 1);
    float u_right = point(0, "u", @ptnum + 1);
    float h_left = point(0, "h", @ptnum - 1);
    float u_left = point(0, "u", @ptnum - 1);

    float h_up = point(0, "h", @ptnum + cols);
    float v_up = point(0, "v", @ptnum + cols);
    float h_down = point(0, "h", @ptnum - cols);
    float v_down = point(0, "v", @ptnum - cols);

    // 二次元浅水方程式の計算
    float h_new = h - dt * ( (u_right * h_right - u_left * h_left) / (2 * dx) +
                            (v_up * h_up - v_down * h_down) / (2 * dy));

    float u_new = u - dt * (u * (u_right - u_left) / (2 * dx) + g * (h_right - h_left) / (2 * dx));
    float v_new = v - dt * (v * (v_up - v_down) / (2 * dy) + g * (h_up - h_down) / (2 * dy));

    // 数値的拡散の追加
    h_new += nu * ( (h_right - 2 * h + h_left) / (dx * dx) + (h_up - 2 * h + h_down) / (dy * dy));
    u_new += nu * ( (u_right - 2 * u + u_left) / (dx * dx) + (u - 2 * u + u) / (dy * dy));
    v_new += nu * ( (v - 2 * v + v) / (dx * dx) + (v_up - 2 * v + v_down) / (dy * dy));

    // 負の高さを防ぐ
    if(h_new < 0) h_new = 0;

    // 更新
    h = h_new;
    u = u_new;
    v = v_new;
}

// ポイント属性の更新
setpointattrib(0, "h", @ptnum, h, "set");
setpointattrib(0, "u", @ptnum, u, "set");
setpointattrib(0, "v", @ptnum, v, "set");

// 水の高さでY座標を更新
@P.y = @h;