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.