「空気抵抗がある場合の斜方投射を調べる準備」を参照。
SymPy で空気抵抗がある場合の斜方投射の最大水平到達距離を調べる
空気抵抗がある場合の斜方投射の軌道を,Python の SymPy を使って(かつ SciPy や NumPy を使わずに)調べる。
詳細は以下のページ
SymPy の import
from sympy import *
# 1文字変数の Symbol の宣言が省略できる
from sympy.abc import *
# 円周率
from sympy import pi
init_printing()
空気抵抗がある場合の斜方投射の解
空気抵抗がある場合の無次元化された斜方投射の解は,
\begin{eqnarray}
X(T, \theta) &=& \frac{1-e^{-bT}}{b} \cos\theta \\
Y(T, \theta) &=& H+ \frac{1-e^{-bT}}{b}\sin\theta + \frac{1 – bT-e^{-bT}}{b^2}
\end{eqnarray}
def X(T, theta, b):
return (1-exp(-b*T))/b * cos(theta)
def Y(T, theta, H, b):
return H + (1-exp(-b*T))/b * sin(theta) + (1-b*T-exp(-b*T))/b**2
X(T, theta, b)
Y(T, theta, H, b)
滞空時間 $T_1$
滞空時間 $T_1\ \ (>0)$ は以下の式を満たす。
$$Y(T_1, \theta, H, b) = 0 \quad\Rightarrow\quad T_1 = T_1(\theta)$$
陰関数定理を使う
簡単な場合には,$T_1$ は $\theta$ の陽関数として求めることができるが,一般にはそうはいかないかもしれない。そこで,$T_1$ は $\theta$ の陰関数であるとして話を進める。
$Y(T_1(\theta), \theta) = 0$ であるから,
$$\frac{d}{d\theta} Y(T_1(\theta),\theta)=
\frac{\partial Y}{\partial T_1} \frac{d T_1}{d\theta} +
\frac{\partial Y}{\partial \theta}
= 0$$
より,$\displaystyle \frac{d T_1}{d\theta}$ を求めることができる。
T1 = Function('T1')(theta)
dY = diff(Y(T1, theta, H, b), theta)
sol1 = solve(dY, diff(T1, theta))
sol1
dT1 = sol1[0]
Eq(Derivative(T1, theta), dT1)
水平到達距離 $L$
滞空時間 $T_1(\theta)$ の間に水平方向に進む距離は
$$L = X(T_1(\theta), \theta)$$
def L(theta):
return X(T1, theta, b)
L(theta)
$L$ が最大となる角度 $\theta_{\rm max}$
$\displaystyle \frac{dL}{d\theta} = 0$ となる角度 $\theta \equiv \theta_{\rm max}$ を求める。陰関数定理の結果を .subs()
で代入して…
dL = diff(L(theta), theta).subs(diff(T1, theta), dT1)
dL = simplify(dL)
Eq(Derivative(L(theta), theta), dL)
$L$ が最大となる角度は,連立方程式
\begin{eqnarray}
Y(T_1(\theta), \theta) &=& 0 \\
\frac{d}{d\theta} L(\theta) &=& 0
\end{eqnarray}
を,$\sin\theta$ と $T_1(\theta)$ について解いて求めることができる。
Eq(Y(T1, theta, H, b), 0)
Eq(dL, 0)
この連立方程式は,$T_1$ について超越方程式であり,solve()
で解くことはできない。
そこでまず,$Y(T_1(\theta), \theta) = 0$ の式から $\sin\theta$ を $T_1$ で表し,$\sin\theta$ を消去して1変数 $T_1$ に関する方程式にする。
eqsin = solve(Y(T1, theta, H, b), sin(theta))
Eq(sin(theta), eqsin[0])
これを $\displaystyle \frac{d}{d\theta} L(\theta) = 0$ の式に代入して,$T_1(\theta)$ に関する1本の方程式にする。
eq = factor(dL.subs(sin(theta), eqsin[0]))
Eq(eq, 0)
def eqT1(Ti, Hi, bi):
tmp = eq.subs(T1, Ti).subs(H, Hi).subs(b, bi)
return tmp
def T1max(H, b):
sol = nsolve(eqT1(x, H, b), x, [0.1, 3], prec=14)
return sol
$T_{1 \rm max}$ が数値的に求まったら,水平到達距離 $L$ を最大にする角度 $\theta_{\rm max}$ は…
var('T1_max theta_max')
Eq(sin(theta_max), eqsin[0].subs(T1, T1_max))
から…
Eq(theta_max, asin(eqsin[0]).subs(T1, T1_max))
def thetamax(Hi, bi):
tmp = eqsin[0].subs(T1, T1max(Hi, bi)).subs(H, Hi).subs(b, bi)
return asin(tmp)
def degrees(theta):
from sympy import pi
return theta*180/float(pi)
def thmax(H, b):
ans = thetamax(H, b)
return degrees(ans)
最大水平到達距離 $L_{\rm max}$
最大水平到達距離
$$L_{\rm max} = X(T_1(\theta_{\rm max}), \theta_{\rm max}, b)$$
は,$\theta_{\rm max}(H, b)$ であることから最終的に,$L_{\rm max}(H, b)$ となる。
def Lmax(H, b):
return X(T1max(H, b), thetamax(H, b), b)
$H=0, b = 0.5$ の場合の最大水平到達距離と軌道
例として,$H=0, b=0.5$ の場合に水平到達距離 $L$ が最大となる角度 $\theta_{\rm max}$ と,そのときの最大水平到達距離 $L_{\rm max}$ を表示させてみる。
Htmp = 0
btmp = 0.5
print("H = %.1f, b = %.1fのとき," % (Htmp, btmp))
print("L が最大となる角度は θmax=%.14f°" % thmax(Htmp, btmp))
print("そのときの最大水平到達距離は Lmax=%.14f" % Lmax(Htmp, btmp))
空気抵抗がある場合の斜方投射の解
空気抵抗がある場合の無次元化された斜方投射の解は,
\begin{eqnarray}
X(T, \theta) &=& \frac{1-e^{-bT}}{b} \cos\theta \\
Y(T, \theta) &=& H+ \frac{1-e^{-bT}}{b}\sin\theta + \frac{1 – bT-e^{-bT}}{b^2}
\end{eqnarray}
X(T, theta, b):= (1-exp(-b*T))/b * cos(theta);
Y(T, theta, H, b):= H + (1-exp(-b*T))/b * sin(theta) + (1-b*T - exp(-b*T))/b**2;
滞空時間 $T_1$
滞空時間 $T_1\ \ (>0)$ は以下の式を満たす。
$$Y(T_1, \theta, H, b) = 0 \quad\Rightarrow\quad T_1 = T_1(\theta)$$
陰関数定理を使う
簡単な場合には,$T_1$ は $\theta$ の陽関数として求めることができるが,一般にはそうはいかないかもしれない。そこで,$T_1$ は $\theta$ の陰関数であるとして話を進める。
$Y(T_1(\theta), \theta) = 0$ であるから,
$$\frac{d }{d\theta} Y(T_1(\theta), \theta)=
\frac{\partial Y}{\partial T_1} \frac{d T_1}{d\theta} +
\frac{\partial Y}{\partial \theta}
= 0$$
より,$\displaystyle \frac{d T_1}{d\theta}$ を求めることができる。
depends(T1, theta);
dY: diff(Y(T1, theta, H, b)=0, theta);
eqdT1: solve(dY, diff(T1, theta));
水平到達距離 $L$
滞空時間 $T_1(\theta)$ の間に水平方向に進む距離は
$$L = X(T_1(\theta), \theta)$$
L(theta, b):= X(T1, theta, b);
$L$ が最大となる角度 $\theta_{\rm max}$
$\displaystyle \frac{dL}{d\theta} = 0$ となる角度 $\theta \equiv \theta_{\rm max}$ を求める。陰関数定理の結果を ev()
で代入して…
dL: diff(L(theta, b), theta);
dL: trigsimp(ev(dL, eqdT1));
$L$ が最大となる角度は,連立方程式
\begin{eqnarray}
Y(T_1(\theta), \theta) &=& 0 \\
\frac{d}{d\theta} L(\theta) &=& 0
\end{eqnarray}
を,$\sin\theta$ と $T_1(\theta)$ について解いて求めることができる。
Y(T1, theta, H, b) = 0;
dL = 0;
この連立方程式は,$T_1$ について超越方程式であり,solve()
で解くことはできない。
そこでまず,$Y(T_1(\theta), \theta) = 0$ の式から $\sin\theta$ を $T_1$ で表し,$\sin\theta$ を消去して1変数 $T_1$ に関する方程式にする。
eqsin: solve(Y(T1, theta, H, b) = 0, sin(theta));
これを $\displaystyle \frac{d}{d\theta} L(\theta) = 0$ の式に代入して,$T_1(\theta)$ に関する1本の方程式にする。
ev(dL=0, eqsin[1]), factor;
この式もまた $T_1$ に関する超越方程式であり,solve()
では解けない。左辺の分子 num()
の必要な部分のみを取り出し…
define(eqT1(H, b),
num(factor(ev(dL, eqsin[1])*exp(2*b*T1)/(1-exp(b*T1))**2)));
$T_1$ について find_root()
で数値的に解くことにする。
$$H b^2 e^{b T_1}-T_1 b e^{b T_1}+e^{b T_1}+b^2-1 = 0$$を $T_1$ について解いた解を $T_{1 \rm{max}}$ とすると…
T1max(H, b):= find_root(eqT1(H, b)=0, T1, 0.1, 3);
$T_{1 \rm max}$ が数値的に求まったら,水平到達距離 $L$ を最大にする角度 $\theta_{\rm max}$ は…
eqsin[1];
上記の式から
$$\theta_{\rm max} = \arcsin\left(-\frac{\left(H\,b^2-T_{1 \rm{max}}\,b+1\right)\,e^{
T_{1 \rm{max}}\,b}-1}{b\,e^{T_{1 \rm{max}}\,b}-b}\right)$$
より求めることができる。
thetamax(H, b):= asin(ev(rhs(eqsin[1]), T1=T1max(H, b)));
/* 度とラジアンの変換関数を作っておく */
degrees(theta):= float(theta*180/%pi);
thmax(H, b):= degrees(thetamax(H, b));
最大水平到達距離 $L_{\rm max}$
最大水平到達距離
$$L_{\rm max} = X(T_1(\theta_{\rm max}), \theta_{\rm max}, b)$$
は,$\theta_{\rm max}(H, b)$ であることから最終的に,$L_{\rm max}(H, b)$ となる。
Lmax(H, b):= X(T1max(H, b), thetamax(H, b), b);
$H=0, b = 0.5$ の場合の最大水平到達距離と軌道
例として,$H=0, b=0.5$ の場合に水平到達距離 $L$ が最大となる角度 $\theta_{\rm max}$ と,そのときの最大水平到達距離 $L_{\rm max}$ を表示させてみる。
H: 0$
b: 0.5$
printf(true, "H = ~,f, b = ~,1fのとき,~%", H, b)$
printf(true, "L が最大となる角度は θmax=~,14f°~%", thmax(H, b))$
printf(true, "そのときの最大水平到達距離は Lmax=~,14f~%", Lmax(H, b))$