지난 포스팅 https://studyingrabbit.tistory.com/53
수치 미분 방정식 풀이법과 이를 이용한 고전 역학 문제 해결 : 오일러 방법(Euler method)을 이용하
미분 방정식을 푸는 방법에 대한 포스팅이랑 수학의 내용을 다루지만, 이 방법을 이용하여 물리 문제를 푸는 것이 포스팅의 목적이기 때문에 이 글의 카테고리를 <물리학>으로 택했습니다. 물리
studyingrabbit.tistory.com
에서 미분 방정식을 수치 해법으로 풀 수 있는 가장 간단한 방법인 오일러 방법에 대해서 알아 봤습니다. 간단히 복습을 하면 오일러 방법은
(1) 시간을 기본 단위
(2) 미분값을 근사적으로 계산
(3) 위
와 같은 방법으로 미분 방정식을 풀게 됩니다. 개념적으로나, 컴퓨터 프로그래밍적으로나 매우 간단한 방법입니다. 하지만,
따라서, 실제 응용을 위해서는 오일러 방법보다 효율적인 방법을 이용해야 합니다. 즉, 계산 시간(량)은 오일러 방법과 유사하면서 계산의 정확도는 훨씬 높은 방법을 이용해야 합니다. 이러 방법 중 대표적인 방법이 바로 이번 포스팅에서 알아볼 룽게-쿠타 방법 (Runge-Kutta method) 입니다.
초기값이 주어진 미분 방정식
를 룽게-쿠타 방법으로 풀어 보도록 하겠습니다. 우선, 구간
오일러 방법에서는
룽게-쿠타 방법 역시 당연히 근사적인 방법이기 때문에 해석적인 방법과 비교하여 에러가 존재하는데, 한 시간 단위
에러의 크기를
실제 문제를 룽게-쿠타 방법으로 풀어 보자.
실제 문제를 오일러 방법과 룽게-쿠타 방법으로 구하고 두 결과의 차이를 비교해 보도록 하겠습니다. 역시 가장 간단한 문제는 고전 역학의 단조화 진동자 문제 입니다. 모든 물리 상수를
이 됩니다. 초기 위치는

결과는 위 그래프와 같습니다. 시간 구간
붉은색으로 표시한 그래프가 해석적인 해

해석적인 해와의 차이를 그리면 위 그래프와 같습니다. 룽게-쿠타 방법으로 푼 경우, 위 구간에서 에러의 최대값은

위 그래프는 오일러 방법에 사용한
위 계산을 하기 위해 생성한 파이썬 코드 입니다. 파이썬 프로그래밍을 할 수 있다면, 다양한 형태의 힘에 대해서 시뮬레이션을 해 볼 수 있습니다.
import numpy as np
from matplotlib import pyplot as plt
def force(t, x, v):
"""
가속도 정의. 모듈의 이름은 force이지만, 사실은 가속도
"""
return -x
def velocity(t, x, v):
"""
속도는 단순한 속도
"""
return v
def rungekutta_method(x0, v0, t0, t1, N):
"""
x0 : 초기 위치
v0 : 초기 속도
t0 : 초기 시각
t1 : 최종 시각
N : t0-t1 구간을 N 조각으로 불연속화
"""
xs, vs, ts= [x0], [v0], np.linspace(t0, t1, N)
h = (t1 - t0) / N
for i in range(1, N):
t = t0 + h*(i-1)
"""
룽게-쿠타 법칙에 따라서 k1, k2, k3, k4를 x, v에 대해서 계산
위치(x)와 속도(v)를 동시에 계산
"""
k1x = velocity(t, x0, v0)
k1v = force(t, x0, v0)
k2x = velocity(t+h/2, x0+h*k1x/2, v0+h*k1v/2)
k2v = force(t+h/2, x0+h*k1x/2, v0+h*k1v/2)
k3x = velocity(t+h/2, x0+h*k2x/2, v0+h*k2v/2)
k3v = force(t+h/2, x0+h*k2x/2, v0+h*k2v/2)
k4x = velocity(t+h, x0+h*k3x, v0+h*k3v)
k4v = force(t+h, x0+h*k3x, v0+h*k3v)
"""
룽게-쿠타 법칙에 따라서 x, v 를 업데이트
"""
x1 = x0 + h*(k1x + 2*k2x + 2*k3x + k4x)/6
v1 = v0 + h*(k1v + 2*k2v + 2*k3v + k4v)/6
xs.append(x1)
vs.append(v1)
x0 = x1
v0 = v1
return ts, xs, vs
def harmonic_oscillator():
"""
계산할 조건 입력
"""
t0, t1 = 0, 5*(2*np.pi)
x0, v0 = 0, 1
N = 1000
"""
룽게-쿠타 방법을 이용하여 미분 방정식 계산
"""
T, X, V = rungekutta_method(x0, v0, t0, t1, N)
"""
matplotlib 라이브러리를 이용하여 (t, x) 그래프를 생성
"""
plt.plot(T, X, lw = 2, color = "green", label = "Runge-Kutta")
plt.xlabel("Time")
plt.ylabel("y(t)")
plt.grid()
plt.show()
plt.close('all')
if __name__ == '__main__':
harmonic_oscillator()
'물리학' 카테고리의 다른 글
슈뢰딩거 방정식을 수치 해법으로 풀기 (2): 단조화 진동자 문제 풀기, 고유값이 아닌 에너지 값에 대응되는 파동 함수의 개형은? (0) | 2021.10.17 |
---|---|
슈뢰딩거 방정식을 수치 해법으로 풀기 (1): 슈팅 방법으로 알아보는 고유값 문제, 무한 포텐셜 우물 문제 풀기 (0) | 2021.10.16 |
수치 미분 방정식 풀이법을 이용하여 최종값 조건이 주어진 문제 풀기 : 슈팅 방법 (0) | 2021.10.15 |
수치 미분 방정식 풀이법과 이를 이용한 고전 역학 문제 해결 : 오일러 방법(Euler method)을 이용하여 조화 진동자 문제 풀기 (1) | 2021.10.12 |
대칭성을 이용한 2차원 단조화 진동자 문제 풀이 (0) | 2021.09.13 |