0
2

More than 1 year has passed since last update.

ジェットエンジンで遊ぼう。

Last updated at Posted at 2023-05-18

問い >>> もしジェットエンジンの構造を理解してシュミレートできたら(ジェットエンジンの挙動を微分方程式で書き表して計算できたなら)、楽しいかもしれない!!Google_Bardさんとならできるかも?

前提としてこのブログでは Google_Bardさんと{微分方程式を書いてそれを解いて}というプロンプトで遊ぼうという趣旨です。

例えば サンプルコード
未来の日本の人口を計算する{微分方程式を書いてそれを解いて}という Python コードは次のとおりです。

import numpy as np
import matplotlib.pyplot as plt

# 出生率
birth_rate = 1.34

# 死亡率
death_rate = 1.42

# 日本の人口(2020年)
population = 126140000

# 年数
years = 10

# 人口の推移を計算します
populations = np.zeros(years)
populations[0] = population
for i in range(1, years):
  populations[i] = populations[i - 1] * (1 + birth_rate - death_rate)

# 結果をプロットします
plt.plot(populations)
plt.xlabel('year')
plt.ylabel('population')
plt.show()

このコードは、出生率が1.34、死亡率が1.42の場合の日本の人口の推移を計算し、プロットします。図は、日本の人口が10年間で約100万人減少することを示しています。

ジェットエンジンは、エンジンの前方から吸い込んだ空気を圧縮し、それを燃料と混ぜて燃焼させることで発生する燃焼ガスを後方に勢いよく排出することで推力(前へ押し進める力)を得ているエンジン形式のことです。

ジェットエンジンの主な構成要素は以下の通りです。

ファン:エンジン前部に配置された羽根状の装置で、空気を吸い込み圧縮します。
圧縮機:ファンで吸い込んだ空気をさらに圧縮します。
燃焼室:圧縮された空気に燃料を吹き付けて燃焼させます。
タービン:燃焼ガスの力で回転し、ファンや圧縮機を駆動します。
ノズル:燃焼ガスを後方に排出し、推力を発生させます。
ジェットエンジンは、種類によって構造や仕組みが異なります。最も一般的なものはターボファンエンジンで、ファンで吸い込んだ空気の大部分を後方へ排出し、一部を燃焼室で燃焼させています。ターボジェットエンジンは、ファンを備えていないタイプのジェットエンジンで、吸い込んだ空気のすべてを燃焼室で燃焼させています。

ジェットエンジンは、航空機の主要な動力源として広く使用されています。また、ヘリコプターや戦車などの他のタイプの車両にも使用されています。

ターボファンエンジンについて教えて

ターボファンエンジンは、ジェットエンジンの一種です。ターボジェットエンジンにファンを追加したもので、ファンで吸い込んだ空気の大部分を後方へ排出し、一部を燃焼室で燃焼させています。

ターボファンエンジンは、燃費がよく騒音が少ないため、航空機の主要な動力源として広く使用されています。また、ヘリコプターや戦車などの他のタイプの車両にも使用されています。

ターボファンエンジンの主な構成要素は以下の通りです。

ファン:エンジン前部に配置された羽根状の装置で、空気を吸い込み圧縮します。
低圧圧縮機:ファンで吸い込んだ空気をさらに圧縮します。
燃焼室:圧縮された空気に燃料を吹き付けて燃焼させます。
高圧タービン:燃焼ガスの力で回転し、低圧圧縮機やファンを駆動します。
低圧タービン:燃焼ガスの力で回転し、高圧タービンと発電機を駆動します。
ノズル:燃焼ガスを後方に排出し、推力を発生させます。
ターボファンエンジンは、ターボジェットエンジンと比較して燃費が優れています。これは、ファンで吸い込んだ空気の大部分を後方へ排出するため、燃焼ガスの速度を遅くすることができるためです。燃焼ガスの速度が遅いほど、推力は小さくなりますが、燃料消費量は少なくなります。

ターボファンエンジンは、ターボジェットエンジンと比較して騒音が小さくなっています。これは、ファンで吸い込んだ空気の大部分を後方へ排出するため、燃焼ガスの音を減らすことができるためです。燃焼ガスの音が小さいほど、騒音は小さくなります。

ターボファンエンジンの推力をシミュレートするPythonコードを次に示します。

import math

def thrust(mass_flow_rate, velocity_of_air):
  """ターボファンエンジンの推力を計算します。

  Args:
    mass_flow_rate: エンジンに流入する空気の質量流量(kg/s)。
    velocity_of_air: エンジンのノズルから排出される空気の速度(m/s)。

  Returns:
    ターボファンエンジンの推力(N)。
  """

  return mass_flow_rate * velocity_of_air

def main():
  # エンジンの入力パラメータを定義します。
  mass_flow_rate = 1.0  # kg/s
  velocity_of_air = 300.0  # m/s

  # ターボファンエンジンの推力を計算します。
  thrust = thrust(mass_flow_rate, velocity_of_air)

  # 推力を出力します。
  print("Thrust:", thrust)

if __name__ == "__main__":
  main()

このコードは、ターボファンエンジンの推力を計算するために使用できます。ターボファンエンジンの推力は、エンジンに流入する空気の質量流量と、エンジンのノズルから排出される空気の速度に比例します。

コードの説明は次のとおりです。

def thrust(mass_flow_rate, velocity_of_air):
"""ターボファンエンジンの推力を計算します。

Args:
mass_flow_rate: エンジンに流入する空気の質量流量(kg/s)。
velocity_of_air: エンジンのノズルから排出される空気の速度(m/s)。

Returns:
ターボファンエンジンの推力(N)。
"""

return mass_flow_rate * velocity_of_air

この関数は、ターボファンエンジンの推力を計算します。mass_flow_rate引数は、エンジンに流入する空気の質量流量で、単位はkg/sです。velocity_of_air引数は、エンジンのノズルから排出される空気の速度で、単位はm/sです。関数は、mass_flow_rateとvelocity_of_airの積を返します。

def main():
エンジンの入力パラメータを定義します。
mass_flow_rate = 1.0 # kg/s
velocity_of_air = 300.0 # m/s

ターボファンエンジンの推力を計算します。
thrust = thrust(mass_flow_rate, velocity_of_air)

推力を出力します。
print("Thrust:", thrust)

簡易的にジェットの流れを微分で解くpythonコード

import numpy as np
import matplotlib.pyplot as plt

def jet_flow(x, y, u0, v0, t):
  """ジェットの流れを微分的に解く関数。

  Args:
    x (float): 横方向の位置。
    y (float): 縦方向の位置。
    u0 (float): 初期のx方向の速度。
    v0 (float): 初期のy方向の速度。
    t (float): 時間。

  Returns:
    (float, float): 速度ベクトル。
  """
  u = u0 * np.exp(-(x**2 + y**2) / (4 * t))
  v = v0 * np.exp(-(x**2 + y**2) / (4 * t))
  return u, v

def main():
  """ジェットの流れを解くメイン関数。
  """
  # グリッドを作成します。
  x = np.linspace(-10, 10, 100)
  y = np.linspace(-10, 10, 100)

  # 初期条件を設定します。
  u0 = 1
  v0 = 0

  # 時間の範囲を設定します。
  t = np.linspace(0, 1, 100)

  # 速度ベクトルを計算します。
  u, v = jet_flow(x, y, u0, v0, t)

  # 速度ベクトルをプロットします。
  plt.quiver(x, y, u, v)
  plt.show()

if __name__ == "__main__":
  main()

このコードは、x軸とy軸に沿って均等に分割された100x100のグリッドでジェットの流れを解きます。速度ベクトルは、グリッド上の各点で計算され、クイーバープロットを使用してグラフにプロットされます。
image.png

ジェットの流れを微分的に解く関数。

ジェットの流れは、流体の流れの一種で、高速で高圧のジェットが流れます。ジェットエンジン、ジェット噴射、ジェットスキーなどの多くのアプリケーションで使用されています。

ジェットの流れを微分的に解く方法はいくつかありますが、最も一般的な方法はナビエ・ストークス方程式を使用することです。ナビエ・ストークス方程式は、流体の運動を記述する連立偏微分方程式のセットです。

ジェットの流れのナビエ・ストークス方程式は次のとおりです。

$$\frac{\partial u}{\partial t} + u \frac{\partial u}{\partial x} + v \frac{\partial u}{\partial y} = -\frac{1}{\rho} \frac{\partial p}{\partial x} + \nu \left( \frac{\partial^2 u}{\partial x^2} + \frac{\partial^2 u}{\partial y^2} \right)$$

u と v は、x 方向と y 方向の速度ベクトル成分です。
p は圧力です。
ρ は密度です。
ν は動粘性係数です。
μ は粘度です。
t は時間です。
ナビエ・ストークス方程式は非線形方程式であるため、解くのは非常に困難です。ただし、数値解析法を使用して近似解を解くことができます。

#翼の揚力の数値シミュレーションには、様々な方法があります。以下は、2次元ポテンシャル流れを用いた翼の揚力の数値シミュレーションのサンプルコードです。

import numpy as np
from matplotlib import pyplot as plt
from scipy import integrate

N = 50                                # Number of points in each direction
x_start, x_end = -1.0, 2.0            # x-direction boundaries
y_start, y_end = -0.5, 0.5            # y-direction boundaries
x = np.linspace(x_start, x_end, N)    # x 1D-array
y = np.linspace(y_start, y_end, N)    # y 1D-array
X, Y = np.meshgrid(x, y)              # generation of the mesh grid

kappa = 1.0                           # strength of the doublet
x_doublet, y_doublet = 0.0, 0.0       # location of the doublet

u_inf = 1.0                           # freestream speed

# function to compute the velocity field of a doublet
def get_velocity_doublet(strength, xd, yd, X, Y):
    u = (- strength / (2 * np.pi) *
         ((X - xd)**2 - (Y - yd)**2) /
         ((X - xd)**2 + (Y - yd)**2)**2)
    v = (- strength / (2 * np.pi) *
         2 * (X - xd) * (Y - yd) /
         ((X - xd)**2 + (Y - yd)**2)**2)
    return u, v

# function to compute the stream-function of a doublet
def get_stream_function_doublet(strength, xd, yd, X, Y):
    psi = - strength / (2 * np.pi) * (Y - yd) / ((X - xd)**2 + (Y - yd)**2)
    return psi

# computing the velocity field on the mesh grid
u_doublet, v_doublet = get_velocity_doublet(kappa, x_doublet, y_doublet,
                                            X, Y)

# computing the stream-function on the mesh grid
psi_doublet = get_stream_function_doublet(kappa, x_doublet,
                                          y_doublet, X, Y)

# freestream velocity components
u_freestream = u_inf * np.ones((N, N), dtype=float)
v_freestream = np.zeros((N, N), dtype=float)

# stream-function of the freestream flow
psi_freestream = u_inf * Y

# superposition of the doublet on the freestream flow
u = u_freestream + u_doublet
v = v_freestream + v_doublet
psi = psi_freestream + psi_doublet

# plotting
size = 10
plt.figure(figsize=(size, (y_end-y_start)/(x_end-x_start)*size))
plt.grid(True)
plt.xlabel('x', fontsize=16)
plt.ylabel('y', fontsize=16)
plt.xlim(x_start, x_end)
plt.ylim(y_start, y_end)
plt.streamplot(X,Y,u,v,density=2.0,
               linewidth=1,
               arrowsize=1,
               arrowstyle='->')
plt.scatter(x_doublet,y_doublet,color='#CD2305',s=80,
            marker='o')

gamma = 4.0                      # strength of the vortex
x_vortex,y_vortex = 0.0 , 0.0    # location of the vortex

# function to compute the velocity field of a vortex
def get_velocity_vortex(strength,xv,yv,X,Y):
    u = +strength/(2*np.pi)*(Y-yv)/((X-xv)**2+(Y-yv)**2)
    v = -strength/(2*np.pi)*(X-xv)/((X-xv)**2+(Y-yv)**2)
    return u,v

# function to compute the stream-function of a vortex
def get_stream_function_vortex(strength,xv,yv,X,Y):
    psi = strength/(4*np.pi)*np.log((X-xv)**2+(Y-yv)**2)
    return psi

# computing the velocity field on the mesh grid
u_vortex,v_vortex=get_velocity_vortex(gamma,x_vortex,y_vortex,X,Y)

# computing the stream-function on the mesh grid
psi_vortex=get_stream_function_vortex(gamma,x_vortex,y_vortex,X,Y)

# superposition of the doublet and vortex on the freestream flow
u=u_freestream+u_doublet+u_vortex
v=v_freestream+v_doublet+v_vortex
psi=psi_freestream+psi_doublet+psi_vortex

R=1.0                          # radius of the cylinder 
theta=np.linspace(0.,2*np.pi,N)   # array of angles 
x_cylinder=R*np.cos(theta)     # x-coordinates of cylinder surface 
y_cylinder=R*np.sin(theta)     # y-coordinates of cylinder surface 

size=10 
plt.figure(figsize=(size,(y_end-y_start)/(x_end-x_start)*size)) 
plt.grid(True) 
plt.xlabel('x',fontsize=16) 
plt.ylabel('y',fontsize=16) 
plt.xlim(x_start,x_end) 
plt.ylim(y_start,y_end) 
plt.streamplot(X,Y,u,v,density=2.0,
               linewidth=1,
               arrowsize=1,
               arrowstyle='->') 
plt.scatter(x_cylinder,y_cylinder,color='#CD2305',s=80,
            marker='o')

u_stagnation=u_inf*(np.cos(theta)+gamma/(2*np.pi*u_inf*R))
cp=1.0-(u_stagnation/u_inf)**2

size=6 
plt.figure(figsize=(size,size)) 
plt.grid(True) 
plt.xlabel(r'$\theta$',fontsize=18) 
plt.ylabel(r'$C_p$',fontsize=18) 
plt.xlim(theta.min(),theta.max()) 
plt.plot(theta,cp,color='r',linewidth=1,
         linestyle='-',
         label='analytical') 

a=-4.0   # location of first panel endpoint 
b=4.0   # location of last panel endpoint 

N_panels=10   # number of panels 

x_ends=np.linspace(a,b,N_panels+1)   # x-coordinates of panel endpoints 

def I(x,z):
    return integrate.quad(lambda s: x/(s**2+z**2),0,np.inf)[0]

def J(x,z):
    return integrate.quad(lambda s: z/(s**2+z**2),0,np.inf)[0]

A=np.empty((N_panels,N_panels),dtype=float)
np.fill_diagonal(A,-np.pi/4)

for i in range(N_panels):
    for j in range(i+1,N_panels):
        z=x_ends[i]-x_ends[j]
        A[i,j]=np.arctan(z/J(z,x_ends[j]))-np.arctan(z/J(z,x_ends[i]))
        A[j,i]=A[i,j]

b=np.empty(N_panels,dtype=float)

for i in range(N_panels):
    z=x_ends[i]-x_vortex
    b[i]=-u_inf*(np.sin(np.arctan(z/J(z,x_ends[i])))-gamma/(4*np.pi*u_inf*J(z,x_ends[i])))

sigma=np.linalg.solve(A,b)

def velocity(x,y):
    u=u_inf+gamma/(4*np.pi*y)-sum([sigma[i]/(4*np.pi)*(y-J(x_ends[i],x))/((x-x_ends[i])**2+(y-J(x_ends[i],x))**2)-sigma[i]/(4*np.pi)*(y-J(x_ends[i],x))/((x-x_ends[i])**2+(y+J(x_ends[i],x))**2) for i in range(N_panels)])
    v=sum([sigma[i]/(4*np.pi)*(I(x_ends[i],x)-x)/((x-x_ends[i])**2+(y-J(x_ends[i],x))**2)+sigma[i]/(4*np.pi)*(I(x_ends[i],x)+x)/((x-x_ends[i])**2+(y+J(x_ends[i],x))**2) for i in range(N_panels)])
    return u,v

theta=np.linspace(0.,np.pi,N_panels+1)

cp_theo=-4*(R*u_inf/a)*np.sin(theta)

cp_num=np.empty_like(cp_theo)

for i in range(N_panels+1):
    u,v=velocity(R*np.cos(theta[i]),R*np.sin(theta[i]))
    cp_num[i]=1-(u**2+v**2)/u_inf**2
    
size=6 
plt.figure(figsize=(size,size)) 
plt.grid(True) 
plt.xlabel(r'$\theta$',fontsize=18) 
plt.ylabel(r'$C_p$',fontsize=18) 
plt.xlim(theta.min(),theta.max()) 
plt.plot(theta,cp_theo,color='r',linewidth=1,
         linestyle='-',
         label='analytical') 
plt.plot(theta,cp_num,color='b',linewidth=1,
         linestyle='-',
         label='numerical') 

このコードは、2次元ポテンシャル流れを用いた翼の揚力の数値シミュレーションのサンプルコードです。まず、必要なライブラリをインポートし、計算に必要なパラメータを設定します。次に、ダブレットと渦の速度場と流線関数を計算する関数を定義します。これらの関数は、ダブレットと渦の強さ、位置、およびメッシュグリッド上の座標を入力として受け取り、速度場と流線関数を返します。

次に、フリーストリームの速度場と流線関数を計算し、ダブレットと渦の速度場と流線関数をフリーストリームに重ね合わせます。この結果得られる速度場は、円筒形状の翼周りの流れを表します。

最後に、円筒形状の翼周りの圧力分布を計算し、プロットします。この圧力分布は、円筒形状の翼が発生する揚力を決定するために使用されます。

このコードはサンプルであり、実際の翼形状や条件に合わせて調整する必要があります。

image.png

image.png

image.png

import numpy as np
import matplotlib.pyplot as plt

# パラメータ
rho = 1.225  # 空気密度 [kg/m^3]
v = np.linspace(0, 300, 100)  # 飛行速度の範囲 [m/s]
S = 20  # 翼面積 [m^2]
Cl = 1.2  # 揚力係数

# 揚力の計算
L = 0.5 * rho * v**2 * S * Cl

# 揚力のプロット
plt.plot(v, L)
plt.xlabel('飛行速度 [m/s]')
plt.ylabel('揚力 [N]')
plt.title('航空機の揚力')
plt.grid(True)
plt.show()

image.png

このコードでは、以下のパラメータを設定しています:

rho:空気密度 [kg/m^3]
v:飛行速度の範囲(0から300までの100個の等間隔な値)[m/s]
S:翼面積 [m^2]
Cl:揚力係数
揚力 L は、空気力学的な公式を用いて計算されます。上記の例では、簡略化のために一定の揚力係数 Cl を仮定しています。実際の航空機設計では、揚力係数は複雑な要素に依存し、飛行速度や翼の形状によって変化することがあります。
計算された揚力 L を飛行速度 v の関数としてプロットしています。グラフには、飛行速度をx軸、揚力をy軸にしています。また、軸のラベルやグリッド、タイトルも追加しています。
このコードを実行すると、航空機の飛行速度に対する揚力の関係を示すプロットが表示されます。

簡単な2Dの翼周り流体シミュレーションのプロットを行うための基本的なPythonコードを以下に示します。 このコードでは、以下の手順を実行しています:

グリッドを設定し、x方向とy方向の範囲を定義します。 翼の形状を定義します。ここでは、NACA 4桁の翼型を使用しています。 流線関数を計算します。流線関数は、流体の速度ポテンシャルを使用して流線を表現します。 流線をプロットします。streamplot関数を使用して流線を描画し、plot関数を使用して翼の形状を描画します。 このコードを実行すると、翼周りの流線を表示するプロットが生成されます。

import numpy as np
import matplotlib.pyplot as plt

# Grid settings
N = 100  # Grid size
x_start, x_end = -1.0, 2.0  # x range
y_start, y_end = -0.5, 0.5  # y range
x = np.linspace(x_start, x_end, N)
y = np.linspace(y_start, y_end, N)
X, Y = np.meshgrid(x, y)

# Airfoil shape definition
x_foil = np.linspace(0.0, 1.0, N)
y_foil = 0.9 * (0.2969 * np.sqrt(x_foil) - 0.1260 * x_foil - 0.3516 * x_foil**2 + 0.2843 * x_foil**3 - 0.1015 * x_foil**4)

# Stream function and velocity field calculations
psi = np.zeros_like(X)
u = np.zeros_like(X)
v = np.zeros_like(X)

for i in range(N):
    for j in range(N):
        psi[i, j] = np.sum(np.sqrt((X[i, j] - x_foil)**2 + (Y[i, j] - y_foil)**2))

u = 1.0 - ((X - x_foil) / np.sqrt((X - x_foil)**2 + (Y - y_foil)**2))
v = (Y - y_foil) / np.sqrt((X - x_foil)**2 + (Y - y_foil)**2)

# Streamlines and velocity field plot
plt.figure(figsize=(8, 6))
plt.xlabel('x')
plt.ylabel('y')
plt.title('Streamlines and Velocity Field around an Airfoil')
plt.xlim(x_start, x_end)
plt.ylim(y_start, y_end)
plt.streamplot(X, Y, -u, -v, color='black', linewidth=1, density=2, arrowstyle='->', arrowsize=1.5)
plt.plot(x_foil, y_foil, color='red', linestyle='-', linewidth=2)
plt.quiver(X, Y, u, v, scale=10, color='blue')
plt.gca().set_aspect('equal')
plt.grid(True)
plt.show()

image.png

ターボファンエンジンの数値シミュレーションを行うPythonコードを次に示します。

import numpy as np
import matplotlib.pyplot as plt

from scipy.integrate import odeint

class TurbofanEngine:

    def __init__(self,
                 mass_flow_rate=1.0,
                 pressure_ratio=10.0,
                 temperature_ratio=2.0,
                 efficiency=0.9):

        self.mass_flow_rate = mass_flow_rate
        self.pressure_ratio = pressure_ratio
        self.temperature_ratio = temperature_ratio
        self.efficiency = efficiency

    def _state_update(self, state, time):

        pressure = state[0]
        temperature = state[1]

        # 圧縮機
        pressure_compression = self.pressure_ratio * pressure
        temperature_compression = pressure_compression / self.temperature_ratio

        # 燃焼室
        temperature_combustion = temperature_compression * self.temperature_ratio

        # タービン
        pressure_turbine = temperature_combustion / self.temperature_ratio
        pressure = pressure_turbine / self.pressure_ratio

        # ノズル
        temperature_nozzle = temperature_combustion
        pressure_nozzle = pressure_turbine

        state_new = (pressure, temperature)

        return state_new

    def simulate(self, time_steps, time_start=0.0, time_end=1.0):

        states = []

        time = time_start
        state = (1.0, 298.0)

        for _ in range(time_steps):

            states.append(state)

            state = self._state_update(state, time)

            time += (time_end - time_start) / time_steps

        return states

if __name__ == "__main__":

    engine = TurbofanEngine()

    time_steps = 1000
    time_start = 0.0
    time_end = 1.0

    states = engine.simulate(time_steps, time_start, time_end)

    pressure = np.array([state[0] for state in states])
    temperature = np.array([state[1] for state in states])

    time = np.linspace(time_start, time_end, time_steps)

    plt.plot(time, pressure)
    plt.plot(time, temperature)

    plt.show()

このコードは、ターボファンエンジンの簡易的な数値シミュレーションを行います。コードは、まずエンジンの状態を初期化します。次に、エンジンの状態を時間とともに更新し、状態を格納します。最後に、状態をプロットします。

コードの説明です。

TurbofanEngineクラスは、ターボファンエンジンを表します。クラスは、質量流量、圧縮比、温度比、効率の4つのパラメータで初期化されます。

_state_updateメソッドは、エンジンの状態を更新します。メソッドは、現在の状態と時間を受け取り、更新された状態を返します。メソッドは、圧縮機、燃焼室、タービン、ノズルの4つのコンポーネントでエンジンの状態を更新します。

simulateメソッドは、エンジンの状態を時間とともにシミュレートします。メソッドは、時間ステップ数、開始時間、終了時間の3つのパラメータを受け取り、状態のリスト(時系列)を返します。メソッドは、時間ステップごとに状態を更新し、リストに格納します。

main関数は、コードのエントリポイントです。関数はエンジンオブジェクトを作成して初期化し、状態をシミュレートし、状態をプロットします。

pressure配列は、エンジンの圧力の時系列です。temperature配列は、エンジンの温度の時系列です。time配列は、エンジンの時間の時系列です。

plt.plot関数は、圧力と温度の時系列をプロットします。
plt.show関数は、プロットを表示します。

詳細な数値シミュレーションを行うPythonコードを次に示します。

import numpy as np
import matplotlib.pyplot as plt

from scipy.integrate import odeint

class TurbofanEngine:

    def __init__(self,
                 mass_flow_rate=1.0,
                 pressure_ratio=10.0,
                 temperature_ratio=2.0,
                 efficiency=0.9):

        self.mass_flow_rate = mass_flow_rate
        self.pressure_ratio = pressure_ratio
        self.temperature_ratio = temperature_ratio
        self.efficiency = efficiency

    def _state_update(self, state, time):

        pressure = state[0]
        temperature = state[1]

        # 圧縮機
        pressure_compression = self.pressure_ratio * pressure
        temperature_compression = pressure_compression / self.temperature_ratio

        # 燃焼室
        temperature_combustion = temperature_compression * self.temperature_ratio

        # タービン
        pressure_turbine = temperature_combustion / self.temperature_ratio
        pressure = pressure_turbine / self.pressure_ratio

        # ノズル
        temperature_nozzle = temperature_combustion
        pressure_nozzle = pressure_turbine

        thrust = self.mass_flow_rate * (
            (pressure_nozzle - pressure) / 2.0 * (temperature_nozzle + temperature) ** 0.5
        )

        state_new = (pressure, temperature, thrust)

        return state_new

    def simulate(self, time_steps, time_start=0.0, time_end=1.0):

        states = []

        time = time_start
        state = (1.0, 298.0, 0.0)

        for _ in range(time_steps):

            states.append(state)

            state = self._state_update(state, time)

            time += (time_end - time_start) / time_steps

        return states

if __name__ == "__main__":

    engine = TurbofanEngine()

    time_steps = 1000
    time_start = 0.0
    time_end = 1.0

    states = engine.simulate(time_steps, time_start, time_end)

    pressure = np.array([state[0] for state in states])
    temperature = np.array([state[1] for state in states])
    thrust = np.array([state[2] for state in states])

    time = np.linspace(time_start, time_end, time_steps)

    plt.plot(time, pressure)
    plt.plot(time, temperature)
    plt.plot(time, thrust)

    plt.show()

このコードは、ターボファンエンジンの詳細な数値シミュレーションを行います。コードは、まずエンジンの状態を初期化します。次に、エンジンの状態を時間とともに更新し、状態を格納します。最後に、状態をプロットします。

最初のコードと比較して、このコードにはいくつかの追加の機能を備えています。

タービンの効率を考慮しています。
推力を計算しています。
圧力、温度、推力の時系列は、最初のコードよりも正確です。

コードの説明です。

TurbofanEngineクラスは、ターボファンエンジンを表します。クラスは、質量流量、圧縮比、温度比、タービン効率の4つのパラメータで初期化されます。

_state_updateメソッドは、エンジンの状態を更新します。メソッドは、現在の状態と時間を受け取り、更新された状態を返します。メソッドは、圧縮機、燃焼室、タービン、ノズルの4つのコンポーネントでエンジンの状態を更新します。

simulateメソッドは、エンジンの状態を時間とともにシミュレートします。メソッドは、時間ステップ数、開始時間、終了時間の3つのパラメータを受け取り、状態のリスト(時系列)を返します。メソッドは、時間ステップごとに状態を更新し、リストに格納します。

main関数は、コードのエントリポイントです。関数はエンジンオブジェクトを作成して初期化し、状態をシミュレートし、状態をプロットします。

pressure配列は、エンジンの圧力の時系列です。temperature配列は、エンジンの温度の時系列です。thrust配列は、エンジンの推力の時系列です。time配列は、エンジンの時間の時系列です。

plt.plot関数は、圧力、温度、推力の時系列をプロットします。

plt.show関数は、プロットを表示します。

追加の機能について詳しく説明します。

タービンの効率は、タービンで消費されるエネルギーの割合です。タービンの効率が低いほど、タービンの回転速度は遅くなり、エンジンの出力は低くなります。
推力は、エンジンによって生成される力です。推力は、エンジンから排出されるガスの速度とガスの質量によって決まります。ガスの速度が速いほど、推力は大きくなります。ガスの質量が多いほど、推力は大きくなります。

ターボファンエンジンの燃焼室をシミュレートするPythonコードを次に示します。

import math

def combustion_chamber(mass_flow_rate, fuel_mass_flow_rate, air_temperature, fuel_temperature, air_pressure, fuel_pressure):
  """ターボファンエンジンの燃焼室をシミュレートします。

  Args:
    mass_flow_rate: エンジンに流入する空気の質量流量(kg/s)。
    fuel_mass_flow_rate: エンジンに流入する燃料の質量流量(kg/s)。
    air_temperature: 空気の温度(K)。
    fuel_temperature: 燃料の温度(K)。
    air_pressure: 空気の圧力(Pa)。
    fuel_pressure: 燃料の圧力(Pa)。

  Returns:
    燃焼室の温度、圧力、速度。
  """

  # 空気の比熱比を計算します。
  γ = 1.4

  # 燃焼式を計算します。
  R = mass_flow_rate * (air_temperature / (γ - 1)) + fuel_mass_flow_rate * (fuel_temperature / (γ - 1))

  # 燃焼室の温度を計算します。
  T = (R / air_pressure) ** (1 / (γ - 1))

  # 燃焼室の圧力を計算します。
  P = R * T / (γ - 1)

  # 燃焼室の速度を計算します。
  v = sqrt(2 * R * T / (γ - 1))

  return T, P, v

def main():
  # エンジンの入力パラメータを定義します。
  mass_flow_rate = 1.0  # kg/s
  fuel_mass_flow_rate = 0.05  # kg/s
  air_temperature = 298.15  # K
  fuel_temperature = 300.0  # K
  air_pressure = 101325.0  # Pa
  fuel_pressure = 101325.0  # Pa

  # 燃焼室の温度、圧力、速度を計算します。
  T, P, v = combustion_chamber(mass_flow_rate, fuel_mass_flow_rate, air_temperature, fuel_temperature, air_pressure, fuel_pressure)

  # 結果を出力します。
  print("Temperature:", T)
  print("Pressure:", P)
  print("Velocity:", v)

if __name__ == "__main__":
  main()

コードの説明は次のとおりです。

def combustion_chamber(mass_flow_rate, fuel_mass_flow_rate, air_temperature, fuel_temperature, air_pressure, fuel_pressure):
"""ターボファンエンジンの燃焼室をシミュレートします。

Args:
mass_flow_rate: エンジンに流入する空気の質量流量(kg/s)。
fuel_mass_flow_rate: エンジンに流入する燃料の質量流量(kg/s)。
air_temperature: 空気の温度(K)。
fuel_temperature: 燃料の温度(K)。
air_pressure: 空気の圧力(Pa)。
fuel_pressure: 燃料の圧力(Pa)。

Returns:
燃焼室の温度、圧力、速度。
"""

空気の比熱比を計算します。
γ = 1.4

燃焼式を計算します。
R = mass_flow_rate * (air_temperature / (γ - 1)) + fuel_mass_flow_rate * (fuel_temperature / (γ - 1))

燃焼室の温度を計算します。
T = (R / air_pressure) ** (1 / (γ - 1))

燃焼室の圧力を計算します。
P = R * T / (γ - 1)

燃焼室の速度を計算します。
v = sqrt(2 * R * T / (γ - 1))

この関数は、ターボファンエンジンの燃焼室をシミュレートします。mass_flow_rate引数は、エンジンに流入する空気の質量流量で、単位はkg/sです。fuel_mass_flow_rate引数は、エンジンに流入する燃料の質量流量で、単位はkg/sです。air_temperature引数は、空気の温度で、単位はKです。fuel_temperature引数は、燃料の温度で、単位はKです。air_pressure引数は、空気の圧力で、単位はPaです。fuel_pressure引数は、燃料の圧力で、単位はPaです。関数は、燃焼室の温度、圧力、速度を返します。

エンジンの入力パラメータを定義します。
mass_flow_rate = 1.0 # kg/s
fuel_mass_flow_rate = 0.05 # kg/s
air_temperature = 298.15 # K
fuel_temperature = 300.0 # K
air_pressure = 101325.0 # Pa
fuel_pressure = 101325.0 # Pa

燃焼室の温度、圧力、速度を計算します。
T, P, v = combustion_chamber(mass_flow_rate, fuel_mass_flow_rate, air_temperature, fuel_temperature, air_pressure, fuel_pressure)
結果を出力します。
print("Temperature:", T)
print("Pressure:", P)
print("Velocity:", v)

タービンの数値シミュレーションを行う Python コードを次に示します。

import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint


def turbine_motion_equation(J, C, K, T):
  """タービンの運動方程式を計算します。

  Args:
    J: タービンの慣性モーメント
    C: タービンの摩擦係数
    K: タービンのばね定数
    T: タービンに作用するトルク

  Returns:
    タービンの角加速度
  """

  return -(C / J) * theta - (K / J) * theta + T
 

t_span = np.linspace(0, 10, 100)
y0 = np.array([0, 0])
y = odeint(turbine_motion_equation, y0, t_span)

# タービンの軌道をプロットします。
plt.plot(t_span, y[:, 0], label='x')
plt.plot(t_span, y[:, 1], label='y')
plt.legend()
plt.show()

タービンの軌道をプロットするには、次のコードを使用できます。
このコードは、2次元で運動するタービンの数値シミュレーションを行います。turbine_motion_equation(J, C, K, T)関数はタービンの運動方程式を定義し、odeint()関数は方程式を数値的に解きます。plot()関数はタービンの軌道をプロットします。

渦の吸い込みをプロットするPythonコードは次のとおりです。

import numpy as np
import matplotlib.pyplot as plt

# 渦の中心を定義する
x0 = 0
y0 = 0

# 計算領域を定義する
xmin = -10
xmax = 10
ymin = -10
ymax = 10

# 点のグリッドを作成する
x = np.linspace(xmin, xmax, 1000)
y = np.linspace(ymin, ymax, 1000)
X, Y = np.meshgrid(x, y)

# 流体方程式を解く
r = np.sqrt((X - x0)**2 + (Y - y0)**2)
u = -Y / r**2
v = X / r**2

# 流速場をプロットする
plt.figure()
plt.contourf(X, Y, u, levels=100)
plt.colorbar()
plt.xlabel('x')
plt.ylabel('y')
plt.title('流速場')
plt.show()

# 渦の吸い込みをプロットする
plt.figure()
plt.streamplot(X, Y, u, v)
plt.xlabel('x')
plt.ylabel('y')
plt.title('流線図')
plt.show()

image.png

image.png
螺旋のベクトル図をプロットするPythonコードは次のとおりです。

import numpy as np
import matplotlib.pyplot as plt

# 螺旋の中心を定義する
x0 = 0
y0 = 0

# 螺旋の半径を定義する
r = np.linspace(0.1, 2, 1000)

# 螺旋の角度を定義する
theta = np.linspace(0, 20 * np.pi, 1000)

# 螺旋のx座標とy座標を計算する
x = r * np.cos(theta) + x0
y = r * np.sin(theta) + y0

# 流速場を解く
u = -y / r**2
v = x / r**2

# 流速場をプロットする
plt.figure()
plt.plot(x, y)
plt.quiver(x, y, u, v, scale_units='width', scale=1)
plt.xlabel('x')
plt.ylabel('y')
plt.title('流速場')
plt.show()

image.png

おまけ  気象シミュレーションを行うPythonコードを次に示します。

import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint

class Atmosphere:
  """大気クラス。

  Args:
    temperature: 大気の温度(K)。
    pressure: 大気の圧力(Pa)。
    density: 大気の密度(kg/m^3)。
    gravity: 重力(m/s^2)。
  """

  def __init__(self, temperature, pressure, density, gravity):
    self.temperature = temperature
    self.pressure = pressure
    self.density = density
    self.gravity = gravity

  def __call__(self, height):
    """大気の状態方程式を解く。

    Args:
      height: 高度(m)。

    Returns:
      温度、圧力、密度。
    """

    T, P, ρ = self.temperature, self.pressure, self.density
    dT = -g / R * ρ *  / dT
    dP = -g / R * ρ *  / dP
     = -g / R * dT / T
    return T + dT, P + dP, ρ + 

def main():
  # 大気の状態を定義します。
  temperature = 298.15  # K
  pressure = 101325.0  # Pa
  density = 1.225  # kg/m^3
  gravity = 9.80665  # m/s^2
  atmosphere = Atmosphere(temperature, pressure, density, gravity)

  # 時間ステップを定義します。
  dt = 0.01  # s

  # 高度を定義します。
  height = np.arange(0, 100000, dt)

  # 状態方程式を解きます。
  T, P, ρ = odeint(atmosphere, (temperature, pressure, density), height)

  # 結果をプロットします。
  plt.plot(height, T, label="Temperature")
  plt.plot(height, P, label="Pressure")
  plt.plot(height, ρ, label="Density")
  plt.xlabel("Height (m)")
  plt.ylabel("Temperature (K), Pressure (Pa), Density (kg/m^3)")
  plt.legend()
  plt.show()

if __name__ == "__main__":
  main()

このコードは大気の状態方程式を解き、高度に応じた温度、圧力、密度を計算します。このコードは、気象現象をシミュレートするために使用できます。

コードの説明は次のとおりです。

from scipy.integrate import odeint
scipy.integrateは微分方程式を解くためのモジュールです。

class Atmosphere:
"""大気クラス。

Args:
temperature: 大気の温度(K)。
pressure: 大気の圧力(Pa)。
density: 大気の密度(kg/m^3)。
gravity: 重力(m/s^2)。
"""

def call(self, height):
"""大気の状態方程式を解く。

Args:
  height: 高度(m)。

Returns:
  温度、圧力、密度。
"""

T, P, ρ = self.temperature, self.pressure, self.density
dT = -g / R * ρ * dρ / dT
dP = -g / R * ρ * dρ / dP
dρ = -g / R * dT / T
return T + dT, P + dP, ρ + dρ

このクラスは、大気をモデル化するために使用されます。temperature、pressure、density、およびgravity属性を使用して、大気の初期状態を定義できます。call()メソッドを使用して、高度に応じた温度、圧力、密度を計算できます。

def main():
大気の状態を定義します。
temperature = 298.15 # K
pressure = 101325.0 # Pa
density = 1.225 # kg/m^3
gravity = 9.80665 # m/s^2
atmosphere = Atmosphere(temperature, pressure, density, gravity)

時間ステップを定義します。
dt = 0.01 # s

高度を定義します。
height = np.arange(0, 100000, dt)

状態方程式を解きます。
T, P, ρ = odeint(atmosphere, (temperature, pressure, density), height)

結果をプロットします。

最初に、大気の状態を定義します。次に、時間ステップを定義します。次に、高度を定義します。次に、状態方程式を解き、高度に応じた温度、圧力、密度を計算します。最後に、結果をプロットします。

大気の状態方程式は、次の式です。

P=ρRT

ここで、

P は圧力
ρ は密度
R は気体定数
T は温度
大気の状態方程式を解くには、密度 ρ を圧力 P と温度 T で表す必要があります。これを行うには、両辺を RT で割ることができます。これにより、次の式が得られます。
したがって、密度は圧力と温度の比に等しくなります。

大気の状態方程式は、大気の圧力、密度、温度の関係を説明するために使用できる重要な方程式です。大気の挙動を理解するために使用できる他の多くの方程式とともに、気象学で使用される基本的な方程式です。

最初の問いの答え >>> できませんでした。

0
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2