ODE ๊ณ ๊ธ
ODE ๊ณ ๊ธ¶
๊ฐ์¶
๊ฐ์ฑ(stiff) ๋ฌธ์ , ์์์ ๋ฐฉ๋ฒ, scipy.integrate์ ๊ณ ๊ธ ์ฌ์ฉ๋ฒ์ ํ์ตํฉ๋๋ค. ์ค์ ์์ฉ์์ ์์ฃผ ๋ฑ์ฅํ๋ ์ด๋ ค์ด ODE ๋ฌธ์ ๋ค์ ๋ค๋ฃน๋๋ค.
1. ๊ฐ์ฑ ๋ฌธ์ (Stiff Problems)¶
1.1 ๊ฐ์ฑ์ ์ ์¶
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import solve_ivp
"""
๊ฐ์ฑ ๋ฌธ์ ์ ํน์ง:
1. ํด์ ์ฑ๋ถ๋ค์ด ๋งค์ฐ ๋ค๋ฅธ ์๊ฐ ์ค์ผ์ผ์ ๊ฐ์ง
2. ์ผ๋ถ ์ฑ๋ถ์ ๋น ๋ฅด๊ฒ ๊ฐ์ ํ๊ณ , ๋ค๋ฅธ ์ฑ๋ถ์ ๋๋ฆฌ๊ฒ ๋ณํ
3. ๋ช
์์ ๋ฐฉ๋ฒ ์ฌ์ฉ ์ ์์ ์ฑ์ ์ํด ๋งค์ฐ ์์ ์คํ
ํ์
"""
def stiff_example():
"""๊ฐ์ฑ ์์คํ
์์"""
# dyโ/dt = -500*yโ + 500*yโ
# dyโ/dt = yโ - yโ
#
# ๊ณ ์ ๊ฐ: ฮปโ โ -500.002, ฮปโ โ -0.998
# ๋น์จ: |ฮปโ/ฮปโ| โ 500 (๊ฐ์ฑ๋น)
def stiff_system(t, y):
return [-500*y[0] + 500*y[1], y[0] - y[1]]
y0 = [1.0, 0.0]
t_span = (0, 5)
# ๋ช
์์ RK45 (๋ง์ ์คํ
ํ์)
sol_rk45 = solve_ivp(stiff_system, t_span, y0, method='RK45',
rtol=1e-6, atol=1e-9)
# ์์์ Radau (์ ์ ์คํ
)
sol_radau = solve_ivp(stiff_system, t_span, y0, method='Radau',
rtol=1e-6, atol=1e-9)
print(f"RK45 ์คํ
์: {len(sol_rk45.t)}")
print(f"Radau ์คํ
์: {len(sol_radau.t)}")
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
axes[0].semilogy(sol_rk45.t, np.abs(sol_rk45.y[0]), 'b-', label='yโ')
axes[0].semilogy(sol_rk45.t, np.abs(sol_rk45.y[1]), 'r-', label='yโ')
axes[0].set_xlabel('t')
axes[0].set_ylabel('|y|')
axes[0].set_title(f'RK45 ({len(sol_rk45.t)} ์คํ
)')
axes[0].legend()
axes[0].grid(True)
axes[1].semilogy(sol_radau.t, np.abs(sol_radau.y[0]), 'b-', label='yโ')
axes[1].semilogy(sol_radau.t, np.abs(sol_radau.y[1]), 'r-', label='yโ')
axes[1].set_xlabel('t')
axes[1].set_ylabel('|y|')
axes[1].set_title(f'Radau ({len(sol_radau.t)} ์คํ
)')
axes[1].legend()
axes[1].grid(True)
plt.tight_layout()
plt.show()
stiff_example()
1.2 ํํ ๋ฐ์ ๋์ญํ¶
def chemical_kinetics():
"""๊ฐ์ฑ ํํ ๋ฐ์ ์์คํ
(Robertson ๋ฌธ์ )"""
# A โ B (kโ = 0.04)
# B + B โ C + B (kโ = 3e7)
# B + C โ A + C (kโ = 1e4)
k1, k2, k3 = 0.04, 3e7, 1e4
def robertson(t, y):
A, B, C = y
dA = -k1*A + k3*B*C
dB = k1*A - k2*B*B - k3*B*C
dC = k2*B*B
return [dA, dB, dC]
y0 = [1.0, 0.0, 0.0]
t_span = (0, 1e7)
t_eval = np.logspace(-5, 7, 200)
# BDF ๋ฐฉ๋ฒ (๊ฐ์ฑ ๋ฌธ์ ์ ์ ํฉ)
sol = solve_ivp(robertson, t_span, y0, method='BDF',
t_eval=t_eval, rtol=1e-8, atol=1e-10)
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# ์ ํ ์ค์ผ์ผ
axes[0].semilogx(sol.t, sol.y[0], label='A')
axes[0].semilogx(sol.t, sol.y[2], label='C')
axes[0].set_xlabel('t')
axes[0].set_ylabel('๋๋')
axes[0].set_title('Robertson ํํ ๋ฐ์ (A, C)')
axes[0].legend()
axes[0].grid(True)
# B๋ ๋งค์ฐ ์์ ๊ฐ์ด๋ฏ๋ก ๋ณ๋ ํ์
axes[1].semilogx(sol.t, sol.y[1] * 1e4, label='B ร 10โด')
axes[1].set_xlabel('t')
axes[1].set_ylabel('๋๋ ร 10โด')
axes[1].set_title('Robertson ํํ ๋ฐ์ (B)')
axes[1].legend()
axes[1].grid(True)
plt.tight_layout()
plt.show()
chemical_kinetics()
2. ์์์ ๋ฐฉ๋ฒ¶
2.1 ํ์ง ์ค์ผ๋ฌ (๋ค์ ๋ณด๊ธฐ)¶
def backward_euler_system(f, jacobian, y0, t_span, n_steps, tol=1e-10):
"""
์์คํ
์ ๋ํ ํ์ง ์ค์ผ๋ฌ + ๋ดํด-๋ฉ์จ
y_{n+1} = y_n + h * f(t_{n+1}, y_{n+1})
"""
t = np.linspace(t_span[0], t_span[1], n_steps + 1)
h = t[1] - t[0]
n = len(y0)
y = np.zeros((n_steps + 1, n))
y[0] = y0
for i in range(n_steps):
y_guess = y[i].copy()
for _ in range(100):
F = y_guess - y[i] - h * np.array(f(t[i+1], y_guess))
J = np.eye(n) - h * np.array(jacobian(t[i+1], y_guess))
delta = np.linalg.solve(J, -F)
y_guess = y_guess + delta
if np.linalg.norm(delta) < tol:
break
y[i+1] = y_guess
return t, y
# ํ
์คํธ: ๊ฐ์ฑ ์์คํ
def stiff_f(t, y):
return [-500*y[0] + 500*y[1], y[0] - y[1]]
def stiff_jacobian(t, y):
return [[-500, 500], [1, -1]]
t, y = backward_euler_system(stiff_f, stiff_jacobian, [1.0, 0.0], (0, 1), 50)
plt.figure(figsize=(10, 5))
plt.plot(t, y[:, 0], 'b-o', label='yโ')
plt.plot(t, y[:, 1], 'r-o', label='yโ')
plt.xlabel('t')
plt.ylabel('y')
plt.title('ํ์ง ์ค์ผ๋ฌ (50 ์คํ
)')
plt.legend()
plt.grid(True)
plt.show()
2.2 Crank-Nicolson ๋ฐฉ๋ฒ¶
def crank_nicolson(f, jacobian, y0, t_span, n_steps, tol=1e-10):
"""
Crank-Nicolson (ํธ๋ํผ์กฐ์ด๋ฌ ๊ท์น)
y_{n+1} = y_n + h/2 * (f(t_n, y_n) + f(t_{n+1}, y_{n+1}))
2์ฐจ ์ ํ๋, A-์์
"""
t = np.linspace(t_span[0], t_span[1], n_steps + 1)
h = t[1] - t[0]
n = len(y0)
y = np.zeros((n_steps + 1, n))
y[0] = y0
for i in range(n_steps):
f_n = np.array(f(t[i], y[i]))
y_guess = y[i] + h * f_n # ์ด๊ธฐ ์ถ์ธก (์ ์ง ์ค์ผ๋ฌ)
for _ in range(100):
f_new = np.array(f(t[i+1], y_guess))
F = y_guess - y[i] - h/2 * (f_n + f_new)
J = np.eye(n) - h/2 * np.array(jacobian(t[i+1], y_guess))
delta = np.linalg.solve(J, -F)
y_guess = y_guess + delta
if np.linalg.norm(delta) < tol:
break
y[i+1] = y_guess
return t, y
# ๋น๊ต
t_be, y_be = backward_euler_system(stiff_f, stiff_jacobian, [1.0, 0.0], (0, 1), 20)
t_cn, y_cn = crank_nicolson(stiff_f, stiff_jacobian, [1.0, 0.0], (0, 1), 20)
# ์ฐธ์กฐ ํด
sol_ref = solve_ivp(stiff_f, (0, 1), [1.0, 0.0], method='Radau',
t_eval=np.linspace(0, 1, 200))
plt.figure(figsize=(10, 5))
plt.plot(sol_ref.t, sol_ref.y[0], 'k-', linewidth=2, label='์ฐธ์กฐ')
plt.plot(t_be, y_be[:, 0], 'bo-', label='ํ์ง ์ค์ผ๋ฌ')
plt.plot(t_cn, y_cn[:, 0], 'rs-', label='Crank-Nicolson')
plt.xlabel('t')
plt.ylabel('yโ')
plt.title('์์์ ๋ฐฉ๋ฒ ๋น๊ต')
plt.legend()
plt.grid(True)
plt.show()
2.3 BDF ๋ฐฉ๋ฒ¶
"""
BDF (Backward Differentiation Formula) ๋ฐฉ๋ฒ
BDF1 (ํ์ง ์ค์ผ๋ฌ):
y_{n+1} - y_n = h * f(t_{n+1}, y_{n+1})
BDF2:
(3y_{n+1} - 4y_n + y_{n-1}) / 2 = h * f(t_{n+1}, y_{n+1})
BDF3:
(11y_{n+1} - 18y_n + 9y_{n-1} - 2y_{n-2}) / 6 = h * f(t_{n+1}, y_{n+1})
ํน์ง:
- A-์์ (BDF1, BDF2)
- ๊ฐ์ฑ ๋ฌธ์ ์ ํจ๊ณผ์
- scipy์ 'BDF' ์๋ฒ๊ฐ ๊ฐ๋ณ ์ฐจ์ BDF ๊ตฌํ
"""
def bdf2_solver(f, jacobian, y0, t_span, n_steps, tol=1e-10):
"""BDF2 ๋ฐฉ๋ฒ"""
t = np.linspace(t_span[0], t_span[1], n_steps + 1)
h = t[1] - t[0]
n = len(y0)
y = np.zeros((n_steps + 1, n))
y[0] = y0
# ์ฒซ ์คํ
์ ํ์ง ์ค์ผ๋ฌ๋ก
y_guess = y[0].copy()
for _ in range(100):
F = y_guess - y[0] - h * np.array(f(t[1], y_guess))
J = np.eye(n) - h * np.array(jacobian(t[1], y_guess))
delta = np.linalg.solve(J, -F)
y_guess = y_guess + delta
if np.linalg.norm(delta) < tol:
break
y[1] = y_guess
# ์ดํ BDF2
for i in range(1, n_steps):
y_guess = y[i].copy()
for _ in range(100):
f_new = np.array(f(t[i+1], y_guess))
# BDF2: (3y_{n+1} - 4y_n + y_{n-1})/2 = h*f(t_{n+1}, y_{n+1})
F = 1.5*y_guess - 2*y[i] + 0.5*y[i-1] - h * f_new
J = 1.5*np.eye(n) - h * np.array(jacobian(t[i+1], y_guess))
delta = np.linalg.solve(J, -F)
y_guess = y_guess + delta
if np.linalg.norm(delta) < tol:
break
y[i+1] = y_guess
return t, y
t_bdf2, y_bdf2 = bdf2_solver(stiff_f, stiff_jacobian, [1.0, 0.0], (0, 1), 20)
plt.figure(figsize=(10, 5))
plt.plot(sol_ref.t, sol_ref.y[0], 'k-', linewidth=2, label='์ฐธ์กฐ')
plt.plot(t_bdf2, y_bdf2[:, 0], 'go-', label='BDF2')
plt.xlabel('t')
plt.ylabel('yโ')
plt.title('BDF2 ๋ฐฉ๋ฒ')
plt.legend()
plt.grid(True)
plt.show()
3. scipy.integrate ๊ณ ๊ธ¶
3.1 ์ผ์ฝ๋น์ ์ ๊ณต¶
def with_jacobian():
"""์ผ์ฝ๋น์์ ์ ๊ณตํ๋ฉด ์ฑ๋ฅ ํฅ์"""
def system(t, y):
return [
-100*y[0] + y[1],
y[0] - 100*y[1] + y[2],
y[1] - 100*y[2]
]
def jacobian(t, y):
return [
[-100, 1, 0],
[1, -100, 1],
[0, 1, -100]
]
y0 = [1.0, 0.0, 0.0]
t_span = (0, 0.5)
import time
# ์ผ์ฝ๋น์ ์์ด
start = time.time()
sol1 = solve_ivp(system, t_span, y0, method='Radau')
time1 = time.time() - start
# ์ผ์ฝ๋น์ ์ ๊ณต
start = time.time()
sol2 = solve_ivp(system, t_span, y0, method='Radau', jac=jacobian)
time2 = time.time() - start
print(f"์ผ์ฝ๋น์ ์์ด: {time1:.4f}์ด, {len(sol1.t)} ์คํ
")
print(f"์ผ์ฝ๋น์ ์ ๊ณต: {time2:.4f}์ด, {len(sol2.t)} ์คํ
")
with_jacobian()
3.2 Dense Output¶
def dense_output_example():
"""Dense output์ผ๋ก ์ฐ์์ ์ธ ํด ์ป๊ธฐ"""
def oscillator(t, y):
return [y[1], -y[0]]
sol = solve_ivp(oscillator, (0, 10), [1, 0],
method='RK45', dense_output=True)
# ์์์ ์๊ฐ์์ ํด ํ๊ฐ
t_dense = np.linspace(0, 10, 1000)
y_dense = sol.sol(t_dense)
plt.figure(figsize=(10, 5))
plt.plot(t_dense, y_dense[0], 'b-', label='Dense output')
plt.plot(sol.t, sol.y[0], 'ro', markersize=5, label='์๋ฒ ์คํ
')
plt.xlabel('t')
plt.ylabel('y')
plt.title('Dense Output')
plt.legend()
plt.grid(True)
plt.show()
dense_output_example()
3.3 ์ง๋ ํ๋ ฌ (DAE)¶
def dae_example():
"""
๋ฏธ๋ถ-๋์ ๋ฐฉ์ ์ (DAE)
M * y' = f(t, y)
์ฌ๊ธฐ์ M์ด ํน์ด ํ๋ ฌ์ด๋ฉด ๋์ ๊ตฌ์์กฐ๊ฑด ํฌํจ
"""
# ์: ๋จ์ง์ (์ ์ฝ์กฐ๊ฑด: xยฒ + yยฒ = Lยฒ)
# x'' = ฮปx
# y'' = ฮปy - g
# xยฒ + yยฒ = Lยฒ
# ์ธ๋ฑ์ค-1 ํํ๋ก ๋ณํ
g = 9.8
L = 1.0
def pendulum(t, y):
x, y_pos, vx, vy, lam = y
# ๊ฐ์๋
ax = lam * x
ay = lam * y_pos - g
# ๊ตฌ์์กฐ๊ฑด (ฮป ๊ฒฐ์ )
# ์ฌ์ค ์ด๊ฑด ๋ ๋ณต์กํ ์ฒ๋ฆฌ๊ฐ ํ์...
# ๊ฐ๋จํ ์์๋ง ๋ณด์ฌ์ค
return [vx, vy, ax, ay, 0]
# scipy์์๋ mass_matrix ์ต์
์ผ๋ก DAE ํ ์ ์์ (Radau)
# ์ฌ๊ธฐ์๋ ๊ฐ๋
๋ง ์ค๋ช
print("DAE๋ scipy.integrate.solve_ivp์ Radau ์๋ฒ์")
print("mass_matrix ์ต์
์ผ๋ก ํ ์ ์์ต๋๋ค.")
dae_example()
4. ๊ฒฝ๊ณ๊ฐ ๋ฌธ์ (BVP)¶
4.1 ์ํ ๋ฐฉ๋ฒ¶
from scipy.optimize import brentq
def shooting_method():
"""
์ํ
๋ฐฉ๋ฒ์ผ๋ก BVP ํ๊ธฐ
y'' = -y, y(0) = 0, y(ฯ) = 0
์ ํํด: y = sin(x)
"""
def ode(t, y):
return [y[1], -y[0]]
def shoot(initial_slope):
"""์ฃผ์ด์ง ์ด๊ธฐ ๊ธฐ์ธ๊ธฐ๋ก IVP ํ๊ธฐ"""
sol = solve_ivp(ode, (0, np.pi), [0, initial_slope],
dense_output=True)
return sol.sol(np.pi)[0] # y(ฯ) ๋ฐํ
# ์ฌ๋ฐ๋ฅธ ์ด๊ธฐ ๊ธฐ์ธ๊ธฐ ์ฐพ๊ธฐ
slope = brentq(shoot, 0.5, 1.5)
print(f"์ฐพ์ ์ด๊ธฐ ๊ธฐ์ธ๊ธฐ: {slope:.6f} (์ ํ๊ฐ: 1.0)")
# ์ต์ข
ํด
sol = solve_ivp(ode, (0, np.pi), [0, slope], dense_output=True)
t = np.linspace(0, np.pi, 100)
plt.figure(figsize=(10, 5))
plt.plot(t, sol.sol(t)[0], 'b-', label='์์นํด')
plt.plot(t, np.sin(t), 'r--', label='์ ํํด sin(x)')
plt.xlabel('x')
plt.ylabel('y')
plt.title('์ํ
๋ฐฉ๋ฒ')
plt.legend()
plt.grid(True)
plt.show()
shooting_method()
4.2 scipy.integrate.solve_bvp¶
from scipy.integrate import solve_bvp
def bvp_example():
"""
y'' + y = 0, y(0) = 0, y(ฯ) = 0
1์ฐจ ์์คํ
์ผ๋ก ๋ณํ:
yโ' = yโ
yโ' = -yโ
"""
def ode(x, y):
return np.vstack([y[1], -y[0]])
def bc(ya, yb):
return np.array([ya[0], yb[0]]) # y(0) = 0, y(ฯ) = 0
# ์ด๊ธฐ ์ถ์ธก
x = np.linspace(0, np.pi, 10)
y = np.zeros((2, x.size))
y[0] = np.sin(x) # ์ด๊ธฐ ์ถ์ธก
sol = solve_bvp(ode, bc, x, y)
x_plot = np.linspace(0, np.pi, 100)
y_plot = sol.sol(x_plot)
plt.figure(figsize=(10, 5))
plt.plot(x_plot, y_plot[0], 'b-', label='์์นํด')
plt.plot(x_plot, np.sin(x_plot), 'r--', label='์ ํํด')
plt.xlabel('x')
plt.ylabel('y')
plt.title('solve_bvp')
plt.legend()
plt.grid(True)
plt.show()
bvp_example()
4.3 ๋น์ ํ BVP¶
def nonlinear_bvp():
"""
๋น์ ํ BVP: y'' = yยฒ - 1
y(0) = 0, y(1) = 1
"""
def ode(x, y):
return np.vstack([y[1], y[0]**2 - 1])
def bc(ya, yb):
return np.array([ya[0], yb[0] - 1])
x = np.linspace(0, 1, 10)
y = np.zeros((2, x.size))
y[0] = x # ์ ํ ์ด๊ธฐ ์ถ์ธก
sol = solve_bvp(ode, bc, x, y)
if sol.success:
x_plot = np.linspace(0, 1, 100)
y_plot = sol.sol(x_plot)
plt.figure(figsize=(10, 5))
plt.plot(x_plot, y_plot[0], 'b-', linewidth=2)
plt.scatter([0, 1], [0, 1], color='red', s=100, zorder=5)
plt.xlabel('x')
plt.ylabel('y')
plt.title("๋น์ ํ BVP: y'' = yยฒ - 1")
plt.grid(True)
plt.show()
else:
print("์๋ ด ์คํจ")
nonlinear_bvp()
5. ํน์ ๋ฌธ์ ¶
5.1 ์ฃผ๊ธฐ ๊ถค๋ ์ฐพ๊ธฐ¶
def find_periodic_orbit():
"""Van der Pol ์ง๋์์ ์ฃผ๊ธฐ ๊ถค๋"""
mu = 1.0
def vdp(t, y):
return [y[1], mu * (1 - y[0]**2) * y[1] - y[0]]
# ํฌ์์นด๋ ๋จ๋ฉด
def poincare(t, y):
return y[1] # y' = 0์ผ ๋
poincare.direction = -1 # ์์์ ์๋๋ก ๊ต์ฐจ
# ์ถฉ๋ถํ ๊ธด ์๊ฐ ์ ๋ถ
sol = solve_ivp(vdp, (0, 100), [2, 0], events=poincare,
dense_output=True, max_step=0.01)
# ๋ฆฌ๋ฐ ์ฌ์ดํด์ ์๋ ด ํ์ ๊ต์ฐจ์ ๋ค
crossings = sol.y_events[0][-5:, 0] # ๋ง์ง๋ง 5๊ฐ ๊ต์ฐจ์ ์ x ๊ฐ
print(f"๋ฆฌ๋ฐ ์ฌ์ดํด ์งํญ: {np.mean(crossings):.6f}")
# ๋ง์ง๋ง ์ฃผ๊ธฐ ์๊ฐํ
t_last = sol.t_events[0][-2:]
period = t_last[1] - t_last[0]
print(f"์ฃผ๊ธฐ: {period:.6f}")
t_plot = np.linspace(t_last[0], t_last[1], 200)
y_plot = sol.sol(t_plot)
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
axes[0].plot(y_plot[0], y_plot[1])
axes[0].set_xlabel('x')
axes[0].set_ylabel("x'")
axes[0].set_title('๋ฆฌ๋ฐ ์ฌ์ดํด')
axes[0].grid(True)
axes[1].plot(t_plot - t_last[0], y_plot[0])
axes[1].set_xlabel('t (์ฃผ๊ธฐ ๋ด)')
axes[1].set_ylabel('x')
axes[1].set_title(f'ํ ์ฃผ๊ธฐ (T = {period:.4f})')
axes[1].grid(True)
plt.tight_layout()
plt.show()
find_periodic_orbit()
5.2 ๋ถ๊ธฐ ๋ถ์¶
def bifurcation_analysis():
"""ํ๋ผ๋ฏธํฐ์ ๋ฐ๋ฅธ ์ ์ ์ํ ๋ณํ"""
# dy/dt = r*y - yยณ
# ํํ์ : y* = 0 ๋๋ y* = ยฑโr (r > 0)
r_values = np.linspace(-1, 2, 100)
plt.figure(figsize=(10, 6))
# ์์ ๋ถ๊ธฐ
r_pos = r_values[r_values >= 0]
plt.plot(r_pos, np.sqrt(r_pos), 'b-', linewidth=2, label='์์ ')
plt.plot(r_pos, -np.sqrt(r_pos), 'b-', linewidth=2)
# ๋ถ์์ ๋ถ๊ธฐ
plt.plot(r_values[r_values <= 0], np.zeros_like(r_values[r_values <= 0]),
'r--', linewidth=2, label='๋ถ์์ ')
plt.plot(r_values[r_values > 0], np.zeros_like(r_values[r_values > 0]),
'r--', linewidth=2)
plt.xlabel('r')
plt.ylabel('y*')
plt.title("ํผ์นํฌํฌ ๋ถ๊ธฐ: y' = ry - yยณ")
plt.legend()
plt.grid(True)
plt.axhline(y=0, color='k', linewidth=0.5)
plt.axvline(x=0, color='k', linewidth=0.5)
plt.show()
bifurcation_analysis()
์ฐ์ต ๋ฌธ์ ¶
๋ฌธ์ 1¶
๋ค์ ๊ฐ์ฑ ์์คํ ์ BDF์ Radau๋ก ํ๊ณ ๋น๊ตํ์ธ์: dyโ/dt = -1000yโ + yโ dyโ/dt = 999yโ - 2*yโ yโ(0) = 1, yโ(0) = 0
def exercise_1():
def system(t, y):
return [-1000*y[0] + y[1], 999*y[0] - 2*y[1]]
y0 = [1.0, 0.0]
t_span = (0, 1)
sol_bdf = solve_ivp(system, t_span, y0, method='BDF',
t_eval=np.linspace(0, 1, 100))
sol_radau = solve_ivp(system, t_span, y0, method='Radau',
t_eval=np.linspace(0, 1, 100))
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
axes[0].semilogy(sol_bdf.t, np.abs(sol_bdf.y[0]), label='yโ')
axes[0].semilogy(sol_bdf.t, np.abs(sol_bdf.y[1]), label='yโ')
axes[0].set_title('BDF')
axes[0].legend()
axes[0].grid(True)
axes[1].semilogy(sol_radau.t, np.abs(sol_radau.y[0]), label='yโ')
axes[1].semilogy(sol_radau.t, np.abs(sol_radau.y[1]), label='yโ')
axes[1].set_title('Radau')
axes[1].legend()
axes[1].grid(True)
plt.tight_layout()
plt.show()
exercise_1()
์์ฝ¶
| ๋ฌธ์ ์ ํ | ๊ถ์ฅ ์๋ฒ | ํน์ง |
|---|---|---|
| ์ผ๋ฐ ๋น๊ฐ์ฑ | RK45, DOP853 | ๋ช ์์ , ๋น ๋ฆ |
| ๊ฐ์ฑ ๋ฌธ์ | Radau, BDF | ์์์ , ์์ |
| DAE | Radau + mass_matrix | ๋์ ๊ตฌ์์กฐ๊ฑด |
| BVP | solve_bvp, ์ํ | ๊ฒฝ๊ณ์กฐ๊ฑด |
| ์์์ ๋ฐฉ๋ฒ | ์ฐจ์ | A-์์ |
|---|---|---|
| ํ์ง ์ค์ผ๋ฌ | 1 | O |
| Crank-Nicolson | 2 | O |
| BDF1-2 | 1-2 | O |
| BDF3-6 | 3-6 | X |