はじめに
物理学や工学の世界では、「ある量が時間とともにどのように変化するか」を記述する場面が数多く登場します。ニュートンの運動方程式、電気回路の電圧・電流の関係、化学反応の濃度変化――これらはすべて 微分方程式 によって記述されます。
本記事では、微分方程式とは何か、どのように分類されるのかを丁寧に解説し、物理・工学での具体例を紹介します。最後に Python を使って微分方程式を数値的に解く方法も示します。
前提知識
この記事を読む前に、以下の記事を読んでおくと理解が深まります。
微分方程式とは何か
微分方程式とは、未知関数とその導関数(微分)を含む等式 のことです。
たとえば、未知関数 $y(x)$ に対して
$$ \frac{dy}{dx} = ky $$
という関係が成り立つとき、これは微分方程式です。ここで $k$ は定数です。この式は「$y$ の変化率が $y$ 自身に比例する」ことを意味しており、人口増加や放射性崩壊のモデルとして広く用いられます。
ポイントは、未知なのは 数値 ではなく 関数 だという点です。代数方程式 $2x + 3 = 0$ の解は数 $x = -3/2$ ですが、微分方程式の解は関数 $y(x) = Ce^{kx}$($C$ は任意定数)のように関数の形で得られます。
なぜ微分方程式が重要か
自然界の法則の多くは、ある物理量の 変化率 に関する法則として表現されます。
- ニュートンの第2法則: 力は質量と加速度の積 → $F = m\ddot{x}$(位置の2階微分)
- フックの法則 + 減衰: バネと減衰の復元力 → $m\ddot{x} + c\dot{x} + kx = 0$
- オームの法則 + キャパシタ: RC回路の過渡応答 → $RC\dot{v} + v = V_0$
- 放射性崩壊: 崩壊率が現在量に比例 → $dN/dt = -\lambda N$
つまり、微分方程式を解くことは、自然現象の時間発展や空間分布を予測すること に直結します。これが微分方程式を学ぶ最大の理由です。
常微分方程式(ODE)と偏微分方程式(PDE)の違い
微分方程式は、含まれる独立変数の数によって大きく2つに分類されます。
常微分方程式(ODE: Ordinary Differential Equation)
未知関数が 1つの独立変数 のみに依存する場合の微分方程式です。
$$ m\frac{d^2 x}{dt^2} = -mg $$
ここでは未知関数 $x(t)$ は時間 $t$ のみに依存しています。
偏微分方程式(PDE: Partial Differential Equation)
未知関数が 複数の独立変数 に依存する場合の微分方程式です。
$$ \frac{\partial u}{\partial t} = \alpha \frac{\partial^2 u}{\partial x^2} $$
これは熱伝導方程式であり、未知関数 $u(x, t)$ は位置 $x$ と時間 $t$ の2つの独立変数に依存しています。偏微分 $\partial$ が登場するのが特徴です。
本記事シリーズでは、まず常微分方程式(ODE)に焦点を当てて解説を進めます。
階数による分類
微分方程式に含まれる 最高階の導関数の次数 を、その微分方程式の 階数(order) と呼びます。
1階の微分方程式
$$ \frac{dy}{dx} = f(x, y) $$
未知関数の1階導関数 $dy/dx$ が最高階の導関数です。
2階の微分方程式
$$ \frac{d^2 y}{dx^2} + p(x)\frac{dy}{dx} + q(x)y = g(x) $$
未知関数の2階導関数 $d^2y/dx^2$ が最高階です。振動やバネ-マスダンパ系の方程式はこの形をしています。
n階の微分方程式
一般に $n$ 階の微分方程式は次のように表されます。
$$ F\!\left(x,\, y,\, \frac{dy}{dx},\, \frac{d^2 y}{dx^2},\, \dots,\, \frac{d^n y}{dx^n}\right) = 0 $$
実用上は1階と2階が最も頻繁に登場します。
線形と非線形の違い
微分方程式の分類でもう1つ重要なのが、線形か非線形か という区別です。
線形微分方程式
未知関数 $y$ とその導関数が 1次の項としてのみ 現れる(積や累乗がない)微分方程式を線形と呼びます。一般的な $n$ 階線形微分方程式は次の形をしています。
$$ a_n(x)\frac{d^n y}{dx^n} + a_{n-1}(x)\frac{d^{n-1} y}{dx^{n-1}} + \cdots + a_1(x)\frac{dy}{dx} + a_0(x)y = g(x) $$
係数 $a_i(x)$ は $x$ の関数であってもよいですが、$y$ やその導関数に依存してはなりません。
非線形微分方程式
$y$ やその導関数の積、累乗、三角関数などが含まれる場合は非線形です。
$$ \frac{dy}{dx} = y^2 \quad \text{(非線形: } y \text{ の2乗が含まれる)} $$
$$ \frac{d^2 \theta}{dt^2} + \frac{g}{L}\sin\theta = 0 \quad \text{(非線形: } \sin\theta \text{ が含まれる)} $$
2番目の例は振り子の運動方程式です。$\sin\theta \approx \theta$ と近似すれば線形になりますが、厳密には非線形です。
線形微分方程式は 重ね合わせの原理 が成り立つため、解の構造が明確で解析しやすいという利点があります。
一般解と特殊解、初期条件
一般解
微分方程式の解のうち、任意定数を含む最も一般的な形 の解を 一般解 と呼びます。
$n$ 階の微分方程式の一般解には、通常 $n$ 個の任意定数が含まれます。たとえば、2階の微分方程式
$$ \frac{d^2 y}{dx^2} = 0 $$
の一般解は
$$ y = C_1 x + C_2 $$
です。ここで $C_1, C_2$ は任意定数です。
特殊解(特解)
一般解の任意定数に具体的な値を代入して得られる解を 特殊解 と呼びます。上の例で $C_1 = 2,\ C_2 = 3$ とすれば、$y = 2x + 3$ が特殊解の1つです。
初期条件と初期値問題
任意定数を決定するために与える条件を 初期条件(または境界条件)と呼びます。$n$ 階の微分方程式には $n$ 個の初期条件が必要です。
たとえば1階の微分方程式
$$ \frac{dy}{dx} = ky, \quad y(0) = y_0 $$
の場合、初期条件 $y(0) = y_0$ から任意定数が $C = y_0$ と決まり、特殊解
$$ y(x) = y_0 e^{kx} $$
が得られます。微分方程式と初期条件をセットにしたものを 初期値問題(IVP: Initial Value Problem) と呼びます。
物理・工学での具体例
例1: 自由落下
質量 $m$ の物体が重力のみを受けて落下する場合、ニュートンの運動方程式は
$$ m\ddot{x} = -mg $$
です。ここで $x$ は鉛直上向きを正とした位置、$g$ は重力加速度です。両辺を $m$ で割ると
$$ \ddot{x} = -g $$
となります。これは2階の線形常微分方程式であり、2回積分することで一般解が得られます。
$$ \dot{x} = -gt + C_1 $$
$$ x = -\frac{1}{2}gt^2 + C_1 t + C_2 $$
初期条件 $x(0) = x_0$(初期位置)、$\dot{x}(0) = v_0$(初速度)を与えると
$$ x(t) = -\frac{1}{2}gt^2 + v_0 t + x_0 $$
という、おなじみの放物運動の式が得られます。
例2: バネ-マスダンパ系
質量 $m$ の物体がバネ定数 $k$ のバネと減衰係数 $c$ のダンパに接続されている場合の運動方程式は
$$ m\ddot{x} + c\dot{x} + kx = 0 $$
です。これは2階の線形常微分方程式であり、$c$ の値に応じて 過減衰、臨界減衰、不足減衰(振動) の3パターンの解が得られます。この方程式は機械工学や制御工学で極めて重要です。
例3: RC回路
抵抗 $R$ とキャパシタ $C$ が直列に接続された回路に一定電圧 $V_0$ を印加したとき、キャパシタ両端の電圧 $v(t)$ に関する方程式は
$$ RC\dot{v} + v = V_0 $$
です。これは1階の線形常微分方程式です。初期条件 $v(0) = 0$(キャパシタが初期放電状態)のもとで解くと
$$ v(t) = V_0\!\left(1 – e^{-t/(RC)}\right) $$
が得られます。時定数 $\tau = RC$ によってキャパシタの充電速度が決まります。
1階変数分離形の解法
最も基本的な解法として、変数分離形 の微分方程式を解いてみましょう。
変数分離形とは
次の形に書ける微分方程式を変数分離形と呼びます。
$$ \frac{dy}{dx} = f(x)\,g(y) $$
右辺が $x$ のみの関数と $y$ のみの関数の積に分離できる場合です。
解法の手順
- 両辺を $g(y)$ で割り、$x$ と $y$ を左辺・右辺に分離します。
$$ \frac{1}{g(y)}\,dy = f(x)\,dx $$
- 両辺を積分します。
$$ \int \frac{1}{g(y)}\,dy = \int f(x)\,dx + C $$
- 積分を実行して $y$ について解きます。
具体例: $dy/dx = ky$
指数関数的増加・減衰を記述する微分方程式 $dy/dx = ky$ を解きます。
ステップ1: 変数を分離します。ここで $f(x) = k$、$g(y) = y$ です。
$$ \frac{1}{y}\,dy = k\,dx $$
ステップ2: 両辺を積分します。
$$ \int \frac{1}{y}\,dy = \int k\,dx $$
$$ \ln|y| = kx + C’ $$
ここで $C’$ は積分定数です。
ステップ3: 両辺の指数関数を取ります。
$$ |y| = e^{kx + C’} = e^{C’} e^{kx} $$
$C = \pm e^{C’}$ とまとめると、一般解は
$$ y = Ce^{kx} $$
となります。初期条件 $y(0) = y_0$ を与えると $C = y_0$ となり、特殊解
$$ y(x) = y_0 e^{kx} $$
が得られます。$k > 0$ のとき指数関数的増加、$k < 0$ のとき指数関数的減衰を表します。
Python による数値解法と可視化
微分方程式の解析解が求められない場合や、数値的に振る舞いを確認したい場合には、数値解法が有効です。Python の scipy.integrate.solve_ivp を使って、指数関数的増加と減衰の例を数値的に解き、可視化してみましょう。
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import solve_ivp
# --- dy/dx = ky の数値解法 ---
# 微分方程式の右辺を定義(solve_ivp の形式に合わせる)
def exponential_ode(t, y, k):
"""dy/dt = k * y"""
return k * y
# パラメータ設定
k_growth = 0.5 # 増加の場合の k
k_decay = -0.5 # 減衰の場合の k
y0 = [1.0] # 初期条件 y(0) = 1
t_span = (0, 10) # 解く区間
t_eval = np.linspace(0, 10, 200) # 出力する時刻
# 数値解を求める(増加)
sol_growth = solve_ivp(
exponential_ode,
t_span,
y0,
t_eval=t_eval,
args=(k_growth,),
method="RK45"
)
# 数値解を求める(減衰)
sol_decay = solve_ivp(
exponential_ode,
t_span,
y0,
t_eval=t_eval,
args=(k_decay,),
method="RK45"
)
# 解析解(比較用)
y_exact_growth = y0[0] * np.exp(k_growth * t_eval)
y_exact_decay = y0[0] * np.exp(k_decay * t_eval)
# --- 可視化 ---
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
# 指数関数的増加
axes[0].plot(sol_growth.t, sol_growth.y[0], "o", markersize=3, label="数値解 (solve_ivp)")
axes[0].plot(t_eval, y_exact_growth, "-", linewidth=2, label=f"解析解 $y = e^{{{k_growth}x}}$")
axes[0].set_xlabel("$x$", fontsize=13)
axes[0].set_ylabel("$y$", fontsize=13)
axes[0].set_title(f"指数関数的増加 ($k = {k_growth}$)", fontsize=14)
axes[0].legend(fontsize=11)
axes[0].grid(True, alpha=0.3)
# 指数関数的減衰
axes[1].plot(sol_decay.t, sol_decay.y[0], "o", markersize=3, label="数値解 (solve_ivp)")
axes[1].plot(t_eval, y_exact_decay, "-", linewidth=2, label=f"解析解 $y = e^{{{k_decay}x}}$")
axes[1].set_xlabel("$x$", fontsize=13)
axes[1].set_ylabel("$y$", fontsize=13)
axes[1].set_title(f"指数関数的減衰 ($k = {k_decay}$)", fontsize=14)
axes[1].legend(fontsize=11)
axes[1].grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig("ode_exponential.png", dpi=150, bbox_inches="tight")
plt.show()
print("=== 数値解と解析解の最大誤差 ===")
print(f"増加 (k={k_growth}): {np.max(np.abs(sol_growth.y[0] - y_exact_growth)):.2e}")
print(f"減衰 (k={k_decay}): {np.max(np.abs(sol_decay.y[0] - y_exact_decay)):.2e}")
このコードを実行すると、左のグラフに指数関数的増加($k = 0.5$)、右のグラフに指数関数的減衰($k = -0.5$)が描画されます。solve_ivp の数値解(マーカー)と解析解(実線)がほぼ完全に一致していることが確認できます。
solve_ivp は Runge-Kutta 法(デフォルトは RK45)を用いて微分方程式を数値的に解きます。引数の意味は以下のとおりです。
| 引数 | 説明 |
|---|---|
fun |
微分方程式の右辺 $f(t, y)$ を定義した関数 |
t_span |
独立変数の区間 $(t_0, t_f)$ |
y0 |
初期条件(リストまたは配列) |
t_eval |
解を出力する時刻の配列 |
args |
fun に渡す追加の引数(今回は $k$) |
method |
数値解法の種類("RK45", "RK23", "Radau" など) |
まとめ
本記事では、微分方程式の基本概念を整理しました。
- 微分方程式は 未知関数とその導関数の関係式 であり、解は関数として得られます。
- 常微分方程式(ODE) は独立変数が1つ、偏微分方程式(PDE) は複数の独立変数を持ちます。
- 微分方程式は 階数(最高階導関数の次数)と 線形性 によって分類されます。
- 一般解 は任意定数を含み、初期条件 を与えることで 特殊解 が決定されます。
- 自由落下、バネ-マスダンパ系、RC回路など、物理・工学の基本的な問題が微分方程式で記述されます。
- 最も基本的な解法として 変数分離法 を用い、$dy/dx = ky$ の解 $y = Ce^{kx}$ を導出しました。
- Python の
scipy.integrate.solve_ivpを用いて、微分方程式を数値的に解く方法を示しました。
次の記事では、より体系的に 1階線形常微分方程式の解法(積分因子法)と 2階定数係数線形常微分方程式の解法(特性方程式法)を解説します。微分方程式の豊かな世界をさらに深く探っていきましょう。