ONLY DO WHAT ONLY YOU CAN DO

こけたら立ちなはれ 立ったら歩きなはれ

C++で常微分方程式(後退オイラー法)

初速 250 km/h で, 45°の角度で打ったボールの軌跡を後退オイラー法で計算する
(空気抵抗係数を 0.01 で計算)

#include <iostream>
#include <iomanip>
#include <math.h>
using namespace std;

// 重力加速度
const double g = -9.8;
// 空気抵抗係数
const double k = -0.01;
// 時間間隔(秒)
const double dt = 0.1;

// 空気抵抗による水平方向の減速分
double fx(double dt, double vx, double v);
// 重力と空気抵抗による鉛直方向の減速分
double fy(double dt, double vy, double v);

int main()
{
    // 角度 
    double degree = 45;
    double radian = degree * M_PI / 180.0;
    // 初速 250 km/h -> 秒速に変換
    double v = 250 * 1000 / 3600; 
    // 水平方向の速度
    double vx = v * cos(radian); 
    // 鉛直方向の速度
    double vy = v * sin(radian); 
    // 経過秒数
    double t = 0.0;
    // 位置
    double x = 0.0;
    double y = 0.0;

    // 後退 Euler法
    for (int i = 1; y >= 0.0; i++) 
    {
        // 経過秒数
        t = i * dt;
        cout << setw(8) << fixed << setprecision(5) << t << "\t";

        // 速度
        cout << setw(8) << fixed << setprecision(5) << vx << "\t";
        cout << setw(8) << fixed << setprecision(5) << vy << "\t";

        // 位置
        x += dt * vx; 
        y += dt * vy; 
        cout << setw(9) << fixed << setprecision(5) << x << "\t";
        cout << setw(8) << fixed << setprecision(5) << y << endl;

        // 速度
        v = sqrt(vx * vx + vy * vy);
        float vx1 = vx + fx(dt, vx, v);
        float vy1 = vy + fy(dt, vy, v);
        for (int j = 0; j <= 10; j++)
        {
            v = sqrt(vx1 * vx1 + vy1 * vy1);
            float vx2 = vx + fx(dt, vx1, v);
            float vy2 = vy + fy(dt, vy1, v);
            if ((fabs(vx1 - vx2) < 0.00001) && (fabs(vy1 - vy2) < 0.00001)) break;
            vx1 = vx2;
            vy1 = vy2;
         }
        vx = vx1;
        vy = vy1;
    }
    return 0;
}

// 空気抵抗による水平方向の減速分
double fx(double dt, double vx, double v)
{
    double ax = k * v * vx;
    return ax * dt; 
}
// 重力と空気抵抗による鉛直方向の減速分
double fy(double dt, double vy, double v)
{
    double ay = k * v * vy;
    return (g + ay) * dt;
}
 0.10000	48.79037	48.79037	  4.87904	 4.87904
 0.20000	45.84741	44.92653	  9.46378	 9.37169
 0.30000	43.25562	41.46219	 13.78934	13.51791
 0.40000	40.95800	38.33189	 17.88514	17.35110
 0.50000	38.90908	35.48337	 21.77605	20.89943
 0.60000	37.07220	32.87448	 25.48327	24.18688
 0.70000	35.41746	30.47085	 29.02502	27.23397
 0.80000	33.92023	28.24416	 32.41704	30.05838
 0.90000	32.56007	26.17089	 35.67305	32.67547
 1.00000	31.31983	24.23135	 38.80503	35.09861
省略
 5.00000	12.88588	-16.83596	116.88782	34.31772
 5.10000	12.61436	-17.44057	118.14926	32.57366
 5.20000	12.34465	-18.02671	119.38372	30.77099
 5.30000	12.07688	-18.59443	120.59141	28.91155
 5.40000	11.81120	-19.14380	121.77253	26.99717
 5.50000	11.54775	-19.67495	122.92731	25.02967
 5.60000	11.28670	-20.18802	124.05598	23.01087
 5.70000	11.02821	-20.68321	125.15880	20.94255
 5.80000	10.77242	-21.16075	126.23604	18.82648
 5.90000	10.51948	-21.62089	127.28799	16.66439
 6.00000	10.26955	-22.06392	128.31494	14.45800
 6.10000	10.02277	-22.49016	129.31722	12.20898
 6.20000	 9.77926	-22.89993	130.29514	 9.91899
 6.30000	 9.53915	-23.29361	131.24906	 7.58963
 6.40000	 9.30255	-23.67155	132.17931	 5.22247
 6.50000	 9.06956	-24.03415	133.08627	 2.81906
 6.60000	 8.84029	-24.38180	133.97030	 0.38088
 6.70000	 8.61481	-24.71493	134.83178	-2.09062
参考文献