Ordinary Differential Equations in 2D
Numerical Integration with SciPy
In this session we move from 1D dynamics to planar systems \[\dot x=f(x,y;\,\theta),\qquad \dot y=g(x,y;\,\theta),\] where behavior can depend strongly on both the initial state \((x_0,y_0)\) and the parameters \(\theta\).
Case studies
Chlorine Dioxide–Iodine–Malonic Acid (CDIMA)
The CDIMA reaction is a classical example from chemical kinetics that can display rich nonlinear dynamics. We will use a reduced 2D model to explore how parameter changes can trigger qualitatively different behaviors (e.g., convergence to a steady state vs. sustained oscillations).
Van der Pol oscillator
The Van der Pol system is a prototypical self-excited oscillator: it exhibits a stable limit cycle for a wide range of initial conditions. It is a clean testbed for studying how nonlinear damping (controlled by a parameter) changes trajectories and transient dynamics.
FitzHugh–Nagumo
The FitzHugh–Nagumo model is a simplified neuron model capturing excitability and spiking. It’s a great example of a fast–slow 2D system, where parameters control whether trajectories relax to rest, fire spikes, or oscillate.
Goals
- Explore the evolution of the system depending on its initial state \((x_0,y_0)\).
- Study how solutions depend on equation parameters (bifurcation-style exploration).
- Build intuition using phase portraits, time series, and (simple) animations.
- Connect the simulations to the theory: oscillations/limit cycles, fast–slow dynamics, and excitability.
- Run the provided scripts and modify initial conditions/parameters to reproduce and explain the behaviors discussed in lecture.
What do we need?
scipy
We’ll use numerical integration to evolve the ODEs forward in time. In particular, we’ll rely on scipy.integrate.solve_ivp() which supports explicit Runge–Kutta methods (and many other solvers). Review session 1 for a refresher on how to use solve_ivp() for 1D ODEs, and we’ll extend that workflow to 2D systems here.
solve_ivp()
Core workflow:
- define the right-hand side \((f,g)\) as a Python function
- choose a time span and evaluation grid
- integrate with an RK method (or a stiff method when needed)
- analyze \((x(t),y(t))\) in time and in phase space
matplotlib.animation
To animate trajectories we update plot elements frame-by-frame (lines, markers, text), creating the illusion of motion. This is a lightweight way to visualize how trajectories “flow” through the phase plane.
matplotlib.pyplot
Used to initialize the figure/axes and draw static plot elements:
- axes labels, titles, legends
- nullclines or vector fields (when included)
- static phase portrait scaffolding
matplotlib.backend_bases
We’ll hook into Matplotlib’s event system (e.g. mouse clicks) to let the user interact with the model. For example, clicking in the phase plane can set a new initial condition \((x_0,y_0)\) and re-run the integration.
streamlit?
At the moment, animations and interactive plots are not implemented yet in Streamlit. For this reason, we will run the code in Python scripts for now.