ode-solver
Solve ordinary differential equations (initial and boundary value problems). Supports stiff/non-stiff systems, event detection, Hamiltonian/symplectic integration, parameter sweeps, and phase space analysis. Use for any ODE system in physics, engineering, or applied math.
- License 许可
- MIT
- 最近更新
- 2026-10-28
- Stars
- ★ 0
- Forks
- 0
01 前言 Front Matter
- name
- ode-solver
- tags
- [ "ODE", "Differential Equations", "Simulation", "Dynamics", "Physics", "IVP", "BVP" ]
- author
- Synthetic Sciences
- license
- MIT
- version
- 1.0.0
- category
- physics
- description
- Solve ordinary differential equations (initial and boundary value problems). Supports stiff/non-stiff systems, event detection, Hamiltonian/symplectic integration, parameter sweeps, and phase space analysis. Use for any ODE system in physics, engineering, or applied math.
- dependencies
- [ "scipy>=1.11.0", "numpy>=1.24.0", "matplotlib>=3.7.0" ]
03 SKILL.md 正文
ODE Solver
Overview
Solve systems of ordinary differential equations using scipy's battle-tested integrators. Covers initial value problems (IVP), boundary value problems (BVP), event detection, stiff systems, and Hamiltonian dynamics with symplectic integrators.
When to Use
- Any initial value problem: dx/dt = f(t, x)
- Boundary value problems: solve with constraints at two endpoints
- Hamiltonian systems needing energy-conserving integration
- Parameter sweeps over ODE systems
- Systems with discrete events (bouncing ball, switching dynamics)
Do NOT Use When
- Solving PDEs (use
pde-solverorfluidsim) - Fitting ODE parameters to data (use
physics-fitting, then come back here) - Discovering governing equations from data (use
symbolic-regressionorsindy)
Core Workflows
1. Basic IVP (Initial Value Problem)
import numpy as np
from scipy.integrate import solve_ivp
import matplotlib.pyplot as plt
# Define the system: dy/dt = f(t, y)
def harmonic_oscillator(t, y, omega=2.0):
"""Simple harmonic oscillator: x'' + omega^2 * x = 0"""
x, v = y
return [v, -omega**2 * x]
# Solve
t_span = (0, 10)
y0 = [1.0, 0.0] # x(0)=1, v(0)=0
sol = solve_ivp(harmonic_oscillator, t_span, y0,
method='RK45', t_eval=np.linspace(0, 10, 1000),
rtol=1e-10, atol=1e-12)
# Plot
plt.plot(sol.t, sol.y[0], label='x(t)')
plt.plot(sol.t, sol.y[1], label='v(t)')
plt.xlabel('Time [s]')
plt.ylabel('State')
plt.legend()
plt.grid(True, alpha=0.3)
plt.savefig('harmonic_oscillator.png', dpi=150, bbox_inches='tight')
2. Stiff Systems
Use method='Radau' or method='BDF' for stiff problems:
def stiff_system(t, y):
"""Van der Pol oscillator (stiff for large mu)"""
mu = 1000 # stiffness parameter
x, v = y
return [v, mu * (1 - x**2) * v - x]
sol = solve_ivp(stiff_system, (0, 3000), [2.0, 0.0],
method='Radau', rtol=1e-8, atol=1e-10,
max_step=10.0)
How to detect stiffness:
- Explicit solver (RK45) takes extremely many steps or fails
- System has widely separated timescales
- Jacobian eigenvalues have large negative real parts
3. Event Detection
Find when specific conditions are met during integration:
def projectile(t, y):
"""Projectile motion with drag"""
x, vx, z, vz = y
g = 9.80665
drag = 0.01 # drag coefficient
speed = np.sqrt(vx**2 + vz**2)
return [vx, -drag * speed * vx,
vz, -g - drag * speed * vz]
def hit_ground(t, y):
"""Event: z = 0 (projectile hits ground)"""
return y[2]
hit_ground.terminal = True # stop integration
hit_ground.direction = -1 # only when z is decreasing
def max_height(t, y):
"""Event: vz = 0 (apex)"""
return y[3]
max_height.direction = -1
sol = solve_ivp(projectile, (0, 100), [0, 50, 0, 50],
events=[hit_ground, max_height],
max_step=0.1, dense_output=True)
print(f"Impact at t = {sol.t_events[0][0]:.3f} s")
print(f"Max height at t = {sol.t_events[1][0]:.3f} s")
4. Hamiltonian Systems (Symplectic Integration)
For energy-conserving systems, use symplectic methods:
def symplectic_leapfrog(H_q, H_p, q0, p0, dt, n_steps):
"""
Leapfrog (Stormer-Verlet) symplectic integrator.
H_q = dH/dq (returns -dp/dt)
H_p = dH/dp (returns dq/dt)
"""
q = np.copy(q0)
p = np.copy(p0)
trajectory = [(q.copy(), p.copy())]
for _ in range(n_steps):
p -= 0.5 * dt * H_q(q, p) # half-step momentum
q += dt * H_p(q, p) # full-step position
p -= 0.5 * dt * H_q(q, p) # half-step momentum
trajectory.append((q.copy(), p.copy()))
return trajectory
# Example: Kepler problem
def dH_dq(q, p):
r = np.linalg.norm(q)
return q / r**3 # gravitational force (GM=1)
def dH_dp(q, p):
return p # velocity
q0 = np.array([1.0, 0.0]) # initial position
p0 = np.array([0.0, 0.8]) # initial velocity (elliptical orbit)
traj = symplectic_leapfrog(dH_dq, dH_dp, q0, p0, dt=0.01, n_steps=10000)
5. Boundary Value Problems (BVP)
from scipy.integrate import solve_bvp
def ode_bvp(x, y):
"""y'' + y = 0 (eigenvalue-like problem)"""
return np.vstack([y[1], -y[0]])
def boundary_conditions(ya, yb):
"""y(0) = 0, y(pi) = 0"""
return np.array([ya[0], yb[0]])
x = np.linspace(0, np.pi, 100)
y_init = np.zeros((2, x.size))
y_init[0] = np.sin(x) # initial guess
sol = solve_bvp(ode_bvp, boundary_conditions, x, y_init)
print(f"BVP solved: {sol.success}")
6. Parameter Sweeps
from functools import partial
def damped_oscillator(t, y, gamma=0.1, omega=1.0):
x, v = y
return [v, -2*gamma*v - omega**2 * x]
gammas = [0.05, 0.1, 0.5, 1.0, 2.0]
fig, ax = plt.subplots(figsize=(10, 6))
for gamma in gammas:
rhs = partial(damped_oscillator, gamma=gamma)
sol = solve_ivp(rhs, (0, 20), [1.0, 0.0],
t_eval=np.linspace(0, 20, 500), rtol=1e-10)
label = f'γ={gamma}'
if gamma < 1:
label += ' (underdamped)'
elif gamma == 1:
label += ' (critical)'
else:
label += ' (overdamped)'
ax.plot(sol.t, sol.y[0], label=label)
ax.set_xlabel('Time [s]')
ax.set_ylabel('x(t)')
ax.set_title('Damped Harmonic Oscillator: Parameter Sweep')
ax.legend()
ax.grid(True, alpha=0.3)
plt.savefig('damped_sweep.png', dpi=150, bbox_inches='tight')
Method Selection Guide
| Problem Type | Method | When to Use |
|---|---|---|
RK45 |
Non-stiff, general purpose | Default choice |
RK23 |
Non-stiff, lower accuracy | Quick estimates |
DOP853 |
Non-stiff, high accuracy | Long integrations, reference solutions |
Radau |
Stiff, implicit Runge-Kutta | Chemical kinetics, electrical circuits |
BDF |
Stiff, multistep | Large stiff systems |
LSODA |
Auto stiff/non-stiff detection | Unknown stiffness |
| Leapfrog/Verlet | Symplectic | Hamiltonian systems, long-time energy conservation |
Validation Checklist
After solving any ODE:
- [ ] Check energy/invariant conservation (for conservative systems)
- [ ] Verify against analytical solution in known limits
- [ ] Confirm convergence: halve
max_stepand check solution doesn't change - [ ] Check
sol.successis True andsol.messageis clean - [ ] For stiff systems: verify
method='Radau'or'BDF'was used - [ ] Plot residuals if fitting to data
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
| Very slow integration | Stiff system with explicit solver | Switch to Radau or BDF |
max_step warnings |
Step size too large | Reduce max_step |
| Energy drift over long times | Non-symplectic integrator | Use leapfrog for Hamiltonian systems |
| Solution oscillates wildly | Insufficient resolution | Decrease rtol/atol |
solve_ivp returns success=False |
Integration failed | Check if system is stiff, reduce tolerances |
| Event not detected | Event function not smooth | Add max_step smaller than event timescale |
04 同仓库更多 Skills
statistical-power
Sample size calculation, power analysis, and effect size conversion for scientific studies. Use BEFORE data collection (a priori) to determine required N, or after (post-hoc) to compute achieved power. Covers parametric tests (t-test, ANOVA, chi-square, proportions, correlation, regression), simulation-based power for complex/clustered/nested designs, and power curves. Use this skill when someone asks 'how many samples do I need', 'what is my power', 'what effect size can I detect', or any variant. Pairs with /experimental-design (choose design first, then compute power) and /statistical-analysis (analyze data after collection).
statistical-analysis
Guided statistical analysis with test selection and reporting. Use when you need help choosing appropriate tests for your data, assumption checking, power analysis, and APA-formatted results. Best for academic research reporting, test selection guidance. For implementing specific models programmatically use statsmodels.
scientific-writing
Core skill for the deep research and writing tool. Write scientific manuscripts in full paragraphs (never bullet points). Use two-stage process with (1) section outlines with key points using research-lookup then (2) convert to flowing prose. IMRAD structure, citations (APA/AMA/Vancouver), figures/tables, reporting guidelines (CONSORT/STROBE/PRISMA), for research papers and journal submissions.
scientific-visualization
Meta-skill for publication-ready figures. Use when creating journal submission figures requiring multi-panel layouts, significance annotations, error bars, colorblind-safe palettes, and specific journal formatting (Nature, Science, Cell). Orchestrates matplotlib/seaborn/plotly with publication styles. For quick exploration use seaborn or plotly directly.
research-code
Debug, profile, review, and restructure Python research and analysis code. Use when analysis scripts crash, produce wrong results, run too slowly, or need a correctness review. Covers: reading tracebacks and diagnosing root causes, hypothesis-driven debugging, reviewing code for common statistical/numerical errors, profiling data pipelines, improving reproducibility (seeds, environments, determinism), and structuring analysis scripts for sharing. Distinct from /exploratory-data-analysis (which understands data) and /statistical-analysis (which chooses and runs tests) — this skill focuses on the code itself.
markdown-mermaid-writing
Comprehensive markdown and Mermaid diagram writing skill. Use when creating any scientific document, report, analysis, or visualization. Establishes text-based diagrams as the default documentation standard with full style guides (markdown + mermaid), 24 diagram type references, and 9 document templates.