1계 선형 미분방정식 문서의 검증 코드다.

"""1계 선형 미분방정식 문서의 풀이를 검증한다. 해를 식에 넣어 양변을 비교하고, RC 회로는 오일러 방법과 비교한다."""
import math

h = 1e-5
d = lambda f, x: (f(x + h) - f(x - h)) / (2 * h)
xs = [-1.0, -0.3, 0.0, 0.7, 1.5, 2.2]

def check(name, y, lhs, rhs):
    for x in xs:
        assert abs(lhs(y, x) - rhs(x)) < 1e-5, (name, x, lhs(y, x), rhs(x))

for C in (-2.0, 0.0, 1.3):
    # 변수분리형 y' = y^2 e^{-x}  ->  y = 1/(e^{-x} + k)
    y = lambda x, k=C + 5: 1 / (math.exp(-x) + k)
    check("separable", y, lambda y, x: d(y, x) - y(x) ** 2 * math.exp(-x), lambda x: 0)
    # y' + y = x  ->  y = x - 1 + C e^{-x}
    check("ex1", lambda x, C=C: x - 1 + C * math.exp(-x), lambda y, x: d(y, x) + y(x), lambda x: x)
    # y' + 2y = 5  ->  y = 5/2 + C e^{-2x}
    check("ex2", lambda x, C=C: 2.5 + C * math.exp(-2 * x), lambda y, x: d(y, x) + 2 * y(x), lambda x: 5)
    # y' + y = x^2  ->  y = x^2 - 2x + 2 + C e^{-x}
    check("ex3", lambda x, C=C: x * x - 2 * x + 2 + C * math.exp(-x), lambda y, x: d(y, x) + y(x), lambda x: x * x)

# RC 회로 dv/dt + v/RC = vs/RC, vs = 1 (t>=0), v(0)=0  ->  v = 1 - e^{-t/RC}
RC, dt, v, t = 0.5, 1e-5, 0.0, 0.0
while t < 2.0 - 1e-12:
    v += dt * (1 - v) / RC
    t += dt
assert abs(v - (1 - math.exp(-2.0 / RC))) < 1e-4
# 시상수 RC가 지나면 최종값의 약 63%
assert abs((1 - math.exp(-1)) - 0.632) < 1e-3
print("ALL CHECKS PASSED")