First-order differential equations are the most fundamental and widely used type of differential equations. From compound interest calculations to drug metabolism, from chemical reactions to circuit analysis, first-order ODEs are everywhere. Mastering the techniques for solving these equations forms the foundation for understanding more complex systems.
Separable Equations: The Most Natural Form
What Is a Separable Equation?
Consider the general form of a first-order ODE:
Core idea: Move all terms containing
Classic Example: Exponential Growth and Decay
Example 1: Solve
Solution: This is a separable equation with
Separating variables:
Physical interpretation: -
1 | import numpy as np |
Compound Interest Problem
Scenario: You deposit
Modeling: Let
Example calculation: Deposit$10,000 with 5% annual interest rate
1 | def compound_interest(): |
Key insight:
| Time | Yearly Compounding | Continuous Compounding | Difference |
|---|---|---|---|
| 10 years | $16,288.95 | $16,487.21 | $198.26 |
| 30 years | $43,219.42 | $44,816.89 | $1,597.47 |
Continuous compounding seems to yield only slightly more interest,
but over the long term, the difference becomes significant. This is the
magic of
Drug Metabolism: The Half-Life Concept
Background: You take a pill, and your body metabolizes the drug at a constant rate. How long until the effect is halved?
Model: Let
Solution:
Example: Ibuprofen has a half-life of about 2 hours. If you initially take 400mg:
1 | def drug_metabolism(): |
Clinical significance: - Typically after 3-5 half-lives, the drug is almost completely metabolized - Dosing intervals are usually designed based on half-life - Ibuprofen: Take every 4-6 hours (about 2-3 half-lives)
Logistic Equation: Growth Under Resource Constraints
Problem with Malthusian model: Exponential
growth
Improvement: Pierre Fran ç ois Verhulst (1838)
proposed the Logistic model
Intuition: - When
Solution: This is a separable equation1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45def logistic_growth():
K = 1000 # Carrying capacity
r = 0.3 # Growth rate
t = np.linspace(0, 30, 300)
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# Logistic curves with different initial values
P0_values = [10, 50, 100, 500, 1200]
colors = plt.cm.viridis(np.linspace(0, 1, len(P0_values)))
for P0, color in zip(P0_values, colors):
P = K / (1 + (K/P0 - 1) * np.exp(-r * t))
axes[0].plot(t, P, color=color, linewidth=2, label=f'P ₀ = {P0}')
axes[0].axhline(y=K, color='red', linestyle='--', linewidth=2, label=f'K = {K}')
axes[0].set_xlabel('Time', fontsize=12)
axes[0].set_ylabel('Population', fontsize=12)
axes[0].set_title('Logistic Growth: Different Initial Conditions', fontsize=14, fontweight='bold')
axes[0].legend()
axes[0].grid(True, alpha=0.3)
# Growth rate vs population
P_range = np.linspace(0, 1.5 * K, 200)
dP_dt = r * P_range * (1 - P_range / K)
axes[1].plot(P_range, dP_dt, 'b-', linewidth=2.5)
axes[1].axvline(x=K/2, color='green', linestyle='--', label='Maximum growth at P = K/2')
axes[1].axvline(x=K, color='red', linestyle='--', label='Carrying capacity K')
axes[1].axhline(y=0, color='black', linewidth=0.5)
axes[1].fill_between(P_range[P_range <= K], dP_dt[P_range <= K], alpha=0.3, color='blue')
axes[1].fill_between(P_range[P_range > K], dP_dt[P_range > K], alpha=0.3, color='red')
axes[1].set_xlabel('Population P', fontsize=12)
axes[1].set_ylabel('Growth Rate dP/dt', fontsize=12)
axes[1].set_title('Growth Rate vs Population', fontsize=14, fontweight='bold')
axes[1].legend()
axes[1].grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('fig4_logistic.png', dpi=150, bbox_inches='tight')
plt.close()
logistic_growth()
Characteristics of the S-shaped curve:
Inflection point: Maximum growth rate at
Asymptote:
(never exceeds by much)Symmetry: Symmetric about the inflection point
Real-world applications: - Bacterial growth in a petri dish - Technology adoption curves - Epidemic spread (early stages) - Market saturation models
First-Order Linear Equations: Integrating Factor Method
Standard Form
The standard form of a first-order linear ODE:
Characteristic: Both
Motivation for the Integrating Factor Method
Consider the derivative of a product:
Condition: Comparing coefficients, we need
General Solution Formula
Multiply both sides of the original equation by
General solution:
Detailed Example
Example 2: Solve
Multiply by integrating factor:
Integrate:
General solution:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28def linear_ode_example():
x = np.linspace(-3, 3, 300)
fig, ax = plt.subplots(figsize=(10, 6))
# Solution curves for different C values
C_values = [-2, -1, -0.5, 0, 0.5, 1, 2]
colors = plt.cm.coolwarm(np.linspace(0, 1, len(C_values)))
for C, color in zip(C_values, colors):
y = 0.5 + C * np.exp(-x**2)
ax.plot(x, y, color=color, linewidth=2, label=f'C = {C}')
# Equilibrium solution
ax.axhline(y=0.5, color='black', linestyle='--', linewidth=2, label='Equilibrium y = 1/2')
ax.set_xlabel('x', fontsize=12)
ax.set_ylabel('y', fontsize=12)
ax.set_title("Solution Family: y' + 2xy = x", fontsize=14, fontweight='bold')
ax.legend(loc='upper right')
ax.grid(True, alpha=0.3)
ax.set_ylim(-2, 3)
plt.tight_layout()
plt.savefig('fig5_linear_ode.png', dpi=150, bbox_inches='tight')
plt.close()
linear_ode_example()
Observation: All solution curves approach the
equilibrium solution
RC Circuit: A Classic Application of First-Order Linear ODEs
Scenario: A resistor
Circuit equation (Kirchhoff's voltage law):
Case 1: Constant voltage source
Integrating factor:
Physical interpretation: - Capacitor voltage
exponentially approaches
1 | def rc_circuit(): |
Exact Equations and Integrating Factors
What Is an Exact Equation?
Consider an equation of the form
Test for exactness:
Solving Exact Equations
If the equation is exact, the general solution is
Steps: 1. Verify$ =
Find
General solution:
Making Equations Exact: Integrating Factors
When an equation is not exact (
Special case 1:
Requires
Then:
Special case 2:
Requires
Then:
Bernoulli Equations
Form and Reduction
Bernoulli equation:
Technique: Make the substitution
Let
Mixing Problems: Salt in a Tank
Problem Setup
A 1000-liter tank initially contains pure water. Salt water with concentration 2 g/L flows in at 5 L/min, and the mixed solution flows out at 5 L/min. Find the amount of salt at any time.
Modeling
Let
Inflow rate of salt:
Outflow rate of salt:
(because outflow concentration = current tank concentration =
Differential equation:
Initial condition:
Solution
This is a first-order linear equation. Rearranging to standard
form:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40def salt_tank():
t = np.linspace(0, 1500, 300)
Q = 2000 * (1 - np.exp(-t / 200))
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# Salt amount over time
axes[0].plot(t, Q, 'b-', linewidth=2.5, label='Salt Amount Q(t)')
axes[0].axhline(y=2000, color='red', linestyle='--', linewidth=2, label='Equilibrium = 2000g')
# Mark key moments
for t_mark in [200, 400, 600, 1000]:
Q_mark = 2000 * (1 - np.exp(-t_mark / 200))
axes[0].plot(t_mark, Q_mark, 'ko', markersize=6)
axes[0].annotate(f't={t_mark}min\nQ={Q_mark:.0f}g',
xy=(t_mark, Q_mark), xytext=(t_mark+50, Q_mark-200),
fontsize=9)
axes[0].set_xlabel('Time (minutes)', fontsize=12)
axes[0].set_ylabel('Salt Amount (grams)', fontsize=12)
axes[0].set_title('Salt Tank Problem', fontsize=14, fontweight='bold')
axes[0].legend()
axes[0].grid(True, alpha=0.3)
# Concentration change
C = Q / 1000 # g/L
axes[1].plot(t, C, 'g-', linewidth=2.5, label='Concentration C(t)')
axes[1].axhline(y=2, color='red', linestyle='--', linewidth=2, label='Inlet Concentration = 2 g/L')
axes[1].set_xlabel('Time (minutes)', fontsize=12)
axes[1].set_ylabel('Concentration (g/L)', fontsize=12)
axes[1].set_title('Salt Concentration Over Time', fontsize=14, fontweight='bold')
axes[1].legend()
axes[1].grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('fig7_salt_tank.png', dpi=150, bbox_inches='tight')
plt.close()
salt_tank()
Key insights: - Salt amount approaches 2000g
(concentration approaches 2 g/L, equal to inlet concentration) - Time
constant
Variation: Changing Tank Volume
If inflow rate
Example: Inflow 6 L/min (2 g/L), outflow 4 L/min, initial 500L pure water.
Volume:
Differential equation:
Existence and Uniqueness Theorem
Picard-Lindel ö f Theorem
Theorem: Consider the initial value problem
Then a unique solution exists near
Why Is This Important?
Positive side: Tells us when we can safely solve the equation
Negative side: When conditions are not met, we may have: - No solution - Infinitely many solutions - Solution exists only on a finite interval
Example 5:
1 | def non_unique_solution(): |
Introduction to Numerical Methods
Euler's Method
Idea: Approximate the curve with tangent lines
Geometric interpretation: Starting from
1 | def euler_method_demo(): |
Error analysis: - Local truncation
error:
Euler's method is a first-order method.
Improved Euler Method (Heun's Method)
Idea: Use the average of slopes$
$
Fourth-Order Runge-Kutta Method (RK4)
The most commonly used numerical method:$
$
Global error:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53def rk4_comparison():
def f(x, y):
return y
def euler(f, x0, y0, h, n_steps):
x, y = [x0], [y0]
for _ in range(n_steps):
y.append(y[-1] + h * f(x[-1], y[-1]))
x.append(x[-1] + h)
return np.array(x), np.array(y)
def rk4(f, x0, y0, h, n_steps):
x, y = [x0], [y0]
for _ in range(n_steps):
k1 = f(x[-1], y[-1])
k2 = f(x[-1] + h/2, y[-1] + h*k1/2)
k3 = f(x[-1] + h/2, y[-1] + h*k2/2)
k4 = f(x[-1] + h, y[-1] + h*k3)
y.append(y[-1] + h/6 * (k1 + 2*k2 + 2*k3 + k4))
x.append(x[-1] + h)
return np.array(x), np.array(y)
h = 0.2
n_steps = 10
x_euler, y_euler = euler(f, 0, 1, h, n_steps)
x_rk4, y_rk4 = rk4(f, 0, 1, h, n_steps)
x_exact = np.linspace(0, 2, 200)
y_exact = np.exp(x_exact)
fig, ax = plt.subplots(figsize=(10, 6))
ax.plot(x_exact, y_exact, 'b-', linewidth=2.5, label='Exact')
ax.plot(x_euler, y_euler, 'r--o', linewidth=2, markersize=6, label='Euler')
ax.plot(x_rk4, y_rk4, 'g-s', linewidth=2, markersize=6, label='RK4')
ax.set_xlabel('x', fontsize=12)
ax.set_ylabel('y', fontsize=12)
ax.set_title(f'Euler vs RK4 (h = {h})', fontsize=14, fontweight='bold')
ax.legend()
ax.grid(True, alpha=0.3)
# Display errors
euler_error = np.abs(y_euler[-1] - np.exp(2))
rk4_error = np.abs(y_rk4[-1] - np.exp(2))
ax.text(0.5, 5, f'Euler error: {euler_error:.4f}\nRK4 error: {rk4_error:.6f}',
fontsize=11, bbox=dict(boxstyle='round', facecolor='wheat'))
plt.tight_layout()
plt.savefig('fig10_rk4.png', dpi=150, bbox_inches='tight')
plt.close()
rk4_comparison()
Python Practice: Comprehensive Applications
Solving ODEs with SciPy
1 | from scipy.integrate import solve_ivp |
Direction Field Visualization
1 | def plot_direction_field(f, x_range, y_range, ax=None, density=20): |
Summary
In this chapter, we systematically studied the main types of first-order differential equations and their solution methods:
| Type | Standard Form | Solution Method |
|---|---|---|
| Separable | Separate variables and integrate | |
| First-order linear | Integrating factor |
|
| Exact | Find potential function |
|
| Bernoulli | Substitution |
Application areas: - Compound interest and investments (exponential growth) - Drug metabolism (exponential decay) - Population dynamics (Logistic equation) - Circuit analysis (RC circuits) - Chemical reactions (mixing problems)
Numerical methods: - Euler's method: Simple but low accuracy - RK4 method: Most commonly used in engineering - SciPy: Modern Python tools
Exercises
Basic Problems
Solve the separable equation
, .Solve the linear equation
.Determine if
is exact. If not, find an integrating factor.A pool initially has 1000 liters of water containing 50kg of salt. Pure water flows in at 10 L/min, mixed solution flows out at 10 L/min. Find
.In an RC circuit with
, , initial capacitor voltage is 0, connected to a 10V source. Find .
Advanced Problems
Solve the Bernoulli equation
.Prove: For equations of the form
, letting converts it to a separable equation.Discuss the existence and uniqueness of solutions for
, .Bacteria count satisfies the Logistic equation
, . Find:- Expression for
- When is ? - Time of maximum growth
- Expression for
Solve the equation
(Hint: use polar coordinates)
Programming Problems
Implement the improved Euler method (Heun's method) in Python and compare accuracy with Euler's method.
Plot the direction field for the Logistic equation with solution curves for different initial values.
Simulate continuous medication: Take 500mg every 6 hours, half-life is 4 hours. Plot the blood drug concentration curve.
Implement adaptive step-size RK45 and compare efficiency with fixed step-size methods.
References
- Boyce, W. E., & DiPrima, R. C. (2012). Elementary Differential Equations and Boundary Value Problems. Wiley.
- Zill, D. G. (2017). A First Course in Differential Equations with Modeling Applications. Cengage.
- Edwards, C. H., & Penney, D. E. (2014). Differential Equations and Boundary Value Problems. Pearson.
- SciPy Documentation: scipy.integrate
Next Chapter Preview: Higher-Order Linear Differential Equations — Spring oscillations, RLC circuits, resonance phenomena
- Post title:Ordinary Differential Equations (2): First-Order Equations
- Post author:Chen Kai
- Create time:2019-04-08 14:30:00
- Post link:https://www.chenk.top/ode-chapter-02-first-order-methods/
- Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.